From 299bed1c05020277c323c912df06a20c8268f5bd Mon Sep 17 00:00:00 2001 From: arendst Date: Sun, 19 Nov 2017 18:02:03 +0100 Subject: [PATCH] v5.9.1f - Update libraries and a fix 5.9.1f * Upgrade library ArduinoJson to 5.11.2 * Upgrade library IRRemoteEsp8266 to 2.2.1 + 2 commits but tweaked some protocols to keep code usage small * Upgrade library NeoPixelBus to 2.2.9 * Upgrade library OneWire to 2.3.3 + 6 commits * Formalize library PubSubClient to 2.6 + 9 commits and additional delay * Add optional ADS1115 driver as alternative for unsupported I2Cdevlib in esp8266-core 2.4.0-rc2 * Fix wrong response name for command HlwISet (#1214) --- README.md | 2 +- .../ArduinoJson/ArduinoJson.h | 0 .../ArduinoJson/CHANGELOG.md | 0 .../ArduinoJson/CMakeLists.txt | 0 .../ArduinoJson/LICENSE.md | 0 .../ArduinoJson/README.md | 0 .../ArduinoJson/appveyor.yml | 0 .../IndentedPrintExample.ino | 0 .../JsonGeneratorExample.ino | 0 .../JsonHttpClient/JsonHttpClient.ino | 0 .../JsonParserExample/JsonParserExample.ino | 0 .../examples/JsonServer/JsonServer.ino | 0 .../examples/JsonUdpBeacon/JsonUdpBeacon.ino | 0 .../ProgmemExample/ProgmemExample.ino | 0 .../examples/StringExample/StringExample.ino | 0 .../ArduinoJson/fuzzing/Makefile | 0 .../ArduinoJson/fuzzing/fuzz.sh | 0 .../ArduinoJson/fuzzing/fuzzer.cpp | 0 .../ArduinoJson/fuzzing/my_corpus/.gitignore | 0 .../fuzzing/seed_corpus/ArduinoJson.json | 0 .../fuzzing/seed_corpus/OpenWeatherMap.json | 0 .../seed_corpus/WeatherUnderground.json | 0 .../ArduinoJson/include/ArduinoJson.h | 0 .../ArduinoJson/include/ArduinoJson.hpp | 0 .../include/ArduinoJson/Configuration.hpp | 0 .../include/ArduinoJson/Data/Encoding.hpp | 0 .../ArduinoJson/Data/JsonBufferAllocated.hpp | 0 .../include/ArduinoJson/Data/JsonFloat.hpp | 0 .../include/ArduinoJson/Data/JsonInteger.hpp | 0 .../ArduinoJson/Data/JsonVariantAs.hpp | 0 .../ArduinoJson/Data/JsonVariantComparer.hpp | 0 .../ArduinoJson/Data/JsonVariantContent.hpp | 0 .../ArduinoJson/Data/JsonVariantDefault.hpp | 0 .../ArduinoJson/Data/JsonVariantType.hpp | 0 .../include/ArduinoJson/Data/List.hpp | 0 .../ArduinoJson/Data/ListConstIterator.hpp | 0 .../include/ArduinoJson/Data/ListIterator.hpp | 0 .../include/ArduinoJson/Data/ListNode.hpp | 0 .../include/ArduinoJson/Data/Parse.hpp | 0 .../ArduinoJson/Data/ReferenceType.hpp | 0 .../include/ArduinoJson/Data/ValueSetter.hpp | 0 .../ArduinoJson/Deserialization/Comments.hpp | 0 .../Deserialization/JsonParser.hpp | 0 .../Deserialization/JsonParserImpl.hpp | 0 .../Deserialization/StringWriter.hpp | 0 .../include/ArduinoJson/DynamicJsonBuffer.hpp | 0 .../include/ArduinoJson/JsonArray.hpp | 0 .../include/ArduinoJson/JsonArrayImpl.hpp | 0 .../ArduinoJson/JsonArraySubscript.hpp | 0 .../include/ArduinoJson/JsonBuffer.hpp | 0 .../include/ArduinoJson/JsonBufferBase.hpp | 0 .../include/ArduinoJson/JsonBufferImpl.hpp | 0 .../include/ArduinoJson/JsonObject.hpp | 0 .../include/ArduinoJson/JsonObjectImpl.hpp | 0 .../ArduinoJson/JsonObjectSubscript.hpp | 0 .../include/ArduinoJson/JsonPair.hpp | 0 .../include/ArduinoJson/JsonVariant.hpp | 0 .../include/ArduinoJson/JsonVariantBase.hpp | 0 .../ArduinoJson/JsonVariantComparisons.hpp | 0 .../include/ArduinoJson/JsonVariantImpl.hpp | 0 .../ArduinoJson/Polyfills/attributes.hpp | 0 .../include/ArduinoJson/Polyfills/math.hpp | 0 .../ArduinoJson/Polyfills/normalize.hpp | 0 .../ArduinoJson/include/ArduinoJson/Print.hpp | 0 .../include/ArduinoJson/RawJson.hpp | 0 .../ArduinoJson/Serialization/DummyPrint.hpp | 0 .../Serialization/DynamicStringBuilder.hpp | 0 .../Serialization/IndentedPrint.hpp | 0 .../Serialization/JsonPrintable.hpp | 0 .../Serialization/JsonSerializer.hpp | 0 .../Serialization/JsonSerializerImpl.hpp | 0 .../ArduinoJson/Serialization/JsonWriter.hpp | 0 .../ArduinoJson/Serialization/Prettyfier.hpp | 0 .../Serialization/StaticStringBuilder.hpp | 0 .../Serialization/StreamPrintAdapter.hpp | 0 .../include/ArduinoJson/StaticJsonBuffer.hpp | 0 .../StringTraits/ArduinoStream.hpp | 0 .../ArduinoJson/StringTraits/CharPointer.hpp | 0 .../ArduinoJson/StringTraits/FlashString.hpp | 0 .../ArduinoJson/StringTraits/StdStream.hpp | 0 .../ArduinoJson/StringTraits/StdString.hpp | 0 .../ArduinoJson/StringTraits/StringTraits.hpp | 0 .../ArduinoJson/TypeTraits/EnableIf.hpp | 0 .../ArduinoJson/TypeTraits/IsArray.hpp | 0 .../ArduinoJson/TypeTraits/IsBaseOf.hpp | 0 .../include/ArduinoJson/TypeTraits/IsChar.hpp | 0 .../ArduinoJson/TypeTraits/IsConst.hpp | 0 .../TypeTraits/IsFloatingPoint.hpp | 0 .../ArduinoJson/TypeTraits/IsIntegral.hpp | 0 .../include/ArduinoJson/TypeTraits/IsSame.hpp | 0 .../TypeTraits/IsSignedIntegral.hpp | 0 .../TypeTraits/IsUnsignedIntegral.hpp | 0 .../ArduinoJson/TypeTraits/RemoveConst.hpp | 0 .../TypeTraits/RemoveReference.hpp | 0 .../ArduinoJson/keywords.txt | 0 .../ArduinoJson/library.json | 0 .../ArduinoJson/library.properties | 0 .../scripts/build-arduino-package.sh | 0 .../ArduinoJson/scripts/cpplint.sh | 0 .../ArduinoJson/scripts/create-build-envs.sh | 0 .../ArduinoJson/scripts/create-size-graph.sh | 0 .../ArduinoJson/scripts/format-code.sh | 0 .../ArduinoJson/scripts/oss-fuzz/.gitignore | 0 .../ArduinoJson/scripts/oss-fuzz/Vagrantfile | 0 .../ArduinoJson/scripts/run-tests.sh | 0 .../ArduinoJson/scripts/travis/arduino.sh | 0 .../ArduinoJson/scripts/travis/cmake.sh | 0 .../ArduinoJson/scripts/travis/coverage.sh | 0 .../ArduinoJson/scripts/travis/platformio.sh | 0 .../ArduinoJson/test/CMakeLists.txt | 0 .../ArduinoJson/test/Deprecated_Tests.cpp | 0 .../test/DynamicJsonBuffer_Array_Tests.cpp | 0 .../test/DynamicJsonBuffer_Basic_Tests.cpp | 0 .../test/DynamicJsonBuffer_NoMemory_Tests.cpp | 0 .../test/DynamicJsonBuffer_Object_Tests.cpp | 0 .../test/DynamicJsonBuffer_String_Tests.cpp | 0 .../ArduinoJson/test/GbathreeBug.cpp | 0 .../ArduinoJson/test/IntegrationTests.cpp | 0 .../ArduinoJson/test/Issue10.cpp | 0 .../ArduinoJson/test/Issue214.cpp | 0 .../ArduinoJson/test/Issue34.cpp | 0 .../ArduinoJson/test/Issue90.cpp | 0 .../ArduinoJson/test/JsonArray_Add_Tests.cpp | 0 .../test/JsonArray_Basic_Tests.cpp | 0 .../test/JsonArray_CopyFrom_Tests.cpp | 0 .../test/JsonArray_CopyTo_Tests.cpp | 0 .../test/JsonArray_Invalid_Tests.cpp | 0 .../test/JsonArray_Iterator_Tests.cpp | 0 .../test/JsonArray_PrettyPrintTo_Tests.cpp | 0 .../test/JsonArray_PrintTo_Tests.cpp | 0 .../test/JsonArray_Remove_Tests.cpp | 0 .../ArduinoJson/test/JsonArray_Set_Tests.cpp | 0 .../test/JsonArray_Subscript_Tests.cpp | 0 .../test/JsonObject_Basic_Tests.cpp | 0 .../test/JsonObject_ContainsKey_Tests.cpp | 0 .../ArduinoJson/test/JsonObject_Get_Tests.cpp | 0 .../test/JsonObject_Invalid_Tests.cpp | 0 .../test/JsonObject_Iterator_Tests.cpp | 0 .../test/JsonObject_PrettyPrintTo_Tests.cpp | 0 .../test/JsonObject_PrintTo_Tests.cpp | 0 .../test/JsonObject_Remove_Tests.cpp | 0 .../ArduinoJson/test/JsonObject_Set_Tests.cpp | 0 .../test/JsonObject_Subscript_Tests.cpp | 0 .../test/JsonParser_Array_Tests.cpp | 0 .../test/JsonParser_Nested_Tests.cpp | 0 .../test/JsonParser_NestingLimit_Tests.cpp | 0 .../test/JsonParser_Object_Tests.cpp | 0 .../test/JsonParser_Variant_Tests.cpp | 0 .../ArduinoJson/test/JsonVariant_As_Tests.cpp | 0 .../test/JsonVariant_Comparison_Tests.cpp | 0 .../test/JsonVariant_Copy_Tests.cpp | 0 .../ArduinoJson/test/JsonVariant_Is_Tests.cpp | 0 .../test/JsonVariant_PrintTo_Tests.cpp | 0 .../test/JsonVariant_Storage_Tests.cpp | 0 .../test/JsonVariant_Subscript_Tests.cpp | 0 .../test/JsonVariant_Success_Tests.cpp | 0 .../test/JsonVariant_Undefined_Tests.cpp | 0 .../test/JsonWriter_WriteFloat_Tests.cpp | 0 .../test/JsonWriter_WriteString_Tests.cpp | 0 .../test/StaticJsonBuffer_Basic_Tests.cpp | 0 .../StaticJsonBuffer_CreateArray_Tests.cpp | 0 .../StaticJsonBuffer_CreateObject_Tests.cpp | 0 .../StaticJsonBuffer_ParseArray_Tests.cpp | 0 .../StaticJsonBuffer_ParseObject_Tests.cpp | 0 .../test/StaticJsonBuffer_String_Tests.cpp | 0 .../ArduinoJson/test/StdStream_Tests.cpp | 0 .../ArduinoJson/test/StringBuilderTests.cpp | 0 .../ArduinoJson/test/String_Tests.cpp | 0 .../ArduinoJson/test/TypeTraits_Tests.cpp | 0 .../ArduinoJson/test/UnsignedChar_Tests.cpp | 0 .../test/VariableLengthArray_Tests.cpp | 0 .../ArduinoJson/test/gtest.cmake | 0 .../third-party/cpplint/cpplint.py | 0 .../third-party/gtest-1.7.0/CHANGES | 0 .../third-party/gtest-1.7.0/CMakeLists.txt | 0 .../third-party/gtest-1.7.0/CONTRIBUTORS | 0 .../third-party/gtest-1.7.0/LICENSE | 0 .../third-party/gtest-1.7.0/Makefile.am | 0 .../third-party/gtest-1.7.0/Makefile.in | 0 .../third-party/gtest-1.7.0/README | 0 .../third-party/gtest-1.7.0/aclocal.m4 | 0 .../gtest-1.7.0/build-aux/config.guess | 0 .../gtest-1.7.0/build-aux/config.h.in | 0 .../gtest-1.7.0/build-aux/config.sub | 0 .../third-party/gtest-1.7.0/build-aux/depcomp | 0 .../gtest-1.7.0/build-aux/install-sh | 0 .../gtest-1.7.0/build-aux/ltmain.sh | 0 .../third-party/gtest-1.7.0/build-aux/missing | 0 .../gtest-1.7.0/cmake/internal_utils.cmake | 0 .../gtest-1.7.0/codegear/gtest.cbproj | 0 .../gtest-1.7.0/codegear/gtest.groupproj | 0 .../gtest-1.7.0/codegear/gtest_all.cc | 0 .../gtest-1.7.0/codegear/gtest_link.cc | 0 .../gtest-1.7.0/codegear/gtest_main.cbproj | 0 .../codegear/gtest_unittest.cbproj | 0 .../third-party/gtest-1.7.0/configure | 0 .../third-party/gtest-1.7.0/configure.ac | 0 .../gtest-1.7.0/fused-src/gtest/gtest-all.cc | 0 .../gtest-1.7.0/fused-src/gtest/gtest.h | 0 .../gtest-1.7.0/fused-src/gtest/gtest_main.cc | 0 .../include/gtest/gtest-death-test.h | 0 .../gtest-1.7.0/include/gtest/gtest-message.h | 0 .../include/gtest/gtest-param-test.h | 0 .../include/gtest/gtest-param-test.h.pump | 0 .../include/gtest/gtest-printers.h | 0 .../gtest-1.7.0/include/gtest/gtest-spi.h | 0 .../include/gtest/gtest-test-part.h | 0 .../include/gtest/gtest-typed-test.h | 0 .../gtest-1.7.0/include/gtest/gtest.h | 0 .../include/gtest/gtest_pred_impl.h | 0 .../gtest-1.7.0/include/gtest/gtest_prod.h | 0 .../internal/gtest-death-test-internal.h | 0 .../include/gtest/internal/gtest-filepath.h | 0 .../include/gtest/internal/gtest-internal.h | 0 .../include/gtest/internal/gtest-linked_ptr.h | 0 .../internal/gtest-param-util-generated.h | 0 .../gtest-param-util-generated.h.pump | 0 .../include/gtest/internal/gtest-param-util.h | 0 .../include/gtest/internal/gtest-port.h | 0 .../include/gtest/internal/gtest-string.h | 0 .../include/gtest/internal/gtest-tuple.h | 0 .../include/gtest/internal/gtest-tuple.h.pump | 0 .../include/gtest/internal/gtest-type-util.h | 0 .../gtest/internal/gtest-type-util.h.pump | 0 .../third-party/gtest-1.7.0/m4/acx_pthread.m4 | 0 .../third-party/gtest-1.7.0/m4/gtest.m4 | 0 .../third-party/gtest-1.7.0/m4/libtool.m4 | 0 .../third-party/gtest-1.7.0/m4/ltoptions.m4 | 0 .../third-party/gtest-1.7.0/m4/ltsugar.m4 | 0 .../third-party/gtest-1.7.0/m4/ltversion.m4 | 0 .../third-party/gtest-1.7.0/m4/lt~obsolete.m4 | 0 .../third-party/gtest-1.7.0/make/Makefile | 0 .../third-party/gtest-1.7.0/msvc/gtest-md.sln | 0 .../gtest-1.7.0/msvc/gtest-md.vcproj | 0 .../third-party/gtest-1.7.0/msvc/gtest.sln | 0 .../third-party/gtest-1.7.0/msvc/gtest.vcproj | 0 .../gtest-1.7.0/msvc/gtest_main-md.vcproj | 0 .../gtest-1.7.0/msvc/gtest_main.vcproj | 0 .../msvc/gtest_prod_test-md.vcproj | 0 .../gtest-1.7.0/msvc/gtest_prod_test.vcproj | 0 .../gtest-1.7.0/msvc/gtest_unittest-md.vcproj | 0 .../gtest-1.7.0/msvc/gtest_unittest.vcproj | 0 .../gtest-1.7.0/samples/prime_tables.h | 0 .../gtest-1.7.0/samples/sample1.cc | 0 .../third-party/gtest-1.7.0/samples/sample1.h | 0 .../gtest-1.7.0/samples/sample10_unittest.cc | 0 .../gtest-1.7.0/samples/sample1_unittest.cc | 0 .../gtest-1.7.0/samples/sample2.cc | 0 .../third-party/gtest-1.7.0/samples/sample2.h | 0 .../gtest-1.7.0/samples/sample2_unittest.cc | 0 .../gtest-1.7.0/samples/sample3-inl.h | 0 .../gtest-1.7.0/samples/sample3_unittest.cc | 0 .../gtest-1.7.0/samples/sample4.cc | 0 .../third-party/gtest-1.7.0/samples/sample4.h | 0 .../gtest-1.7.0/samples/sample4_unittest.cc | 0 .../gtest-1.7.0/samples/sample5_unittest.cc | 0 .../gtest-1.7.0/samples/sample6_unittest.cc | 0 .../gtest-1.7.0/samples/sample7_unittest.cc | 0 .../gtest-1.7.0/samples/sample8_unittest.cc | 0 .../gtest-1.7.0/samples/sample9_unittest.cc | 0 .../gtest-1.7.0/scripts/fuse_gtest_files.py | 0 .../scripts/gen_gtest_pred_impl.py | 0 .../gtest-1.7.0/scripts/gtest-config.in | 0 .../third-party/gtest-1.7.0/scripts/pump.py | 0 .../gtest-1.7.0/scripts/test/Makefile | 0 .../third-party/gtest-1.7.0/src/gtest-all.cc | 0 .../gtest-1.7.0/src/gtest-death-test.cc | 0 .../gtest-1.7.0/src/gtest-filepath.cc | 0 .../gtest-1.7.0/src/gtest-internal-inl.h | 0 .../third-party/gtest-1.7.0/src/gtest-port.cc | 0 .../gtest-1.7.0/src/gtest-printers.cc | 0 .../gtest-1.7.0/src/gtest-test-part.cc | 0 .../gtest-1.7.0/src/gtest-typed-test.cc | 0 .../third-party/gtest-1.7.0/src/gtest.cc | 0 .../third-party/gtest-1.7.0/src/gtest_main.cc | 0 .../test/gtest-death-test_ex_test.cc | 0 .../gtest-1.7.0/test/gtest-death-test_test.cc | 0 .../gtest-1.7.0/test/gtest-filepath_test.cc | 0 .../gtest-1.7.0/test/gtest-linked_ptr_test.cc | 0 .../gtest-1.7.0/test/gtest-listener_test.cc | 0 .../gtest-1.7.0/test/gtest-message_test.cc | 0 .../gtest-1.7.0/test/gtest-options_test.cc | 0 .../test/gtest-param-test2_test.cc | 0 .../gtest-1.7.0/test/gtest-param-test_test.cc | 0 .../gtest-1.7.0/test/gtest-param-test_test.h | 0 .../gtest-1.7.0/test/gtest-port_test.cc | 0 .../gtest-1.7.0/test/gtest-printers_test.cc | 0 .../gtest-1.7.0/test/gtest-test-part_test.cc | 0 .../gtest-1.7.0/test/gtest-tuple_test.cc | 0 .../test/gtest-typed-test2_test.cc | 0 .../gtest-1.7.0/test/gtest-typed-test_test.cc | 0 .../gtest-1.7.0/test/gtest-typed-test_test.h | 0 .../test/gtest-unittest-api_test.cc | 0 .../gtest-1.7.0/test/gtest_all_test.cc | 0 .../test/gtest_break_on_failure_unittest.py | 0 .../test/gtest_break_on_failure_unittest_.cc | 0 .../test/gtest_catch_exceptions_test.py | 0 .../test/gtest_catch_exceptions_test_.cc | 0 .../gtest-1.7.0/test/gtest_color_test.py | 0 .../gtest-1.7.0/test/gtest_color_test_.cc | 0 .../gtest-1.7.0/test/gtest_env_var_test.py | 0 .../gtest-1.7.0/test/gtest_env_var_test_.cc | 0 .../test/gtest_environment_test.cc | 0 .../gtest-1.7.0/test/gtest_filter_unittest.py | 0 .../test/gtest_filter_unittest_.cc | 0 .../gtest-1.7.0/test/gtest_help_test.py | 0 .../gtest-1.7.0/test/gtest_help_test_.cc | 0 .../test/gtest_list_tests_unittest.py | 0 .../test/gtest_list_tests_unittest_.cc | 0 .../gtest-1.7.0/test/gtest_main_unittest.cc | 0 .../test/gtest_no_test_unittest.cc | 0 .../gtest-1.7.0/test/gtest_output_test.py | 0 .../gtest-1.7.0/test/gtest_output_test_.cc | 0 .../test/gtest_output_test_golden_lin.txt | 0 .../test/gtest_pred_impl_unittest.cc | 0 .../test/gtest_premature_exit_test.cc | 0 .../gtest-1.7.0/test/gtest_prod_test.cc | 0 .../gtest-1.7.0/test/gtest_repeat_test.cc | 0 .../gtest-1.7.0/test/gtest_shuffle_test.py | 0 .../gtest-1.7.0/test/gtest_shuffle_test_.cc | 0 .../test/gtest_sole_header_test.cc | 0 .../gtest-1.7.0/test/gtest_stress_test.cc | 0 .../gtest-1.7.0/test/gtest_test_utils.py | 0 .../test/gtest_throw_on_failure_ex_test.cc | 0 .../test/gtest_throw_on_failure_test.py | 0 .../test/gtest_throw_on_failure_test_.cc | 0 .../test/gtest_uninitialized_test.py | 0 .../test/gtest_uninitialized_test_.cc | 0 .../gtest-1.7.0/test/gtest_unittest.cc | 0 .../test/gtest_xml_outfile1_test_.cc | 0 .../test/gtest_xml_outfile2_test_.cc | 0 .../test/gtest_xml_outfiles_test.py | 0 .../test/gtest_xml_output_unittest.py | 0 .../test/gtest_xml_output_unittest_.cc | 0 .../gtest-1.7.0/test/gtest_xml_test_utils.py | 0 .../gtest-1.7.0/test/production.cc | 0 .../third-party/gtest-1.7.0/test/production.h | 0 .../xcode/Config/DebugProject.xcconfig | 0 .../xcode/Config/FrameworkTarget.xcconfig | 0 .../gtest-1.7.0/xcode/Config/General.xcconfig | 0 .../xcode/Config/ReleaseProject.xcconfig | 0 .../xcode/Config/StaticLibraryTarget.xcconfig | 0 .../xcode/Config/TestTarget.xcconfig | 0 .../gtest-1.7.0/xcode/Resources/Info.plist | 0 .../xcode/Samples/FrameworkSample/Info.plist | 0 .../WidgetFramework.xcodeproj/project.pbxproj | 0 .../xcode/Samples/FrameworkSample/runtests.sh | 0 .../xcode/Samples/FrameworkSample/widget.cc | 0 .../xcode/Samples/FrameworkSample/widget.h | 0 .../Samples/FrameworkSample/widget_test.cc | 0 .../gtest-1.7.0/xcode/Scripts/runtests.sh | 0 .../xcode/Scripts/versiongenerate.py | 0 .../xcode/gtest.xcodeproj/project.pbxproj | 0 .../I2Cdevlib-ADS1115/.library.json | 40 + .../I2Cdevlib-ADS1115/ADS1115.cpp | 649 ++++++++ lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.h | 200 +++ .../ADS1115_differential.ino | 91 + .../ADS1115_single/ADS1115_single.ino | 110 ++ .../I2Cdevlib-ADS1115/library.json | 18 + .../I2Cdevlib-Core/.library.json | 31 + lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.cpp | 1457 +++++++++++++++++ lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.h | 278 ++++ lib-before-5.9.1f/I2Cdevlib-Core/keywords.txt | 38 + lib-before-5.9.1f/I2Cdevlib-Core/library.json | 13 + .../IRremoteESP8266/Contributors.md | 0 .../IRremoteESP8266/IRDaikinESP.cpp | 0 .../IRremoteESP8266/IRDaikinESP.h | 0 .../IRremoteESP8266/IRKelvinator.cpp | 0 .../IRremoteESP8266/IRKelvinator.h | 0 .../IRremoteESP8266/IRMitsubishiAC.cpp | 0 .../IRremoteESP8266/IRMitsubishiAC.h | 0 .../IRremoteESP8266/IRremoteESP8266.cpp | 0 .../IRremoteESP8266/IRremoteESP8266.h | 0 .../IRremoteESP8266/IRremoteInt.h | 0 .../IRremoteESP8266/LICENSE.txt | 0 .../IRremoteESP8266/README.md | 0 .../examples/IRGCSendDemo/IRGCSendDemo.ino | 0 .../examples/IRGCTCPServer/IRGCTCPServer.ino | 0 .../examples/IRServer/IRServer.ino | 0 .../examples/IRrecvDemo/IRrecvDemo.ino | 0 .../examples/IRrecvDump/IRrecvDump.ino | 0 .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 0 .../examples/IRsendDemo/IRsendDemo.ino | 0 .../JVCPanasonicSendDemo.ino | 0 .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 0 .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 0 .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 0 .../IRremoteESP8266/keywords.txt | 0 .../IRremoteESP8266/library.json | 0 .../IRremoteESP8266/library.properties | 0 .../NeoPixelBus_by_Makuna/COPYING | 0 .../NeoPixelBus_by_Makuna/ReadMe.md | 0 .../examples/DotStarTest/DotStarTest.ino | 0 .../NeoPixelAnimation/NeoPixelAnimation.ino | 0 .../NeoPixelBitmap/NeoPixelBitmap.ino | 0 .../examples/NeoPixelBitmap/Strings.bmp | Bin .../examples/NeoPixelBitmap/StringsW.bmp | Bin .../NeoPixelBrightness/NeoPixelBrightness.ino | 0 .../examples/NeoPixelBufferCylon/Cylon.pdn | Bin .../examples/NeoPixelBufferCylon/CylonGrb.h | 0 .../examples/NeoPixelBufferCylon/CylonGrbw.h | 0 .../NeoPixelBufferCylon.ino | 0 .../examples/NeoPixelCylon/NeoPixelCylon.ino | 0 .../NeoPixelFunFadeInOut.ino | 0 .../NeoPixelFunLoop/NeoPixelFunLoop.ino | 0 .../NeoPixelFunRandomChange.ino | 0 .../examples/NeoPixelGamma/NeoPixelGamma.ino | 0 .../NeoPixelMosaicDump/NeoPixelMosaicDump.ino | 0 .../NeoPixelMosaicTest/NeoPixelMosaicTest.ino | 0 .../NeoPixelRingTopologyTest.ino | 0 .../NeoPixelRotateLoop/NeoPixelRotateLoop.ino | 0 .../examples/NeoPixelTest/NeoPixelTest.ino | 0 .../NeoPixelTilesDump/NeoPixelTilesDump.ino | 0 .../NeoPixelTilesTest/NeoPixelTilesTest.ino | 0 .../NeoPixelTopologyDump.ino | 0 .../NeoPixelTopologyTest.ino | 0 .../NeoPixelBus_by_Makuna/keywords.txt | 0 .../NeoPixelBus_by_Makuna/library.json | 0 .../NeoPixelBus_by_Makuna/library.properties | 0 .../src/NeoPixelAnimator.h | 0 .../src/NeoPixelBrightnessBus.h | 0 .../NeoPixelBus_by_Makuna/src/NeoPixelBus.h | 0 .../src/internal/DotStarAvrMethod.h | 0 .../src/internal/DotStarColorFeatures.h | 0 .../src/internal/DotStarGenericMethod.h | 0 .../src/internal/DotStarSpiMethod.h | 0 .../src/internal/HsbColor.cpp | 0 .../src/internal/HsbColor.h | 0 .../src/internal/HslColor.cpp | 0 .../src/internal/HslColor.h | 0 .../src/internal/HtmlColor.cpp | 0 .../src/internal/HtmlColor.h | 0 .../src/internal/HtmlColorNameStrings.cpp | 0 .../src/internal/HtmlColorNameStrings.h | 0 .../src/internal/HtmlColorNames.cpp | 0 .../src/internal/HtmlColorShortNames.cpp | 0 .../src/internal/Layouts.h | 0 .../src/internal/NeoArmMethod.h | 0 .../src/internal/NeoAvrMethod.h | 0 .../src/internal/NeoBitmapFile.h | 0 .../src/internal/NeoBuffer.h | 0 .../src/internal/NeoBufferContext.h | 0 .../src/internal/NeoBufferMethods.h | 0 .../src/internal/NeoColorFeatures.h | 0 .../src/internal/NeoEase.h | 0 .../src/internal/NeoEsp8266BitBangMethod.h | 0 .../src/internal/NeoEsp8266DmaMethod.h | 0 .../src/internal/NeoEsp8266UartMethod.cpp | 0 .../src/internal/NeoEsp8266UartMethod.h | 0 .../src/internal/NeoGamma.cpp | 0 .../src/internal/NeoGamma.h | 0 .../src/internal/NeoHueBlend.h | 0 .../src/internal/NeoMosaic.h | 0 .../src/internal/NeoPixelAnimator.cpp | 0 .../src/internal/NeoPixelAvr.c | 0 .../src/internal/NeoPixelEsp8266.c | 0 .../src/internal/NeoRingTopology.h | 0 .../src/internal/NeoSpriteSheet.h | 0 .../src/internal/NeoTiles.h | 0 .../src/internal/NeoTopology.h | 0 .../src/internal/RgbColor.cpp | 0 .../src/internal/RgbColor.h | 0 .../src/internal/RgbwColor.cpp | 0 .../src/internal/RgbwColor.h | 0 .../OneWire/OneWire.cpp | 0 {lib => lib-before-5.9.1f}/OneWire/OneWire.h | 0 .../DS18x20_Temperature.pde | 0 .../examples/DS2408_Switch/DS2408_Switch.pde | 0 .../examples/DS250x_PROM/DS250x_PROM.pde | 0 .../OneWire/keywords.txt | 0 .../OneWire/library.json | 0 .../OneWire/library.properties | 0 .../PubSubClient/CHANGES.txt | 0 .../PubSubClient/LICENSE.txt | 0 .../PubSubClient/README.md | 0 .../examples/mqtt_auth/mqtt_auth.ino | 0 .../examples/mqtt_basic/mqtt_basic.ino | 0 .../examples/mqtt_esp8266/mqtt_esp8266.ino | 0 .../mqtt_publish_in_callback.ino | 0 .../mqtt_reconnect_nonblocking.ino | 0 .../examples/mqtt_stream/mqtt_stream.ino | 0 .../PubSubClient/keywords.txt | 0 .../PubSubClient/library.json | 0 .../PubSubClient/library.properties | 0 .../PubSubClient/src/PubSubClient.cpp | 0 .../PubSubClient/src/PubSubClient.h | 0 .../PubSubClient/tests/.gitignore | 0 .../PubSubClient/tests/Makefile | 0 .../PubSubClient/tests/README.md | 0 .../PubSubClient/tests/src/connect_spec.cpp | 0 .../PubSubClient/tests/src/keepalive_spec.cpp | 0 .../PubSubClient/tests/src/lib/Arduino.h | 0 .../PubSubClient/tests/src/lib/BDDTest.cpp | 0 .../PubSubClient/tests/src/lib/BDDTest.h | 0 .../PubSubClient/tests/src/lib/Buffer.cpp | 0 .../PubSubClient/tests/src/lib/Buffer.h | 0 .../PubSubClient/tests/src/lib/Client.h | 0 .../PubSubClient/tests/src/lib/IPAddress.cpp | 0 .../PubSubClient/tests/src/lib/IPAddress.h | 0 .../PubSubClient/tests/src/lib/ShimClient.cpp | 0 .../PubSubClient/tests/src/lib/ShimClient.h | 0 .../PubSubClient/tests/src/lib/Stream.cpp | 0 .../PubSubClient/tests/src/lib/Stream.h | 0 .../PubSubClient/tests/src/lib/trace.h | 0 .../PubSubClient/tests/src/publish_spec.cpp | 0 .../PubSubClient/tests/src/receive_spec.cpp | 0 .../PubSubClient/tests/src/subscribe_spec.cpp | 0 .../PubSubClient/tests/testcases/__init__.py | 0 .../tests/testcases/mqtt_basic.py | 0 .../testcases/mqtt_publish_in_callback.py | 0 .../PubSubClient/tests/testcases/settings.py | 0 .../PubSubClient/tests/testsuite.py | 0 lib/ArduinoJson-5.11.2/ArduinoJson.h | 8 + lib/ArduinoJson-5.11.2/CHANGELOG.md | 512 ++++++ lib/ArduinoJson-5.11.2/LICENSE.md | 10 + lib/ArduinoJson-5.11.2/README.md | 130 ++ .../JsonGeneratorExample.ino | 70 + .../JsonHttpClient/JsonHttpClient.ino | 184 +++ .../JsonParserExample/JsonParserExample.ino | 67 + .../examples/JsonServer/JsonServer.ino | 76 + .../examples/JsonUdpBeacon/JsonUdpBeacon.ino | 57 + .../ProgmemExample/ProgmemExample.ino | 56 + .../examples/StringExample/StringExample.ino | 63 + lib/ArduinoJson-5.11.2/keywords.txt | 15 + lib/ArduinoJson-5.11.2/library.properties | 9 + lib/ArduinoJson-5.11.2/src/ArduinoJson.h | 12 + lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp | 20 + .../src/ArduinoJson/Configuration.hpp | 153 ++ .../src/ArduinoJson/Data/Encoding.hpp | 40 + .../ArduinoJson/Data/JsonBufferAllocated.hpp | 25 + .../src/ArduinoJson/Data/JsonFloat.hpp | 21 + .../src/ArduinoJson/Data/JsonInteger.hpp | 26 + .../src/ArduinoJson/Data/JsonVariantAs.hpp | 45 + .../ArduinoJson/Data/JsonVariantContent.hpp | 30 + .../ArduinoJson/Data/JsonVariantDefault.hpp | 26 + .../src/ArduinoJson/Data/JsonVariantType.hpp | 30 + .../src/ArduinoJson/Data/List.hpp | 97 ++ .../ArduinoJson/Data/ListConstIterator.hpp | 53 + .../src/ArduinoJson/Data/ListIterator.hpp | 63 + .../src/ArduinoJson/Data/ListNode.hpp | 27 + .../src/ArduinoJson/Data/NonCopyable.hpp | 26 + .../src/ArduinoJson/Data/ReferenceType.hpp | 27 + .../src/ArduinoJson/Data/ValueSetter.hpp | 51 + .../ArduinoJson/Deserialization/Comments.hpp | 64 + .../Deserialization/JsonParser.hpp | 107 ++ .../Deserialization/JsonParserImpl.hpp | 194 +++ .../Deserialization/StringWriter.hpp | 44 + .../src/ArduinoJson/DynamicJsonBuffer.hpp | 170 ++ .../src/ArduinoJson/JsonArray.hpp | 233 +++ .../src/ArduinoJson/JsonArrayImpl.hpp | 29 + .../src/ArduinoJson/JsonArraySubscript.hpp | 125 ++ .../src/ArduinoJson/JsonBuffer.hpp | 80 + .../src/ArduinoJson/JsonBufferBase.hpp | 128 ++ .../src/ArduinoJson/JsonBufferImpl.hpp | 20 + .../src/ArduinoJson/JsonObject.hpp | 351 ++++ .../src/ArduinoJson/JsonObjectImpl.hpp | 31 + .../src/ArduinoJson/JsonObjectSubscript.hpp | 117 ++ .../src/ArduinoJson/JsonPair.hpp | 19 + .../src/ArduinoJson/JsonVariant.hpp | 360 ++++ .../src/ArduinoJson/JsonVariantBase.hpp | 23 + .../src/ArduinoJson/JsonVariantCasts.hpp | 60 + .../ArduinoJson/JsonVariantComparisons.hpp | 144 ++ .../src/ArduinoJson/JsonVariantImpl.hpp | 129 ++ .../src/ArduinoJson/JsonVariantSubscripts.hpp | 89 + .../src/ArduinoJson/Polyfills/attributes.hpp | 32 + .../src/ArduinoJson/Polyfills/ctype.hpp | 21 + .../src/ArduinoJson/Polyfills/isFloat.hpp | 41 + .../src/ArduinoJson/Polyfills/isInteger.hpp | 22 + .../src/ArduinoJson/Polyfills/math.hpp | 22 + .../src/ArduinoJson/Polyfills/parseFloat.hpp | 93 ++ .../ArduinoJson/Polyfills/parseInteger.hpp | 44 + .../src/ArduinoJson/RawJson.hpp | 23 + .../ArduinoJson/Serialization/DummyPrint.hpp | 25 + .../Serialization/DynamicStringBuilder.hpp | 38 + .../ArduinoJson/Serialization/FloatParts.hpp | 92 ++ .../Serialization/IndentedPrint.hpp | 71 + .../Serialization/JsonPrintable.hpp | 122 ++ .../Serialization/JsonSerializer.hpp | 34 + .../Serialization/JsonSerializerImpl.hpp | 106 ++ .../ArduinoJson/Serialization/JsonWriter.hpp | 158 ++ .../ArduinoJson/Serialization/Prettyfier.hpp | 136 ++ .../Serialization/StaticStringBuilder.hpp | 39 + .../Serialization/StreamPrintAdapter.hpp | 42 + .../src/ArduinoJson/StaticJsonBuffer.hpp | 126 ++ .../StringTraits/ArduinoStream.hpp | 61 + .../ArduinoJson/StringTraits/CharPointer.hpp | 58 + .../ArduinoJson/StringTraits/FlashString.hpp | 56 + .../ArduinoJson/StringTraits/StdStream.hpp | 60 + .../ArduinoJson/StringTraits/StdString.hpp | 70 + .../ArduinoJson/StringTraits/StringTraits.hpp | 50 + .../src/ArduinoJson/TypeTraits/EnableIf.hpp | 22 + .../ArduinoJson/TypeTraits/FloatTraits.hpp | 153 ++ .../src/ArduinoJson/TypeTraits/IsArray.hpp | 27 + .../src/ArduinoJson/TypeTraits/IsBaseOf.hpp | 30 + .../src/ArduinoJson/TypeTraits/IsChar.hpp | 26 + .../src/ArduinoJson/TypeTraits/IsConst.hpp | 24 + .../TypeTraits/IsFloatingPoint.hpp | 21 + .../src/ArduinoJson/TypeTraits/IsIntegral.hpp | 29 + .../src/ArduinoJson/TypeTraits/IsSame.hpp | 24 + .../TypeTraits/IsSignedIntegral.hpp | 33 + .../TypeTraits/IsUnsignedIntegral.hpp | 33 + .../src/ArduinoJson/TypeTraits/IsVariant.hpp | 20 + .../ArduinoJson/TypeTraits/RemoveConst.hpp | 23 + .../TypeTraits/RemoveReference.hpp | 23 + .../.github/CONTRIBUTING.md | 82 + .../.github/Contributors.md | 16 + .../.github/issue_template.md | 39 + lib/IRremoteESP8266-2.2.1.02/.gitignore | 39 + lib/IRremoteESP8266-2.2.1.02/.gitmodules | 3 + lib/IRremoteESP8266-2.2.1.02/.travis.yml | 57 + lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg | 3 + lib/IRremoteESP8266-2.2.1.02/LICENSE.txt | 458 ++++++ lib/IRremoteESP8266-2.2.1.02/README.md | 74 + lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md | 112 ++ .../examples/IRGCSendDemo/IRGCSendDemo.ino | 63 + .../examples/IRGCSendDemo/platformio.ini | 17 + .../examples/IRGCTCPServer/IRGCTCPServer.ino | 129 ++ .../examples/IRGCTCPServer/platformio.ini | 17 + .../examples/IRMQTTServer/IRMQTTServer.ino | 982 +++++++++++ .../examples/IRMQTTServer/platformio.ini | 28 + .../examples/IRServer/IRServer.ino | 121 ++ .../examples/IRServer/platformio.ini | 17 + .../examples/IRrecvDemo/IRrecvDemo.ino | 44 + .../examples/IRrecvDemo/platformio.ini | 17 + .../examples/IRrecvDump/IRrecvDump.ino | 104 ++ .../examples/IRrecvDump/platformio.ini | 17 + .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 199 +++ .../examples/IRrecvDumpV2/platformio.ini | 17 + .../examples/IRsendDemo/IRsendDemo.ino | 62 + .../examples/IRsendDemo/platformio.ini | 17 + .../IRsendProntoDemo/IRsendProntoDemo.ino | 105 ++ .../examples/IRsendProntoDemo/platformio.ini | 17 + .../JVCPanasonicSendDemo.ino | 56 + .../JVCPanasonicSendDemo/platformio.ini | 17 + .../examples/LGACSend/LGACSend.ino | 259 +++ .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 52 + .../examples/TurnOnArgoAC/platformio.ini | 17 + .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 56 + .../examples/TurnOnDaikinAC/platformio.ini | 17 + .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 44 + .../examples/TurnOnFujitsuAC/platformio.ini | 17 + .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 80 + .../TurnOnKelvinatorAC/platformio.ini | 17 + .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 71 + .../TurnOnMitsubishiAC/platformio.ini | 17 + .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 52 + .../examples/TurnOnTrotecAC/platformio.ini | 17 + lib/IRremoteESP8266-2.2.1.02/keywords.txt | 128 ++ lib/IRremoteESP8266-2.2.1.02/library.json | 44 + .../library.properties | 9 + lib/IRremoteESP8266-2.2.1.02/platformio.ini | 26 + lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg | 1 + lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp | 632 +++++++ 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/IRtimer.cpp | 33 + lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h | 20 + lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp | 82 + lib/IRremoteESP8266-2.2.1.02/src/IRutils.h | 23 + lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp | 118 ++ lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp | 264 +++ lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h | 124 ++ .../src/ir_Coolix.cpp | 167 ++ .../src/ir_Daikin.cpp | 347 ++++ lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h | 107 ++ lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp | 153 ++ lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp | 144 ++ .../src/ir_Fujitsu.cpp | 221 +++ lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h | 80 + .../src/ir_GlobalCache.cpp | 72 + lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp | 113 ++ lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp | 165 ++ .../src/ir_Kelvinator.cpp | 329 ++++ .../src/ir_Kelvinator.h | 152 ++ lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp | 233 +++ lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h | 17 + .../src/ir_Mitsubishi.cpp | 349 ++++ .../src/ir_Mitsubishi.h | 65 + lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp | 210 +++ lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp | 120 ++ .../src/ir_Panasonic.cpp | 196 +++ .../src/ir_Pronto.cpp | 109 ++ .../src/ir_RC5_RC6.cpp | 514 ++++++ lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp | 174 ++ .../src/ir_Samsung.cpp | 175 ++ lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp | 239 +++ lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp | 278 ++++ .../src/ir_Sherwood.cpp | 29 + lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp | 197 +++ .../src/ir_Trotec.cpp | 151 ++ lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h | 80 + .../src/ir_Whynter.cpp | 144 ++ .../test/IRrecv_test.cpp | 448 +++++ .../test/IRsend_test.cpp | 139 ++ .../test/IRsend_test.h | 106 ++ .../test/IRutils_test.cpp | 91 + lib/IRremoteESP8266-2.2.1.02/test/Makefile | 348 ++++ .../test/ir_Aiwa_test.cpp | 338 ++++ .../test/ir_Coolix_test.cpp | 290 ++++ .../test/ir_Daikin_test.cpp | 419 +++++ .../test/ir_Denon_test.cpp | 272 +++ .../test/ir_Dish_test.cpp | 321 ++++ .../test/ir_Fujitsu_test.cpp | 207 +++ .../test/ir_GlobalCache_test.cpp | 68 + .../test/ir_Gree_test.cpp | 192 +++ .../test/ir_JVC_test.cpp | 299 ++++ .../test/ir_Kelvinator_test.cpp | 432 +++++ .../test/ir_LG_test.cpp | 358 ++++ .../test/ir_Mitsubishi_test.cpp | 694 ++++++++ .../test/ir_NEC_test.cpp | 320 ++++ .../test/ir_Nikai_test.cpp | 210 +++ .../test/ir_Panasonic_test.cpp | 457 ++++++ .../test/ir_Pronto_test.cpp | 358 ++++ .../test/ir_RC5_RC6_test.cpp | 873 ++++++++++ .../test/ir_RCMM_test.cpp | 239 +++ .../test/ir_Samsung_test.cpp | 276 ++++ .../test/ir_Sanyo_test.cpp | 242 +++ .../test/ir_Sharp_test.cpp | 357 ++++ .../test/ir_Sherwood_test.cpp | 72 + .../test/ir_Sony_test.cpp | 323 ++++ .../test/ir_Whynter_test.cpp | 247 +++ lib/IRremoteESP8266-2.2.1.02/tools/Makefile | 136 ++ .../tools/gc_decode.cpp | 106 ++ lib/NeoPixelBus-2.2.9/.gitattributes | 22 + lib/NeoPixelBus-2.2.9/.gitignore | 36 + lib/NeoPixelBus-2.2.9/COPYING | 675 ++++++++ lib/NeoPixelBus-2.2.9/ReadMe.md | 34 + .../examples/DotStarTest/DotStarTest.ino | 88 + .../NeoPixelBrightness/NeoPixelBrightness.ino | 83 + .../examples/NeoPixelGamma/NeoPixelGamma.ino | 95 ++ .../examples/NeoPixelTest/NeoPixelTest.ino | 140 ++ .../NeoPixelAnimation/NeoPixelAnimation.ino | 225 +++ .../NeoPixelCylon/NeoPixelCylon.ino | 123 ++ .../NeoPixelFunFadeInOut.ino | 132 ++ .../NeoPixelFunLoop/NeoPixelFunLoop.ino | 141 ++ .../NeoPixelFunRandomChange.ino | 116 ++ .../NeoPixelRotateLoop/NeoPixelRotateLoop.ino | 97 ++ .../bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino | 98 ++ .../bitmaps/NeoPixelBitmap/Strings.bmp | Bin 0 -> 62262 bytes .../bitmaps/NeoPixelBitmap/StringsW.bmp | Bin 0 -> 82998 bytes .../bitmaps/NeoPixelBufferCylon/Cylon.pdn | Bin 0 -> 3953 bytes .../bitmaps/NeoPixelBufferCylon/CylonGrb.h | 30 + .../bitmaps/NeoPixelBufferCylon/CylonGrbw.h | 30 + .../NeoPixelBufferCylon.ino | 74 + .../NeoPixelBufferShader.ino | 167 ++ .../NeoPixelDibTest/NeoPixelDibTest.ino | 158 ++ .../NeoPixelMosaicDump/NeoPixelMosaicDump.ino | 98 ++ .../NeoPixelMosaicTest/NeoPixelMosaicTest.ino | 97 ++ .../NeoPixelRingTopologyTest.ino | 100 ++ .../NeoPixelTilesDump/NeoPixelTilesDump.ino | 102 ++ .../NeoPixelTilesTest/NeoPixelTilesTest.ino | 103 ++ .../NeoPixelTopologyDump.ino | 78 + .../NeoPixelTopologyTest.ino | 92 ++ lib/NeoPixelBus-2.2.9/keywords.txt | 184 +++ lib/NeoPixelBus-2.2.9/library.json | 15 + lib/NeoPixelBus-2.2.9/library.properties | 9 + lib/NeoPixelBus-2.2.9/src/NeoPixelAnimator.h | 174 ++ .../src/NeoPixelBrightnessBus.h | 161 ++ lib/NeoPixelBus-2.2.9/src/NeoPixelBus.h | 400 +++++ .../src/internal/DotStarAvrMethod.h | 153 ++ .../src/internal/DotStarColorFeatures.h | 326 ++++ .../src/internal/DotStarGenericMethod.h | 128 ++ .../src/internal/DotStarSpiMethod.h | 125 ++ .../src/internal/HsbColor.cpp | 68 + lib/NeoPixelBus-2.2.9/src/internal/HsbColor.h | 113 ++ .../src/internal/HslColor.cpp | 72 + lib/NeoPixelBus-2.2.9/src/internal/HslColor.h | 113 ++ .../src/internal/HtmlColor.cpp | 58 + .../src/internal/HtmlColor.h | 340 ++++ .../src/internal/HtmlColorNameStrings.cpp | 178 ++ .../src/internal/HtmlColorNameStrings.h | 180 ++ .../src/internal/HtmlColorNames.cpp | 188 +++ .../src/internal/HtmlColorShortNames.cpp | 59 + lib/NeoPixelBus-2.2.9/src/internal/Layouts.h | 426 +++++ .../src/internal/NeoArmMethod.h | 697 ++++++++ .../src/internal/NeoAvrMethod.h | 200 +++ .../src/internal/NeoBitmapFile.h | 351 ++++ .../src/internal/NeoBuffer.h | 154 ++ .../src/internal/NeoBufferContext.h | 48 + .../src/internal/NeoBufferMethods.h | 263 +++ .../src/internal/NeoColorFeatures.h | 389 +++++ lib/NeoPixelBus-2.2.9/src/internal/NeoDib.h | 161 ++ lib/NeoPixelBus-2.2.9/src/internal/NeoEase.h | 224 +++ .../src/internal/NeoEsp8266DmaMethod.h | 382 +++++ .../src/internal/NeoEsp8266UartMethod.cpp | 216 +++ .../src/internal/NeoEsp8266UartMethod.h | 178 ++ .../src/internal/NeoEspBitBangMethod.h | 166 ++ .../src/internal/NeoGamma.cpp | 50 + lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.h | 73 + .../src/internal/NeoHueBlend.h | 118 ++ .../src/internal/NeoMosaic.h | 191 +++ .../src/internal/NeoPixelAnimator.cpp | 166 ++ .../src/internal/NeoPixelAvr.c | 648 ++++++++ .../src/internal/NeoPixelEsp.c | 151 ++ .../src/internal/NeoRingTopology.h | 89 + .../src/internal/NeoSpriteSheet.h | 163 ++ lib/NeoPixelBus-2.2.9/src/internal/NeoTiles.h | 158 ++ .../src/internal/NeoTopology.h | 91 + .../src/internal/RgbColor.cpp | 249 +++ lib/NeoPixelBus-2.2.9/src/internal/RgbColor.h | 148 ++ .../src/internal/RgbwColor.cpp | 178 ++ .../src/internal/RgbwColor.h | 178 ++ lib/OneWire-2.3.3.06/OneWire.cpp | 597 +++++++ lib/OneWire-2.3.3.06/OneWire.h | 545 ++++++ .../DS18x20_Temperature.pde | 112 ++ .../examples/DS2408_Switch/DS2408_Switch.pde | 74 + .../examples/DS250x_PROM/DS250x_PROM.pde | 90 + lib/OneWire-2.3.3.06/keywords.txt | 38 + lib/OneWire-2.3.3.06/library.json | 61 + lib/OneWire-2.3.3.06/library.properties | 10 + lib/PubSubClient-2.6.09/.gitignore | 1 + lib/PubSubClient-2.6.09/.travis.yml | 7 + lib/PubSubClient-2.6.09/CHANGES.txt | 68 + lib/PubSubClient-2.6.09/LICENSE.txt | 20 + lib/PubSubClient-2.6.09/README.md | 47 + .../examples/mqtt_auth/mqtt_auth.ino | 43 + .../examples/mqtt_basic/mqtt_basic.ino | 77 + .../examples/mqtt_esp8266/mqtt_esp8266.ino | 132 ++ .../mqtt_publish_in_callback.ino | 60 + .../mqtt_reconnect_nonblocking.ino | 67 + .../examples/mqtt_stream/mqtt_stream.ino | 57 + lib/PubSubClient-2.6.09/keywords.txt | 30 + lib/PubSubClient-2.6.09/library.json | 17 + lib/PubSubClient-2.6.09/library.properties | 9 + lib/PubSubClient-2.6.09/src/PubSubClient.cpp | 589 +++++++ lib/PubSubClient-2.6.09/src/PubSubClient.h | 145 ++ lib/PubSubClient-2.6.09/tests/.gitignore | 4 + lib/PubSubClient-2.6.09/tests/Makefile | 25 + lib/PubSubClient-2.6.09/tests/README.md | 93 ++ .../tests/src/connect_spec.cpp | 273 +++ .../tests/src/keepalive_spec.cpp | 185 +++ .../tests/src/lib/Arduino.h | 23 + .../tests/src/lib/BDDTest.cpp | 50 + .../tests/src/lib/BDDTest.h | 23 + .../tests/src/lib/Buffer.cpp | 34 + .../tests/src/lib/Buffer.h | 23 + .../tests/src/lib/Client.h | 21 + .../tests/src/lib/IPAddress.cpp | 44 + .../tests/src/lib/IPAddress.h | 72 + .../tests/src/lib/ShimClient.cpp | 153 ++ .../tests/src/lib/ShimClient.h | 51 + .../tests/src/lib/Stream.cpp | 39 + .../tests/src/lib/Stream.h | 22 + lib/PubSubClient-2.6.09/tests/src/lib/trace.h | 10 + .../tests/src/publish_spec.cpp | 190 +++ .../tests/src/receive_spec.cpp | 249 +++ .../tests/src/subscribe_spec.cpp | 177 ++ .../tests/testcases/__init__.py | 0 .../tests/testcases/mqtt_basic.py | 39 + .../testcases/mqtt_publish_in_callback.py | 59 + .../tests/testcases/settings.py | 2 + lib/PubSubClient-2.6.09/tests/testsuite.py | 181 ++ lib/readme.txt | 36 + sonoff/_releasenotes.ino | 11 +- sonoff/sonoff.ino | 2 +- sonoff/support.ino | 2 +- sonoff/user_config.h | 7 +- sonoff/xdrv_irremote.ino | 21 +- sonoff/xsns_03_hlw8012.ino | 2 +- sonoff/xsns_12_ads1115.ino | 160 +- sonoff/xsns_12_ads1115_i2cdev.ino | 162 ++ 863 files changed, 48468 insertions(+), 57 deletions(-) rename {lib => lib-before-5.9.1f}/ArduinoJson/ArduinoJson.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/CHANGELOG.md (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/CMakeLists.txt (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/LICENSE.md (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/README.md (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/appveyor.yml (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/IndentedPrintExample/IndentedPrintExample.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/JsonServer/JsonServer.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/examples/StringExample/StringExample.ino (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/fuzzing/Makefile (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/fuzzing/fuzz.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/fuzzing/fuzzer.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/fuzzing/my_corpus/.gitignore (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/fuzzing/seed_corpus/ArduinoJson.json (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Configuration.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/Encoding.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonBufferAllocated.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonFloat.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonInteger.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonVariantAs.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonVariantComparer.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonVariantContent.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonVariantDefault.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/JsonVariantType.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/List.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/ListConstIterator.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/ListIterator.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/ListNode.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/Parse.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/ReferenceType.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Data/ValueSetter.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Deserialization/Comments.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Deserialization/JsonParser.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Deserialization/JsonParserImpl.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Deserialization/StringWriter.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/DynamicJsonBuffer.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonArray.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonArrayImpl.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonArraySubscript.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonBuffer.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonBufferBase.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonBufferImpl.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonObject.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonObjectImpl.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonObjectSubscript.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonPair.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonVariant.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonVariantBase.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonVariantComparisons.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/JsonVariantImpl.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Polyfills/attributes.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Polyfills/math.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Polyfills/normalize.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Print.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/RawJson.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/DummyPrint.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/DynamicStringBuilder.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/IndentedPrint.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/JsonPrintable.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializer.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializerImpl.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/JsonWriter.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/Prettyfier.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/StaticStringBuilder.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/Serialization/StreamPrintAdapter.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/StaticJsonBuffer.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/StringTraits/ArduinoStream.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/StringTraits/CharPointer.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/StringTraits/FlashString.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/StringTraits/StdStream.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/StringTraits/StdString.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/StringTraits/StringTraits.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/EnableIf.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsArray.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsBaseOf.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsChar.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsConst.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsIntegral.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsSame.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsSignedIntegral.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveConst.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveReference.hpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/keywords.txt (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/library.json (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/library.properties (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/build-arduino-package.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/cpplint.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/create-build-envs.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/create-size-graph.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/format-code.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/oss-fuzz/.gitignore (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/oss-fuzz/Vagrantfile (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/run-tests.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/travis/arduino.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/travis/cmake.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/travis/coverage.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/scripts/travis/platformio.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/CMakeLists.txt (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/Deprecated_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/DynamicJsonBuffer_Array_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/DynamicJsonBuffer_Basic_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/DynamicJsonBuffer_NoMemory_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/DynamicJsonBuffer_Object_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/DynamicJsonBuffer_String_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/GbathreeBug.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/IntegrationTests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/Issue10.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/Issue214.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/Issue34.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/Issue90.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_Add_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_Basic_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_CopyFrom_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_CopyTo_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_Invalid_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_Iterator_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_PrettyPrintTo_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_PrintTo_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_Remove_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_Set_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonArray_Subscript_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_Basic_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_ContainsKey_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_Get_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_Invalid_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_Iterator_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_PrettyPrintTo_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_PrintTo_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_Remove_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_Set_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonObject_Subscript_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonParser_Array_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonParser_Nested_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonParser_NestingLimit_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonParser_Object_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonParser_Variant_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_As_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_Comparison_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_Copy_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_Is_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_PrintTo_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_Storage_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_Subscript_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_Success_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonVariant_Undefined_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonWriter_WriteFloat_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/JsonWriter_WriteString_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StaticJsonBuffer_Basic_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StaticJsonBuffer_CreateArray_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StaticJsonBuffer_CreateObject_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StaticJsonBuffer_ParseArray_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StaticJsonBuffer_ParseObject_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StaticJsonBuffer_String_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StdStream_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/StringBuilderTests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/String_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/TypeTraits_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/UnsignedChar_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/VariableLengthArray_Tests.cpp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/test/gtest.cmake (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/cpplint/cpplint.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/CHANGES (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/CMakeLists.txt (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/CONTRIBUTORS (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/LICENSE (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/Makefile.am (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/Makefile.in (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/README (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/aclocal.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.guess (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.h.in (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.sub (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/build-aux/depcomp (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/build-aux/install-sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/build-aux/ltmain.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/build-aux/missing (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/cmake/internal_utils.cmake (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.cbproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.groupproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_all.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_link.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_main.cbproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_unittest.cbproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/configure (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/configure.ac (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest-all.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest_main.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-death-test.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-message.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h.pump (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-printers.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-spi.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-test-part.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-typed-test.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_pred_impl.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_prod.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-filepath.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-string.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/m4/acx_pthread.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/m4/gtest.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/m4/libtool.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/m4/ltoptions.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/m4/ltsugar.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/m4/ltversion.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/m4/lt~obsolete.m4 (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/make/Makefile (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.sln (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.sln (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main-md.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test-md.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest-md.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest.vcproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/prime_tables.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample10_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample1_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample2_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample3-inl.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample3_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample4_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample5_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample6_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample7_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample8_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/samples/sample9_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/scripts/fuse_gtest_files.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/scripts/gen_gtest_pred_impl.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/scripts/gtest-config.in (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/scripts/pump.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/scripts/test/Makefile (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-all.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-death-test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-filepath.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-internal-inl.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-port.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-printers.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-test-part.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest-typed-test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/src/gtest_main.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_ex_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-filepath_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-linked_ptr_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-listener_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-message_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-options_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test2_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-port_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-printers_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-test-part_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-tuple_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test2_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest-unittest-api_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_all_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_environment_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_main_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_no_test_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_golden_lin.txt (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_pred_impl_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_premature_exit_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_prod_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_repeat_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_sole_header_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_stress_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_test_utils.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_ex_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_unittest.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile1_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile2_test_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfiles_test.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest_.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_test_utils.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/production.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/test/production.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/DebugProject.xcconfig (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/FrameworkTarget.xcconfig (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/General.xcconfig (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/ReleaseProject.xcconfig (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/StaticLibraryTarget.xcconfig (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/TestTarget.xcconfig (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Resources/Info.plist (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/Info.plist (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/runtests.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.h (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget_test.cc (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/runtests.sh (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/versiongenerate.py (100%) rename {lib => lib-before-5.9.1f}/ArduinoJson/third-party/gtest-1.7.0/xcode/gtest.xcodeproj/project.pbxproj (100%) create mode 100644 lib-before-5.9.1f/I2Cdevlib-ADS1115/.library.json create mode 100644 lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.cpp create mode 100644 lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.h create mode 100644 lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_differential/ADS1115_differential.ino create mode 100644 lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino create mode 100644 lib-before-5.9.1f/I2Cdevlib-ADS1115/library.json create mode 100644 lib-before-5.9.1f/I2Cdevlib-Core/.library.json create mode 100644 lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.cpp create mode 100644 lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.h create mode 100644 lib-before-5.9.1f/I2Cdevlib-Core/keywords.txt create mode 100644 lib-before-5.9.1f/I2Cdevlib-Core/library.json rename {lib => lib-before-5.9.1f}/IRremoteESP8266/Contributors.md (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRDaikinESP.cpp (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRDaikinESP.h (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRKelvinator.cpp (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRKelvinator.h (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRMitsubishiAC.cpp (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRMitsubishiAC.h (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRremoteESP8266.cpp (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRremoteESP8266.h (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/IRremoteInt.h (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/LICENSE.txt (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/README.md (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/IRGCSendDemo/IRGCSendDemo.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/IRGCTCPServer/IRGCTCPServer.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/IRServer/IRServer.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/IRrecvDemo/IRrecvDemo.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/IRrecvDump/IRrecvDump.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/IRsendDemo/IRsendDemo.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/keywords.txt (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/library.json (100%) rename {lib => lib-before-5.9.1f}/IRremoteESP8266/library.properties (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/COPYING (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/ReadMe.md (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/DotStarTest/DotStarTest.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelAnimation/NeoPixelAnimation.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/NeoPixelBitmap.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/Strings.bmp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/StringsW.bmp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBrightness/NeoPixelBrightness.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/Cylon.pdn (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrb.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrbw.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/NeoPixelBufferCylon.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelCylon/NeoPixelCylon.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelFunLoop/NeoPixelFunLoop.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelGamma/NeoPixelGamma.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicDump/NeoPixelMosaicDump.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicTest/NeoPixelMosaicTest.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelTest/NeoPixelTest.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelTilesDump/NeoPixelTilesDump.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelTilesTest/NeoPixelTilesTest.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyDump/NeoPixelTopologyDump.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyTest/NeoPixelTopologyTest.ino (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/keywords.txt (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/library.json (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/library.properties (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/NeoPixelAnimator.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/NeoPixelBrightnessBus.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/NeoPixelBus.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/DotStarAvrMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/DotStarColorFeatures.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/DotStarGenericMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/DotStarSpiMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HsbColor.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HsbColor.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HslColor.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HslColor.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HtmlColor.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HtmlColor.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HtmlColorNames.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/HtmlColorShortNames.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/Layouts.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoArmMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoAvrMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoBitmapFile.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoBuffer.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoBufferContext.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoBufferMethods.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoColorFeatures.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoEase.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266BitBangMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266DmaMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoGamma.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoGamma.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoHueBlend.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoMosaic.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoPixelAnimator.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoPixelAvr.c (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoPixelEsp8266.c (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoRingTopology.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoSpriteSheet.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoTiles.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/NeoTopology.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/RgbColor.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/RgbColor.h (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/RgbwColor.cpp (100%) rename {lib => lib-before-5.9.1f}/NeoPixelBus_by_Makuna/src/internal/RgbwColor.h (100%) rename {lib => lib-before-5.9.1f}/OneWire/OneWire.cpp (100%) rename {lib => lib-before-5.9.1f}/OneWire/OneWire.h (100%) rename {lib => lib-before-5.9.1f}/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde (100%) rename {lib => lib-before-5.9.1f}/OneWire/examples/DS2408_Switch/DS2408_Switch.pde (100%) rename {lib => lib-before-5.9.1f}/OneWire/examples/DS250x_PROM/DS250x_PROM.pde (100%) rename {lib => lib-before-5.9.1f}/OneWire/keywords.txt (100%) rename {lib => lib-before-5.9.1f}/OneWire/library.json (100%) rename {lib => lib-before-5.9.1f}/OneWire/library.properties (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/CHANGES.txt (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/LICENSE.txt (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/README.md (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/examples/mqtt_auth/mqtt_auth.ino (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/examples/mqtt_basic/mqtt_basic.ino (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/examples/mqtt_esp8266/mqtt_esp8266.ino (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/examples/mqtt_stream/mqtt_stream.ino (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/keywords.txt (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/library.json (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/library.properties (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/src/PubSubClient.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/src/PubSubClient.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/.gitignore (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/Makefile (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/README.md (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/connect_spec.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/keepalive_spec.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/Arduino.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/BDDTest.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/BDDTest.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/Buffer.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/Buffer.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/Client.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/IPAddress.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/IPAddress.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/ShimClient.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/ShimClient.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/Stream.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/Stream.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/lib/trace.h (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/publish_spec.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/receive_spec.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/src/subscribe_spec.cpp (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/testcases/__init__.py (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/testcases/mqtt_basic.py (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/testcases/mqtt_publish_in_callback.py (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/testcases/settings.py (100%) rename {lib => lib-before-5.9.1f}/PubSubClient/tests/testsuite.py (100%) create mode 100644 lib/ArduinoJson-5.11.2/ArduinoJson.h create mode 100644 lib/ArduinoJson-5.11.2/CHANGELOG.md create mode 100644 lib/ArduinoJson-5.11.2/LICENSE.md create mode 100644 lib/ArduinoJson-5.11.2/README.md create mode 100644 lib/ArduinoJson-5.11.2/examples/JsonGeneratorExample/JsonGeneratorExample.ino create mode 100644 lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino create mode 100644 lib/ArduinoJson-5.11.2/examples/JsonParserExample/JsonParserExample.ino create mode 100644 lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino create mode 100644 lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino create mode 100644 lib/ArduinoJson-5.11.2/examples/ProgmemExample/ProgmemExample.ino create mode 100644 lib/ArduinoJson-5.11.2/examples/StringExample/StringExample.ino create mode 100644 lib/ArduinoJson-5.11.2/keywords.txt create mode 100644 lib/ArduinoJson-5.11.2/library.properties create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson.h create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Configuration.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/Encoding.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonBufferAllocated.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonFloat.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonInteger.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantAs.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantContent.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantDefault.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantType.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/List.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListConstIterator.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListIterator.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListNode.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/NonCopyable.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ReferenceType.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/Comments.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParser.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParserImpl.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/StringWriter.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/DynamicJsonBuffer.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArray.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArrayImpl.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArraySubscript.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBuffer.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferBase.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferImpl.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObject.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectImpl.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectSubscript.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonPair.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariant.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantBase.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantCasts.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantComparisons.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantImpl.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantSubscripts.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/attributes.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/ctype.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isFloat.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/math.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseFloat.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseInteger.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DummyPrint.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/FloatParts.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/IndentedPrint.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonPrintable.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializer.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonWriter.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/Prettyfier.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StaticStringBuilder.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/StaticJsonBuffer.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/ArduinoStream.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/CharPointer.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/FlashString.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdStream.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdString.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StringTraits.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/EnableIf.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/FloatTraits.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsArray.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsBaseOf.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsChar.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsConst.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsIntegral.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSame.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsVariant.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveConst.hpp create mode 100644 lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveReference.hpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md create mode 100644 lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md create mode 100644 lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md create mode 100644 lib/IRremoteESP8266-2.2.1.02/.gitignore create mode 100644 lib/IRremoteESP8266-2.2.1.02/.gitmodules create mode 100644 lib/IRremoteESP8266-2.2.1.02/.travis.yml create mode 100644 lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg create mode 100644 lib/IRremoteESP8266-2.2.1.02/LICENSE.txt create mode 100644 lib/IRremoteESP8266-2.2.1.02/README.md create mode 100644 lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRServer/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino create mode 100644 lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/keywords.txt create mode 100644 lib/IRremoteESP8266-2.2.1.02/library.json create mode 100644 lib/IRremoteESP8266-2.2.1.02/library.properties create mode 100644 lib/IRremoteESP8266-2.2.1.02/platformio.ini create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRsend.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/IRutils.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/Makefile create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp create mode 100644 lib/IRremoteESP8266-2.2.1.02/tools/Makefile create mode 100644 lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp create mode 100644 lib/NeoPixelBus-2.2.9/.gitattributes create mode 100644 lib/NeoPixelBus-2.2.9/.gitignore create mode 100644 lib/NeoPixelBus-2.2.9/COPYING create mode 100644 lib/NeoPixelBus-2.2.9/ReadMe.md create mode 100644 lib/NeoPixelBus-2.2.9/examples/DotStarTest/DotStarTest.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/NeoPixelBrightness/NeoPixelBrightness.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/NeoPixelGamma/NeoPixelGamma.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/NeoPixelTest/NeoPixelTest.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelCylon/NeoPixelCylon.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/Strings.bmp create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/StringsW.bmp create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/Cylon.pdn create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino create mode 100644 lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino create mode 100644 lib/NeoPixelBus-2.2.9/keywords.txt create mode 100644 lib/NeoPixelBus-2.2.9/library.json create mode 100644 lib/NeoPixelBus-2.2.9/library.properties create mode 100644 lib/NeoPixelBus-2.2.9/src/NeoPixelAnimator.h create mode 100644 lib/NeoPixelBus-2.2.9/src/NeoPixelBrightnessBus.h create mode 100644 lib/NeoPixelBus-2.2.9/src/NeoPixelBus.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/DotStarAvrMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/DotStarColorFeatures.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/DotStarGenericMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/DotStarSpiMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HsbColor.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HsbColor.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HslColor.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HslColor.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNames.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/HtmlColorShortNames.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/Layouts.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoArmMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoAvrMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoBitmapFile.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoBuffer.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoBufferContext.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoBufferMethods.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoColorFeatures.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoDib.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoEase.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoEspBitBangMethod.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoHueBlend.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoMosaic.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAnimator.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAvr.c create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoPixelEsp.c create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoRingTopology.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoSpriteSheet.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoTiles.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/NeoTopology.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/RgbColor.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/RgbColor.h create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.cpp create mode 100644 lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.h create mode 100644 lib/OneWire-2.3.3.06/OneWire.cpp create mode 100644 lib/OneWire-2.3.3.06/OneWire.h create mode 100644 lib/OneWire-2.3.3.06/examples/DS18x20_Temperature/DS18x20_Temperature.pde create mode 100644 lib/OneWire-2.3.3.06/examples/DS2408_Switch/DS2408_Switch.pde create mode 100644 lib/OneWire-2.3.3.06/examples/DS250x_PROM/DS250x_PROM.pde create mode 100644 lib/OneWire-2.3.3.06/keywords.txt create mode 100644 lib/OneWire-2.3.3.06/library.json create mode 100644 lib/OneWire-2.3.3.06/library.properties create mode 100644 lib/PubSubClient-2.6.09/.gitignore create mode 100644 lib/PubSubClient-2.6.09/.travis.yml create mode 100644 lib/PubSubClient-2.6.09/CHANGES.txt create mode 100644 lib/PubSubClient-2.6.09/LICENSE.txt create mode 100644 lib/PubSubClient-2.6.09/README.md create mode 100644 lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino create mode 100644 lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino create mode 100644 lib/PubSubClient-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino create mode 100644 lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino create mode 100644 lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino create mode 100644 lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino create mode 100644 lib/PubSubClient-2.6.09/keywords.txt create mode 100644 lib/PubSubClient-2.6.09/library.json create mode 100644 lib/PubSubClient-2.6.09/library.properties create mode 100644 lib/PubSubClient-2.6.09/src/PubSubClient.cpp create mode 100644 lib/PubSubClient-2.6.09/src/PubSubClient.h create mode 100644 lib/PubSubClient-2.6.09/tests/.gitignore create mode 100644 lib/PubSubClient-2.6.09/tests/Makefile create mode 100644 lib/PubSubClient-2.6.09/tests/README.md create mode 100644 lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/Client.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/Stream.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/lib/trace.h create mode 100644 lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp create mode 100644 lib/PubSubClient-2.6.09/tests/testcases/__init__.py create mode 100644 lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py create mode 100644 lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py create mode 100644 lib/PubSubClient-2.6.09/tests/testcases/settings.py create mode 100644 lib/PubSubClient-2.6.09/tests/testsuite.py create mode 100644 lib/readme.txt create mode 100644 sonoff/xsns_12_ads1115_i2cdev.ino diff --git a/README.md b/README.md index a2ff09975..985280efd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.9.1e** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. +Current version is **5.9.1f** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions diff --git a/lib/ArduinoJson/ArduinoJson.h b/lib-before-5.9.1f/ArduinoJson/ArduinoJson.h similarity index 100% rename from lib/ArduinoJson/ArduinoJson.h rename to lib-before-5.9.1f/ArduinoJson/ArduinoJson.h diff --git a/lib/ArduinoJson/CHANGELOG.md b/lib-before-5.9.1f/ArduinoJson/CHANGELOG.md similarity index 100% rename from lib/ArduinoJson/CHANGELOG.md rename to lib-before-5.9.1f/ArduinoJson/CHANGELOG.md diff --git a/lib/ArduinoJson/CMakeLists.txt b/lib-before-5.9.1f/ArduinoJson/CMakeLists.txt similarity index 100% rename from lib/ArduinoJson/CMakeLists.txt rename to lib-before-5.9.1f/ArduinoJson/CMakeLists.txt diff --git a/lib/ArduinoJson/LICENSE.md b/lib-before-5.9.1f/ArduinoJson/LICENSE.md similarity index 100% rename from lib/ArduinoJson/LICENSE.md rename to lib-before-5.9.1f/ArduinoJson/LICENSE.md diff --git a/lib/ArduinoJson/README.md b/lib-before-5.9.1f/ArduinoJson/README.md similarity index 100% rename from lib/ArduinoJson/README.md rename to lib-before-5.9.1f/ArduinoJson/README.md diff --git a/lib/ArduinoJson/appveyor.yml b/lib-before-5.9.1f/ArduinoJson/appveyor.yml similarity index 100% rename from lib/ArduinoJson/appveyor.yml rename to lib-before-5.9.1f/ArduinoJson/appveyor.yml diff --git a/lib/ArduinoJson/examples/IndentedPrintExample/IndentedPrintExample.ino b/lib-before-5.9.1f/ArduinoJson/examples/IndentedPrintExample/IndentedPrintExample.ino similarity index 100% rename from lib/ArduinoJson/examples/IndentedPrintExample/IndentedPrintExample.ino rename to lib-before-5.9.1f/ArduinoJson/examples/IndentedPrintExample/IndentedPrintExample.ino diff --git a/lib/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino b/lib-before-5.9.1f/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino similarity index 100% rename from lib/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino rename to lib-before-5.9.1f/ArduinoJson/examples/JsonGeneratorExample/JsonGeneratorExample.ino diff --git a/lib/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino b/lib-before-5.9.1f/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino similarity index 100% rename from lib/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino rename to lib-before-5.9.1f/ArduinoJson/examples/JsonHttpClient/JsonHttpClient.ino diff --git a/lib/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino b/lib-before-5.9.1f/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino similarity index 100% rename from lib/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino rename to lib-before-5.9.1f/ArduinoJson/examples/JsonParserExample/JsonParserExample.ino diff --git a/lib/ArduinoJson/examples/JsonServer/JsonServer.ino b/lib-before-5.9.1f/ArduinoJson/examples/JsonServer/JsonServer.ino similarity index 100% rename from lib/ArduinoJson/examples/JsonServer/JsonServer.ino rename to lib-before-5.9.1f/ArduinoJson/examples/JsonServer/JsonServer.ino diff --git a/lib/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino b/lib-before-5.9.1f/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino similarity index 100% rename from lib/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino rename to lib-before-5.9.1f/ArduinoJson/examples/JsonUdpBeacon/JsonUdpBeacon.ino diff --git a/lib/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino b/lib-before-5.9.1f/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino similarity index 100% rename from lib/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino rename to lib-before-5.9.1f/ArduinoJson/examples/ProgmemExample/ProgmemExample.ino diff --git a/lib/ArduinoJson/examples/StringExample/StringExample.ino b/lib-before-5.9.1f/ArduinoJson/examples/StringExample/StringExample.ino similarity index 100% rename from lib/ArduinoJson/examples/StringExample/StringExample.ino rename to lib-before-5.9.1f/ArduinoJson/examples/StringExample/StringExample.ino diff --git a/lib/ArduinoJson/fuzzing/Makefile b/lib-before-5.9.1f/ArduinoJson/fuzzing/Makefile similarity index 100% rename from lib/ArduinoJson/fuzzing/Makefile rename to lib-before-5.9.1f/ArduinoJson/fuzzing/Makefile diff --git a/lib/ArduinoJson/fuzzing/fuzz.sh b/lib-before-5.9.1f/ArduinoJson/fuzzing/fuzz.sh similarity index 100% rename from lib/ArduinoJson/fuzzing/fuzz.sh rename to lib-before-5.9.1f/ArduinoJson/fuzzing/fuzz.sh diff --git a/lib/ArduinoJson/fuzzing/fuzzer.cpp b/lib-before-5.9.1f/ArduinoJson/fuzzing/fuzzer.cpp similarity index 100% rename from lib/ArduinoJson/fuzzing/fuzzer.cpp rename to lib-before-5.9.1f/ArduinoJson/fuzzing/fuzzer.cpp diff --git a/lib/ArduinoJson/fuzzing/my_corpus/.gitignore b/lib-before-5.9.1f/ArduinoJson/fuzzing/my_corpus/.gitignore similarity index 100% rename from lib/ArduinoJson/fuzzing/my_corpus/.gitignore rename to lib-before-5.9.1f/ArduinoJson/fuzzing/my_corpus/.gitignore diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/ArduinoJson.json b/lib-before-5.9.1f/ArduinoJson/fuzzing/seed_corpus/ArduinoJson.json similarity index 100% rename from lib/ArduinoJson/fuzzing/seed_corpus/ArduinoJson.json rename to lib-before-5.9.1f/ArduinoJson/fuzzing/seed_corpus/ArduinoJson.json diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json b/lib-before-5.9.1f/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json similarity index 100% rename from lib/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json rename to lib-before-5.9.1f/ArduinoJson/fuzzing/seed_corpus/OpenWeatherMap.json diff --git a/lib/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json b/lib-before-5.9.1f/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json similarity index 100% rename from lib/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json rename to lib-before-5.9.1f/ArduinoJson/fuzzing/seed_corpus/WeatherUnderground.json diff --git a/lib/ArduinoJson/include/ArduinoJson.h b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson.h similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson.h rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson.h diff --git a/lib/ArduinoJson/include/ArduinoJson.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Configuration.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Configuration.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Configuration.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Configuration.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/Encoding.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/Encoding.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/Encoding.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/Encoding.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonBufferAllocated.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonBufferAllocated.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonBufferAllocated.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonBufferAllocated.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonFloat.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonFloat.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonFloat.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonFloat.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonInteger.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonInteger.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonInteger.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonInteger.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantAs.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantAs.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantAs.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantAs.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantComparer.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantComparer.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantComparer.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantComparer.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantContent.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantContent.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantContent.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantContent.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantDefault.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantDefault.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantDefault.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantDefault.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantType.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantType.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/JsonVariantType.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/JsonVariantType.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/List.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/List.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/List.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/List.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/ListConstIterator.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ListConstIterator.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/ListConstIterator.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ListConstIterator.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/ListIterator.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ListIterator.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/ListIterator.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ListIterator.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/ListNode.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ListNode.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/ListNode.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ListNode.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/Parse.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/Parse.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/Parse.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/Parse.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/ReferenceType.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ReferenceType.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/ReferenceType.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ReferenceType.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Data/ValueSetter.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ValueSetter.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Data/ValueSetter.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Data/ValueSetter.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Deserialization/Comments.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/Comments.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Deserialization/Comments.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/Comments.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Deserialization/JsonParser.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/JsonParser.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Deserialization/JsonParser.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/JsonParser.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Deserialization/JsonParserImpl.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/JsonParserImpl.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Deserialization/JsonParserImpl.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/JsonParserImpl.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Deserialization/StringWriter.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/StringWriter.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Deserialization/StringWriter.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Deserialization/StringWriter.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/DynamicJsonBuffer.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/DynamicJsonBuffer.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/DynamicJsonBuffer.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/DynamicJsonBuffer.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonArray.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonArray.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonArray.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonArray.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonArrayImpl.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonArrayImpl.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonArrayImpl.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonArrayImpl.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonArraySubscript.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonArraySubscript.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonArraySubscript.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonArraySubscript.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonBuffer.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonBuffer.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonBuffer.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonBuffer.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonBufferBase.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonBufferBase.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonBufferBase.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonBufferBase.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonBufferImpl.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonBufferImpl.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonBufferImpl.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonBufferImpl.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonObject.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonObject.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonObject.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonObject.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonObjectImpl.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonObjectImpl.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonObjectImpl.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonObjectImpl.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonObjectSubscript.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonObjectSubscript.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonObjectSubscript.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonObjectSubscript.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonPair.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonPair.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonPair.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonPair.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonVariant.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariant.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonVariant.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariant.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonVariantBase.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariantBase.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonVariantBase.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariantBase.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonVariantComparisons.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariantComparisons.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonVariantComparisons.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariantComparisons.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/JsonVariantImpl.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariantImpl.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/JsonVariantImpl.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/JsonVariantImpl.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Polyfills/attributes.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Polyfills/attributes.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Polyfills/attributes.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Polyfills/attributes.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Polyfills/math.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Polyfills/math.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Polyfills/math.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Polyfills/math.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Polyfills/normalize.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Polyfills/normalize.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Polyfills/normalize.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Polyfills/normalize.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Print.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Print.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Print.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Print.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/RawJson.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/RawJson.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/RawJson.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/RawJson.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/DummyPrint.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/DummyPrint.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/DummyPrint.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/DummyPrint.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/DynamicStringBuilder.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/DynamicStringBuilder.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/DynamicStringBuilder.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/DynamicStringBuilder.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/IndentedPrint.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/IndentedPrint.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/IndentedPrint.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/IndentedPrint.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/JsonPrintable.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonPrintable.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/JsonPrintable.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonPrintable.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializer.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializer.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializer.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializer.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializerImpl.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializerImpl.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializerImpl.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonSerializerImpl.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/JsonWriter.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonWriter.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/JsonWriter.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/JsonWriter.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/Prettyfier.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/Prettyfier.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/Prettyfier.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/Prettyfier.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/StaticStringBuilder.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/StaticStringBuilder.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/StaticStringBuilder.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/StaticStringBuilder.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/Serialization/StreamPrintAdapter.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/StreamPrintAdapter.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/Serialization/StreamPrintAdapter.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/Serialization/StreamPrintAdapter.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/StaticJsonBuffer.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StaticJsonBuffer.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/StaticJsonBuffer.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StaticJsonBuffer.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/StringTraits/ArduinoStream.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/ArduinoStream.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/StringTraits/ArduinoStream.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/ArduinoStream.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/StringTraits/CharPointer.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/CharPointer.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/StringTraits/CharPointer.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/CharPointer.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/StringTraits/FlashString.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/FlashString.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/StringTraits/FlashString.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/FlashString.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/StringTraits/StdStream.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/StdStream.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/StringTraits/StdStream.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/StdStream.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/StringTraits/StdString.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/StdString.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/StringTraits/StdString.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/StdString.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/StringTraits/StringTraits.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/StringTraits.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/StringTraits/StringTraits.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/StringTraits/StringTraits.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/EnableIf.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/EnableIf.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/EnableIf.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/EnableIf.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsArray.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsArray.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsArray.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsArray.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsBaseOf.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsBaseOf.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsBaseOf.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsBaseOf.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsChar.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsChar.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsChar.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsChar.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsConst.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsConst.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsConst.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsConst.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsIntegral.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsIntegral.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsIntegral.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsIntegral.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsSame.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsSame.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsSame.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsSame.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsSignedIntegral.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsSignedIntegral.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsSignedIntegral.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsSignedIntegral.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveConst.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveConst.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveConst.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveConst.hpp diff --git a/lib/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveReference.hpp b/lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveReference.hpp similarity index 100% rename from lib/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveReference.hpp rename to lib-before-5.9.1f/ArduinoJson/include/ArduinoJson/TypeTraits/RemoveReference.hpp diff --git a/lib/ArduinoJson/keywords.txt b/lib-before-5.9.1f/ArduinoJson/keywords.txt similarity index 100% rename from lib/ArduinoJson/keywords.txt rename to lib-before-5.9.1f/ArduinoJson/keywords.txt diff --git a/lib/ArduinoJson/library.json b/lib-before-5.9.1f/ArduinoJson/library.json similarity index 100% rename from lib/ArduinoJson/library.json rename to lib-before-5.9.1f/ArduinoJson/library.json diff --git a/lib/ArduinoJson/library.properties b/lib-before-5.9.1f/ArduinoJson/library.properties similarity index 100% rename from lib/ArduinoJson/library.properties rename to lib-before-5.9.1f/ArduinoJson/library.properties diff --git a/lib/ArduinoJson/scripts/build-arduino-package.sh b/lib-before-5.9.1f/ArduinoJson/scripts/build-arduino-package.sh similarity index 100% rename from lib/ArduinoJson/scripts/build-arduino-package.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/build-arduino-package.sh diff --git a/lib/ArduinoJson/scripts/cpplint.sh b/lib-before-5.9.1f/ArduinoJson/scripts/cpplint.sh similarity index 100% rename from lib/ArduinoJson/scripts/cpplint.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/cpplint.sh diff --git a/lib/ArduinoJson/scripts/create-build-envs.sh b/lib-before-5.9.1f/ArduinoJson/scripts/create-build-envs.sh similarity index 100% rename from lib/ArduinoJson/scripts/create-build-envs.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/create-build-envs.sh diff --git a/lib/ArduinoJson/scripts/create-size-graph.sh b/lib-before-5.9.1f/ArduinoJson/scripts/create-size-graph.sh similarity index 100% rename from lib/ArduinoJson/scripts/create-size-graph.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/create-size-graph.sh diff --git a/lib/ArduinoJson/scripts/format-code.sh b/lib-before-5.9.1f/ArduinoJson/scripts/format-code.sh similarity index 100% rename from lib/ArduinoJson/scripts/format-code.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/format-code.sh diff --git a/lib/ArduinoJson/scripts/oss-fuzz/.gitignore b/lib-before-5.9.1f/ArduinoJson/scripts/oss-fuzz/.gitignore similarity index 100% rename from lib/ArduinoJson/scripts/oss-fuzz/.gitignore rename to lib-before-5.9.1f/ArduinoJson/scripts/oss-fuzz/.gitignore diff --git a/lib/ArduinoJson/scripts/oss-fuzz/Vagrantfile b/lib-before-5.9.1f/ArduinoJson/scripts/oss-fuzz/Vagrantfile similarity index 100% rename from lib/ArduinoJson/scripts/oss-fuzz/Vagrantfile rename to lib-before-5.9.1f/ArduinoJson/scripts/oss-fuzz/Vagrantfile diff --git a/lib/ArduinoJson/scripts/run-tests.sh b/lib-before-5.9.1f/ArduinoJson/scripts/run-tests.sh similarity index 100% rename from lib/ArduinoJson/scripts/run-tests.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/run-tests.sh diff --git a/lib/ArduinoJson/scripts/travis/arduino.sh b/lib-before-5.9.1f/ArduinoJson/scripts/travis/arduino.sh similarity index 100% rename from lib/ArduinoJson/scripts/travis/arduino.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/travis/arduino.sh diff --git a/lib/ArduinoJson/scripts/travis/cmake.sh b/lib-before-5.9.1f/ArduinoJson/scripts/travis/cmake.sh similarity index 100% rename from lib/ArduinoJson/scripts/travis/cmake.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/travis/cmake.sh diff --git a/lib/ArduinoJson/scripts/travis/coverage.sh b/lib-before-5.9.1f/ArduinoJson/scripts/travis/coverage.sh similarity index 100% rename from lib/ArduinoJson/scripts/travis/coverage.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/travis/coverage.sh diff --git a/lib/ArduinoJson/scripts/travis/platformio.sh b/lib-before-5.9.1f/ArduinoJson/scripts/travis/platformio.sh similarity index 100% rename from lib/ArduinoJson/scripts/travis/platformio.sh rename to lib-before-5.9.1f/ArduinoJson/scripts/travis/platformio.sh diff --git a/lib/ArduinoJson/test/CMakeLists.txt b/lib-before-5.9.1f/ArduinoJson/test/CMakeLists.txt similarity index 100% rename from lib/ArduinoJson/test/CMakeLists.txt rename to lib-before-5.9.1f/ArduinoJson/test/CMakeLists.txt diff --git a/lib/ArduinoJson/test/Deprecated_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/Deprecated_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/Deprecated_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/Deprecated_Tests.cpp diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer_Array_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_Array_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/DynamicJsonBuffer_Array_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_Array_Tests.cpp diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer_Basic_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_Basic_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/DynamicJsonBuffer_Basic_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_Basic_Tests.cpp diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer_NoMemory_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_NoMemory_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/DynamicJsonBuffer_NoMemory_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_NoMemory_Tests.cpp diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer_Object_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_Object_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/DynamicJsonBuffer_Object_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_Object_Tests.cpp diff --git a/lib/ArduinoJson/test/DynamicJsonBuffer_String_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_String_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/DynamicJsonBuffer_String_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/DynamicJsonBuffer_String_Tests.cpp diff --git a/lib/ArduinoJson/test/GbathreeBug.cpp b/lib-before-5.9.1f/ArduinoJson/test/GbathreeBug.cpp similarity index 100% rename from lib/ArduinoJson/test/GbathreeBug.cpp rename to lib-before-5.9.1f/ArduinoJson/test/GbathreeBug.cpp diff --git a/lib/ArduinoJson/test/IntegrationTests.cpp b/lib-before-5.9.1f/ArduinoJson/test/IntegrationTests.cpp similarity index 100% rename from lib/ArduinoJson/test/IntegrationTests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/IntegrationTests.cpp diff --git a/lib/ArduinoJson/test/Issue10.cpp b/lib-before-5.9.1f/ArduinoJson/test/Issue10.cpp similarity index 100% rename from lib/ArduinoJson/test/Issue10.cpp rename to lib-before-5.9.1f/ArduinoJson/test/Issue10.cpp diff --git a/lib/ArduinoJson/test/Issue214.cpp b/lib-before-5.9.1f/ArduinoJson/test/Issue214.cpp similarity index 100% rename from lib/ArduinoJson/test/Issue214.cpp rename to lib-before-5.9.1f/ArduinoJson/test/Issue214.cpp diff --git a/lib/ArduinoJson/test/Issue34.cpp b/lib-before-5.9.1f/ArduinoJson/test/Issue34.cpp similarity index 100% rename from lib/ArduinoJson/test/Issue34.cpp rename to lib-before-5.9.1f/ArduinoJson/test/Issue34.cpp diff --git a/lib/ArduinoJson/test/Issue90.cpp b/lib-before-5.9.1f/ArduinoJson/test/Issue90.cpp similarity index 100% rename from lib/ArduinoJson/test/Issue90.cpp rename to lib-before-5.9.1f/ArduinoJson/test/Issue90.cpp diff --git a/lib/ArduinoJson/test/JsonArray_Add_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_Add_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_Add_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_Add_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_Basic_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_Basic_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_Basic_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_Basic_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_CopyFrom_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_CopyFrom_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_CopyFrom_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_CopyFrom_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_CopyTo_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_CopyTo_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_CopyTo_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_CopyTo_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_Invalid_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_Invalid_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_Invalid_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_Invalid_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_Iterator_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_Iterator_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_Iterator_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_Iterator_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_PrettyPrintTo_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_PrettyPrintTo_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_PrettyPrintTo_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_PrettyPrintTo_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_PrintTo_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_PrintTo_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_PrintTo_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_PrintTo_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_Remove_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_Remove_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_Remove_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_Remove_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_Set_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_Set_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_Set_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_Set_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonArray_Subscript_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonArray_Subscript_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonArray_Subscript_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonArray_Subscript_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_Basic_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_Basic_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_Basic_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_Basic_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_ContainsKey_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_ContainsKey_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_ContainsKey_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_ContainsKey_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_Get_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_Get_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_Get_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_Get_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_Invalid_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_Invalid_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_Invalid_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_Invalid_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_Iterator_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_Iterator_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_Iterator_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_Iterator_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_PrettyPrintTo_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_PrettyPrintTo_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_PrettyPrintTo_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_PrettyPrintTo_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_PrintTo_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_PrintTo_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_PrintTo_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_PrintTo_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_Remove_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_Remove_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_Remove_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_Remove_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_Set_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_Set_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_Set_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_Set_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonObject_Subscript_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonObject_Subscript_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonObject_Subscript_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonObject_Subscript_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonParser_Array_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonParser_Array_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonParser_Array_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonParser_Array_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonParser_Nested_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonParser_Nested_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonParser_Nested_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonParser_Nested_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonParser_NestingLimit_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonParser_NestingLimit_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonParser_NestingLimit_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonParser_NestingLimit_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonParser_Object_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonParser_Object_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonParser_Object_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonParser_Object_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonParser_Variant_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonParser_Variant_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonParser_Variant_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonParser_Variant_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_As_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_As_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_As_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_As_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_Comparison_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Comparison_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_Comparison_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Comparison_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_Copy_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Copy_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_Copy_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Copy_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_Is_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Is_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_Is_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Is_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_PrintTo_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_PrintTo_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_PrintTo_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_PrintTo_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_Storage_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Storage_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_Storage_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Storage_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_Subscript_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Subscript_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_Subscript_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Subscript_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_Success_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Success_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_Success_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Success_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonVariant_Undefined_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Undefined_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonVariant_Undefined_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonVariant_Undefined_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonWriter_WriteFloat_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonWriter_WriteFloat_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonWriter_WriteFloat_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonWriter_WriteFloat_Tests.cpp diff --git a/lib/ArduinoJson/test/JsonWriter_WriteString_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/JsonWriter_WriteString_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/JsonWriter_WriteString_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/JsonWriter_WriteString_Tests.cpp diff --git a/lib/ArduinoJson/test/StaticJsonBuffer_Basic_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_Basic_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/StaticJsonBuffer_Basic_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_Basic_Tests.cpp diff --git a/lib/ArduinoJson/test/StaticJsonBuffer_CreateArray_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_CreateArray_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/StaticJsonBuffer_CreateArray_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_CreateArray_Tests.cpp diff --git a/lib/ArduinoJson/test/StaticJsonBuffer_CreateObject_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_CreateObject_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/StaticJsonBuffer_CreateObject_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_CreateObject_Tests.cpp diff --git a/lib/ArduinoJson/test/StaticJsonBuffer_ParseArray_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_ParseArray_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/StaticJsonBuffer_ParseArray_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_ParseArray_Tests.cpp diff --git a/lib/ArduinoJson/test/StaticJsonBuffer_ParseObject_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_ParseObject_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/StaticJsonBuffer_ParseObject_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_ParseObject_Tests.cpp diff --git a/lib/ArduinoJson/test/StaticJsonBuffer_String_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_String_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/StaticJsonBuffer_String_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StaticJsonBuffer_String_Tests.cpp diff --git a/lib/ArduinoJson/test/StdStream_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StdStream_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/StdStream_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StdStream_Tests.cpp diff --git a/lib/ArduinoJson/test/StringBuilderTests.cpp b/lib-before-5.9.1f/ArduinoJson/test/StringBuilderTests.cpp similarity index 100% rename from lib/ArduinoJson/test/StringBuilderTests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/StringBuilderTests.cpp diff --git a/lib/ArduinoJson/test/String_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/String_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/String_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/String_Tests.cpp diff --git a/lib/ArduinoJson/test/TypeTraits_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/TypeTraits_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/TypeTraits_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/TypeTraits_Tests.cpp diff --git a/lib/ArduinoJson/test/UnsignedChar_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/UnsignedChar_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/UnsignedChar_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/UnsignedChar_Tests.cpp diff --git a/lib/ArduinoJson/test/VariableLengthArray_Tests.cpp b/lib-before-5.9.1f/ArduinoJson/test/VariableLengthArray_Tests.cpp similarity index 100% rename from lib/ArduinoJson/test/VariableLengthArray_Tests.cpp rename to lib-before-5.9.1f/ArduinoJson/test/VariableLengthArray_Tests.cpp diff --git a/lib/ArduinoJson/test/gtest.cmake b/lib-before-5.9.1f/ArduinoJson/test/gtest.cmake similarity index 100% rename from lib/ArduinoJson/test/gtest.cmake rename to lib-before-5.9.1f/ArduinoJson/test/gtest.cmake diff --git a/lib/ArduinoJson/third-party/cpplint/cpplint.py b/lib-before-5.9.1f/ArduinoJson/third-party/cpplint/cpplint.py similarity index 100% rename from lib/ArduinoJson/third-party/cpplint/cpplint.py rename to lib-before-5.9.1f/ArduinoJson/third-party/cpplint/cpplint.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/CHANGES b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/CHANGES similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/CHANGES rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/CHANGES diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/CMakeLists.txt b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/CMakeLists.txt similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/CMakeLists.txt rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/CMakeLists.txt diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/CONTRIBUTORS b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/CONTRIBUTORS similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/CONTRIBUTORS rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/CONTRIBUTORS diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/LICENSE b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/LICENSE similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/LICENSE rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/LICENSE diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/Makefile.am b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/Makefile.am similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/Makefile.am rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/Makefile.am diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/Makefile.in b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/Makefile.in similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/Makefile.in rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/Makefile.in diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/README b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/README similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/README rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/README diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/aclocal.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/aclocal.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/aclocal.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/aclocal.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.guess b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.guess similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.guess rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.guess diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.h.in b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.h.in similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.h.in rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.h.in diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.sub b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.sub similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.sub rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/config.sub diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/depcomp b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/depcomp similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/depcomp rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/depcomp diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/install-sh b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/install-sh similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/install-sh rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/install-sh diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/ltmain.sh b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/ltmain.sh similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/ltmain.sh rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/ltmain.sh diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/missing b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/missing similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/build-aux/missing rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/build-aux/missing diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/cmake/internal_utils.cmake b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/cmake/internal_utils.cmake similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/cmake/internal_utils.cmake rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/cmake/internal_utils.cmake diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.cbproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.cbproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.cbproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.cbproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.groupproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.groupproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.groupproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest.groupproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_all.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_all.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_all.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_all.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_link.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_link.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_link.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_link.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_main.cbproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_main.cbproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_main.cbproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_main.cbproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_unittest.cbproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_unittest.cbproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_unittest.cbproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/codegear/gtest_unittest.cbproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/configure b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/configure similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/configure rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/configure diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/configure.ac b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/configure.ac similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/configure.ac rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/configure.ac diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest-all.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest-all.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest-all.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest-all.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest_main.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest_main.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest_main.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/fused-src/gtest/gtest_main.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-death-test.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-death-test.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-death-test.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-death-test.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-message.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-message.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-message.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-message.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h.pump b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h.pump similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h.pump rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-param-test.h.pump diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-printers.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-printers.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-printers.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-printers.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-spi.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-spi.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-spi.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-spi.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-test-part.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-test-part.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-test-part.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-test-part.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-typed-test.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-typed-test.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-typed-test.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest-typed-test.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_pred_impl.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_pred_impl.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_pred_impl.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_pred_impl.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_prod.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_prod.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_prod.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/gtest_prod.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-filepath.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-filepath.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-filepath.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-filepath.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-internal.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-param-util.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-port.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-string.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-string.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-string.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-string.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/m4/acx_pthread.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/acx_pthread.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/m4/acx_pthread.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/acx_pthread.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/m4/gtest.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/gtest.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/m4/gtest.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/gtest.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/m4/libtool.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/libtool.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/m4/libtool.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/libtool.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/m4/ltoptions.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/ltoptions.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/m4/ltoptions.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/ltoptions.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/m4/ltsugar.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/ltsugar.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/m4/ltsugar.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/ltsugar.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/m4/ltversion.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/ltversion.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/m4/ltversion.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/ltversion.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/m4/lt~obsolete.m4 b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/lt~obsolete.m4 similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/m4/lt~obsolete.m4 rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/m4/lt~obsolete.m4 diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/make/Makefile b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/make/Makefile similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/make/Makefile rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/make/Makefile diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.sln b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.sln similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.sln rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.sln diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest-md.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.sln b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.sln similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.sln rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.sln diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main-md.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main-md.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main-md.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main-md.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_main.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test-md.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test-md.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test-md.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test-md.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_prod_test.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest-md.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest-md.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest-md.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest-md.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest.vcproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest.vcproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest.vcproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/msvc/gtest_unittest.vcproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/prime_tables.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/prime_tables.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/prime_tables.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/prime_tables.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample1.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample10_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample10_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample10_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample10_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample1_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample1_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample1_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample1_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample2.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample2_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample2_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample2_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample2_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample3-inl.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample3-inl.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample3-inl.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample3-inl.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample3_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample3_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample3_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample3_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample4.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample4_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample4_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample4_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample4_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample5_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample5_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample5_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample5_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample6_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample6_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample6_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample6_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample7_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample7_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample7_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample7_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample8_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample8_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample8_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample8_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample9_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample9_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/samples/sample9_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/samples/sample9_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/scripts/fuse_gtest_files.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/fuse_gtest_files.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/scripts/fuse_gtest_files.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/fuse_gtest_files.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/scripts/gen_gtest_pred_impl.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/gen_gtest_pred_impl.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/scripts/gen_gtest_pred_impl.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/gen_gtest_pred_impl.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/scripts/gtest-config.in b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/gtest-config.in similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/scripts/gtest-config.in rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/gtest-config.in diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/scripts/pump.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/pump.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/scripts/pump.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/pump.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/scripts/test/Makefile b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/test/Makefile similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/scripts/test/Makefile rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/scripts/test/Makefile diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-all.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-all.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-all.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-all.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-death-test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-death-test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-death-test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-death-test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-filepath.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-filepath.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-filepath.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-filepath.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-internal-inl.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-internal-inl.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-internal-inl.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-internal-inl.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-port.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-port.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-port.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-port.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-printers.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-printers.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-printers.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-printers.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-test-part.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-test-part.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-test-part.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-test-part.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-typed-test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-typed-test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest-typed-test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest-typed-test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest_main.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest_main.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/src/gtest_main.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/src/gtest_main.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_ex_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_ex_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_ex_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_ex_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-death-test_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-filepath_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-filepath_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-filepath_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-filepath_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-linked_ptr_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-linked_ptr_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-linked_ptr_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-linked_ptr_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-listener_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-listener_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-listener_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-listener_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-message_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-message_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-message_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-message_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-options_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-options_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-options_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-options_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test2_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test2_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test2_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test2_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-param-test_test.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-port_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-port_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-port_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-port_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-printers_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-printers_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-printers_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-printers_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-test-part_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-test-part_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-test-part_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-test-part_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-tuple_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-tuple_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-tuple_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-tuple_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test2_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test2_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test2_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test2_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-typed-test_test.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-unittest-api_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-unittest-api_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest-unittest-api_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest-unittest-api_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_all_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_all_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_all_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_all_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_break_on_failure_unittest_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_catch_exceptions_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_color_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_env_var_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_environment_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_environment_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_environment_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_environment_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_filter_unittest_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_help_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_list_tests_unittest_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_main_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_main_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_main_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_main_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_no_test_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_no_test_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_no_test_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_no_test_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_golden_lin.txt b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_golden_lin.txt similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_golden_lin.txt rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_output_test_golden_lin.txt diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_pred_impl_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_pred_impl_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_pred_impl_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_pred_impl_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_premature_exit_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_premature_exit_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_premature_exit_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_premature_exit_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_prod_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_prod_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_prod_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_prod_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_repeat_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_repeat_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_repeat_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_repeat_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_shuffle_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_sole_header_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_sole_header_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_sole_header_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_sole_header_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_stress_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_stress_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_stress_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_stress_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_test_utils.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_test_utils.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_test_utils.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_test_utils.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_ex_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_ex_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_ex_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_ex_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_throw_on_failure_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_uninitialized_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_unittest.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_unittest.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_unittest.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_unittest.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile1_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile1_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile1_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile1_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile2_test_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile2_test_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile2_test_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfile2_test_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfiles_test.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfiles_test.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfiles_test.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_outfiles_test.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest_.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest_.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest_.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_output_unittest_.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_test_utils.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_test_utils.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_test_utils.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/gtest_xml_test_utils.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/production.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/production.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/production.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/production.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/test/production.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/production.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/test/production.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/test/production.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/DebugProject.xcconfig b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/DebugProject.xcconfig similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/DebugProject.xcconfig rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/DebugProject.xcconfig diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/FrameworkTarget.xcconfig b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/FrameworkTarget.xcconfig similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/FrameworkTarget.xcconfig rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/FrameworkTarget.xcconfig diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/General.xcconfig b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/General.xcconfig similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/General.xcconfig rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/General.xcconfig diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/ReleaseProject.xcconfig b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/ReleaseProject.xcconfig similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/ReleaseProject.xcconfig rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/ReleaseProject.xcconfig diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/StaticLibraryTarget.xcconfig b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/StaticLibraryTarget.xcconfig similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/StaticLibraryTarget.xcconfig rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/StaticLibraryTarget.xcconfig diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/TestTarget.xcconfig b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/TestTarget.xcconfig similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/TestTarget.xcconfig rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Config/TestTarget.xcconfig diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Resources/Info.plist b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Resources/Info.plist similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Resources/Info.plist rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Resources/Info.plist diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/Info.plist b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/Info.plist similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/Info.plist rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/Info.plist diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/runtests.sh b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/runtests.sh similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/runtests.sh rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/runtests.sh diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.h b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.h similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.h rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget.h diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget_test.cc b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget_test.cc similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget_test.cc rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Samples/FrameworkSample/widget_test.cc diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/runtests.sh b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/runtests.sh similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/runtests.sh rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/runtests.sh diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/versiongenerate.py b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/versiongenerate.py similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/versiongenerate.py rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/Scripts/versiongenerate.py diff --git a/lib/ArduinoJson/third-party/gtest-1.7.0/xcode/gtest.xcodeproj/project.pbxproj b/lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/gtest.xcodeproj/project.pbxproj similarity index 100% rename from lib/ArduinoJson/third-party/gtest-1.7.0/xcode/gtest.xcodeproj/project.pbxproj rename to lib-before-5.9.1f/ArduinoJson/third-party/gtest-1.7.0/xcode/gtest.xcodeproj/project.pbxproj diff --git a/lib-before-5.9.1f/I2Cdevlib-ADS1115/.library.json b/lib-before-5.9.1f/I2Cdevlib-ADS1115/.library.json new file mode 100644 index 000000000..42719db38 --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-ADS1115/.library.json @@ -0,0 +1,40 @@ +{ + "name": "I2Cdevlib-ADS1115", + "repository": { + "url": "https://github.com/jrowberg/i2cdevlib.git", + "type": "git" + }, + "platforms": [ + "atmelavr" + ], + "frameworks": [ + "arduino" + ], + "dependencies": { + "frameworks": "arduino", + "name": "I2Cdevlib-Core" + }, + "export": { + "include": "Arduino/ADS1115" + }, + "version": "3b4c8bda90", + "authors": [ + { + "maintainer": false, + "name": "Jeff Rowberg", + "url": "https://github.com/jrowberg", + "email": "jeff@rowberg.net" + } + ], + "keywords": [ + "i2c", + "comparator", + "reference", + "pga", + "oscillator", + "mux", + "i2cdevlib" + ], + "id": 95, + "description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference" +} \ No newline at end of file diff --git a/lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.cpp b/lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.cpp new file mode 100644 index 000000000..c3d7e873e --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.cpp @@ -0,0 +1,649 @@ +// I2Cdev library collection - ADS1115 I2C device class +// Based on Texas Instruments ADS1113/4/5 datasheet, May 2009 (SBAS444B, revised October 2009) +// Note that the ADS1115 uses 16-bit registers, not 8-bit registers. +// 8/2/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2013-05-05 - Add debug information. Rename methods to match datasheet. +// 2011-11-06 - added getVoltage, F. Farzanegan +// 2011-10-29 - added getDifferentialx() methods, F. Farzanegan +// 2011-08-02 - initial release +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation 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 +furnished 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 FOR 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 "ADS1115.h" + +/** Default constructor, uses default I2C address. + * @see ADS1115_DEFAULT_ADDRESS + */ +ADS1115::ADS1115() { + devAddr = ADS1115_DEFAULT_ADDRESS; +} + +/** Specific address constructor. + * @param address I2C address + * @see ADS1115_DEFAULT_ADDRESS + * @see ADS1115_ADDRESS_ADDR_GND + * @see ADS1115_ADDRESS_ADDR_VDD + * @see ADS1115_ADDRESS_ADDR_SDA + * @see ADS1115_ADDRESS_ADDR_SDL + */ +ADS1115::ADS1115(uint8_t address) { + devAddr = address; +} + +/** Power on and prepare for general usage. + * This device is ready to use automatically upon power-up. It defaults to + * single-shot read mode, P0/N1 mux, 2.048v gain, 128 samples/sec, default + * comparator with hysterysis, active-low polarity, non-latching comparator, + * and comparater-disabled operation. + */ +void ADS1115::initialize() { + setMultiplexer(ADS1115_MUX_P0_N1); + setGain(ADS1115_PGA_2P048); + setMode(ADS1115_MODE_SINGLESHOT); + setRate(ADS1115_RATE_128); + setComparatorMode(ADS1115_COMP_MODE_HYSTERESIS); + setComparatorPolarity(ADS1115_COMP_POL_ACTIVE_LOW); + setComparatorLatchEnabled(ADS1115_COMP_LAT_NON_LATCHING); + setComparatorQueueMode(ADS1115_COMP_QUE_DISABLE); +} + +/** Verify the I2C connection. + * Make sure the device is connected and responds as expected. + * @return True if connection is valid, false otherwise + */ +bool ADS1115::testConnection() { + return I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer) == 1; +} + +/** Poll the operational status bit until the conversion is finished + * Retry at most 'max_retries' times + * conversion is finished, then return true; + * @see ADS1115_CFG_OS_BIT + * @return True if data is available, false otherwise + */ +bool ADS1115::pollConversion(uint16_t max_retries) { + for(uint16_t i = 0; i < max_retries; i++) { + if (isConversionReady()) return true; + } + return false; +} + +/** Read differential value based on current MUX configuration. + * The default MUX setting sets the device to get the differential between the + * AIN0 and AIN1 pins. There are 8 possible MUX settings, but if you are using + * all four input pins as single-end voltage sensors, then the default option is + * not what you want; instead you will need to set the MUX to compare the + * desired AIN* pin with GND. There are shortcut methods (getConversion*) to do + * this conveniently, but you can also do it manually with setMultiplexer() + * followed by this method. + * + * In single-shot mode, this register may not have fresh data. You need to write + * a 1 bit to the MSB of the CONFIG register to trigger a single read/conversion + * before this will be populated with fresh data. This technique is not as + * effortless, but it has enormous potential to save power by only running the + * comparison circuitry when needed. + * + * @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger + * will be executed and the conversion results will be polled. + * @return 16-bit signed differential value + * @see getConversionP0N1(); + * @see getConversionPON3(); + * @see getConversionP1N3(); + * @see getConversionP2N3(); + * @see getConversionP0GND(); + * @see getConversionP1GND(); + * @see getConversionP2GND(); + * @see getConversionP3GND); + * @see setMultiplexer(); + * @see ADS1115_RA_CONVERSION + * @see ADS1115_MUX_P0_N1 + * @see ADS1115_MUX_P0_N3 + * @see ADS1115_MUX_P1_N3 + * @see ADS1115_MUX_P2_N3 + * @see ADS1115_MUX_P0_NG + * @see ADS1115_MUX_P1_NG + * @see ADS1115_MUX_P2_NG + * @see ADS1115_MUX_P3_NG + */ +int16_t ADS1115::getConversion(bool triggerAndPoll) { + if (triggerAndPoll && devMode == ADS1115_MODE_SINGLESHOT) { + triggerConversion(); + pollConversion(I2CDEV_DEFAULT_READ_TIMEOUT); + } + I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer); + return buffer[0]; +} +/** Get AIN0/N1 differential. + * This changes the MUX setting to AIN0/N1 if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP0N1() { + if (muxMode != ADS1115_MUX_P0_N1) setMultiplexer(ADS1115_MUX_P0_N1); + return getConversion(); +} + +/** Get AIN0/N3 differential. + * This changes the MUX setting to AIN0/N3 if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP0N3() { + if (muxMode != ADS1115_MUX_P0_N3) setMultiplexer(ADS1115_MUX_P0_N3); + return getConversion(); +} + +/** Get AIN1/N3 differential. + * This changes the MUX setting to AIN1/N3 if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP1N3() { + if (muxMode != ADS1115_MUX_P1_N3) setMultiplexer(ADS1115_MUX_P1_N3); + return getConversion(); +} + +/** Get AIN2/N3 differential. + * This changes the MUX setting to AIN2/N3 if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP2N3() { + if (muxMode != ADS1115_MUX_P2_N3) setMultiplexer(ADS1115_MUX_P2_N3); + return getConversion(); +} + +/** Get AIN0/GND differential. + * This changes the MUX setting to AIN0/GND if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP0GND() { + if (muxMode != ADS1115_MUX_P0_NG) setMultiplexer(ADS1115_MUX_P0_NG); + return getConversion(); +} +/** Get AIN1/GND differential. + * This changes the MUX setting to AIN1/GND if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP1GND() { + if (muxMode != ADS1115_MUX_P1_NG) setMultiplexer(ADS1115_MUX_P1_NG); + return getConversion(); +} +/** Get AIN2/GND differential. + * This changes the MUX setting to AIN2/GND if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP2GND() { + if (muxMode != ADS1115_MUX_P2_NG) setMultiplexer(ADS1115_MUX_P2_NG); + return getConversion(); +} +/** Get AIN3/GND differential. + * This changes the MUX setting to AIN3/GND if necessary, triggers a new + * measurement (also only if necessary), then gets the differential value + * currently in the CONVERSION register. + * @return 16-bit signed differential value + * @see getConversion() + */ +int16_t ADS1115::getConversionP3GND() { + if (muxMode != ADS1115_MUX_P3_NG) setMultiplexer(ADS1115_MUX_P3_NG); + return getConversion(); +} + +/** Get the current voltage reading + * Read the current differential and return it multiplied + * by the constant for the current gain. mV is returned to + * increase the precision of the voltage + * @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger + * will be executed and the conversion results will be polled. + */ +float ADS1115::getMilliVolts(bool triggerAndPoll) { + switch (pgaMode) { + case ADS1115_PGA_6P144: + return (getConversion(triggerAndPoll) * ADS1115_MV_6P144); + break; + case ADS1115_PGA_4P096: + return (getConversion(triggerAndPoll) * ADS1115_MV_4P096); + break; + case ADS1115_PGA_2P048: + return (getConversion(triggerAndPoll) * ADS1115_MV_2P048); + break; + case ADS1115_PGA_1P024: + return (getConversion(triggerAndPoll) * ADS1115_MV_1P024); + break; + case ADS1115_PGA_0P512: + return (getConversion(triggerAndPoll) * ADS1115_MV_0P512); + break; + case ADS1115_PGA_0P256: + case ADS1115_PGA_0P256B: + case ADS1115_PGA_0P256C: + return (getConversion(triggerAndPoll) * ADS1115_MV_0P256); + break; + } +} + +/** + * Return the current multiplier for the PGA setting. + * + * This may be directly retreived by using getMilliVolts(), + * but this causes an independent read. This function could + * be used to average a number of reads from the getConversion() + * getConversionx() functions and cut downon the number of + * floating-point calculations needed. + * + */ + +float ADS1115::getMvPerCount() { + switch (pgaMode) { + case ADS1115_PGA_6P144: + return ADS1115_MV_6P144; + break; + case ADS1115_PGA_4P096: + return ADS1115_MV_4P096; + break; + case ADS1115_PGA_2P048: + return ADS1115_MV_2P048; + break; + case ADS1115_PGA_1P024: + return ADS1115_MV_1P024; + break; + case ADS1115_PGA_0P512: + return ADS1115_MV_0P512; + break; + case ADS1115_PGA_0P256: + case ADS1115_PGA_0P256B: + case ADS1115_PGA_0P256C: + return ADS1115_MV_0P256; + break; + } +} + +// CONFIG register + +/** Get operational status. + * @return Current operational status (false for active conversion, true for inactive) + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_OS_BIT + */ +bool ADS1115::isConversionReady() { + I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, buffer); + return buffer[0]; +} +/** Trigger a new conversion. + * Writing to this bit will only have effect while in power-down mode (no conversions active). + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_OS_BIT + */ +void ADS1115::triggerConversion() { + I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, 1); +} +/** Get multiplexer connection. + * @return Current multiplexer connection setting + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_MUX_BIT + * @see ADS1115_CFG_MUX_LENGTH + */ +uint8_t ADS1115::getMultiplexer() { + I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MUX_BIT, ADS1115_CFG_MUX_LENGTH, buffer); + muxMode = (uint8_t)buffer[0]; + return muxMode; +} +/** Set multiplexer connection. Continous mode may fill the conversion register + * with data before the MUX setting has taken effect. A stop/start of the conversion + * is done to reset the values. + * @param mux New multiplexer connection setting + * @see ADS1115_MUX_P0_N1 + * @see ADS1115_MUX_P0_N3 + * @see ADS1115_MUX_P1_N3 + * @see ADS1115_MUX_P2_N3 + * @see ADS1115_MUX_P0_NG + * @see ADS1115_MUX_P1_NG + * @see ADS1115_MUX_P2_NG + * @see ADS1115_MUX_P3_NG + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_MUX_BIT + * @see ADS1115_CFG_MUX_LENGTH + */ +void ADS1115::setMultiplexer(uint8_t mux) { + if (I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MUX_BIT, ADS1115_CFG_MUX_LENGTH, mux)) { + muxMode = mux; + if (devMode == ADS1115_MODE_CONTINUOUS) { + // Force a stop/start + setMode(ADS1115_MODE_SINGLESHOT); + getConversion(); + setMode(ADS1115_MODE_CONTINUOUS); + } + } + +} +/** Get programmable gain amplifier level. + * @return Current programmable gain amplifier level + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_PGA_BIT + * @see ADS1115_CFG_PGA_LENGTH + */ +uint8_t ADS1115::getGain() { + I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_PGA_BIT, ADS1115_CFG_PGA_LENGTH, buffer); + pgaMode=(uint8_t)buffer[0]; + return pgaMode; +} +/** Set programmable gain amplifier level. + * Continous mode may fill the conversion register + * with data before the gain setting has taken effect. A stop/start of the conversion + * is done to reset the values. + * @param gain New programmable gain amplifier level + * @see ADS1115_PGA_6P144 + * @see ADS1115_PGA_4P096 + * @see ADS1115_PGA_2P048 + * @see ADS1115_PGA_1P024 + * @see ADS1115_PGA_0P512 + * @see ADS1115_PGA_0P256 + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_PGA_BIT + * @see ADS1115_CFG_PGA_LENGTH + */ +void ADS1115::setGain(uint8_t gain) { + if (I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_PGA_BIT, ADS1115_CFG_PGA_LENGTH, gain)) { + pgaMode = gain; + if (devMode == ADS1115_MODE_CONTINUOUS) { + // Force a stop/start + setMode(ADS1115_MODE_SINGLESHOT); + getConversion(); + setMode(ADS1115_MODE_CONTINUOUS); + } + } +} +/** Get device mode. + * @return Current device mode + * @see ADS1115_MODE_CONTINUOUS + * @see ADS1115_MODE_SINGLESHOT + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_MODE_BIT + */ +bool ADS1115::getMode() { + I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, buffer); + devMode = buffer[0]; + return devMode; +} +/** Set device mode. + * @param mode New device mode + * @see ADS1115_MODE_CONTINUOUS + * @see ADS1115_MODE_SINGLESHOT + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_MODE_BIT + */ +void ADS1115::setMode(bool mode) { + if (I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, mode)) { + devMode = mode; + } +} +/** Get data rate. + * @return Current data rate + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_DR_BIT + * @see ADS1115_CFG_DR_LENGTH + */ +uint8_t ADS1115::getRate() { + I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_DR_BIT, ADS1115_CFG_DR_LENGTH, buffer); + return (uint8_t)buffer[0]; +} +/** Set data rate. + * @param rate New data rate + * @see ADS1115_RATE_8 + * @see ADS1115_RATE_16 + * @see ADS1115_RATE_32 + * @see ADS1115_RATE_64 + * @see ADS1115_RATE_128 + * @see ADS1115_RATE_250 + * @see ADS1115_RATE_475 + * @see ADS1115_RATE_860 + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_DR_BIT + * @see ADS1115_CFG_DR_LENGTH + */ +void ADS1115::setRate(uint8_t rate) { + I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_DR_BIT, ADS1115_CFG_DR_LENGTH, rate); +} +/** Get comparator mode. + * @return Current comparator mode + * @see ADS1115_COMP_MODE_HYSTERESIS + * @see ADS1115_COMP_MODE_WINDOW + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_MODE_BIT + */ +bool ADS1115::getComparatorMode() { + I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, buffer); + return buffer[0]; +} +/** Set comparator mode. + * @param mode New comparator mode + * @see ADS1115_COMP_MODE_HYSTERESIS + * @see ADS1115_COMP_MODE_WINDOW + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_MODE_BIT + */ +void ADS1115::setComparatorMode(bool mode) { + I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, mode); +} +/** Get comparator polarity setting. + * @return Current comparator polarity setting + * @see ADS1115_COMP_POL_ACTIVE_LOW + * @see ADS1115_COMP_POL_ACTIVE_HIGH + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_POL_BIT + */ +bool ADS1115::getComparatorPolarity() { + I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, buffer); + return buffer[0]; +} +/** Set comparator polarity setting. + * @param polarity New comparator polarity setting + * @see ADS1115_COMP_POL_ACTIVE_LOW + * @see ADS1115_COMP_POL_ACTIVE_HIGH + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_POL_BIT + */ +void ADS1115::setComparatorPolarity(bool polarity) { + I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, polarity); +} +/** Get comparator latch enabled value. + * @return Current comparator latch enabled value + * @see ADS1115_COMP_LAT_NON_LATCHING + * @see ADS1115_COMP_LAT_LATCHING + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_LAT_BIT + */ +bool ADS1115::getComparatorLatchEnabled() { + I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_LAT_BIT, buffer); + return buffer[0]; +} +/** Set comparator latch enabled value. + * @param enabled New comparator latch enabled value + * @see ADS1115_COMP_LAT_NON_LATCHING + * @see ADS1115_COMP_LAT_LATCHING + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_LAT_BIT + */ +void ADS1115::setComparatorLatchEnabled(bool enabled) { + I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_LAT_BIT, enabled); +} +/** Get comparator queue mode. + * @return Current comparator queue mode + * @see ADS1115_COMP_QUE_ASSERT1 + * @see ADS1115_COMP_QUE_ASSERT2 + * @see ADS1115_COMP_QUE_ASSERT4 + * @see ADS1115_COMP_QUE_DISABLE + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_QUE_BIT + * @see ADS1115_CFG_COMP_QUE_LENGTH + */ +uint8_t ADS1115::getComparatorQueueMode() { + I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_QUE_BIT, ADS1115_CFG_COMP_QUE_LENGTH, buffer); + return (uint8_t)buffer[0]; +} +/** Set comparator queue mode. + * @param mode New comparator queue mode + * @see ADS1115_COMP_QUE_ASSERT1 + * @see ADS1115_COMP_QUE_ASSERT2 + * @see ADS1115_COMP_QUE_ASSERT4 + * @see ADS1115_COMP_QUE_DISABLE + * @see ADS1115_RA_CONFIG + * @see ADS1115_CFG_COMP_QUE_BIT + * @see ADS1115_CFG_COMP_QUE_LENGTH + */ +void ADS1115::setComparatorQueueMode(uint8_t mode) { + I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_QUE_BIT, ADS1115_CFG_COMP_QUE_LENGTH, mode); +} + +// *_THRESH registers + +/** Get low threshold value. + * @return Current low threshold value + * @see ADS1115_RA_LO_THRESH + */ +int16_t ADS1115::getLowThreshold() { + I2Cdev::readWord(devAddr, ADS1115_RA_LO_THRESH, buffer); + return buffer[0]; +} +/** Set low threshold value. + * @param threshold New low threshold value + * @see ADS1115_RA_LO_THRESH + */ +void ADS1115::setLowThreshold(int16_t threshold) { + I2Cdev::writeWord(devAddr, ADS1115_RA_LO_THRESH, threshold); +} +/** Get high threshold value. + * @return Current high threshold value + * @see ADS1115_RA_HI_THRESH + */ +int16_t ADS1115::getHighThreshold() { + I2Cdev::readWord(devAddr, ADS1115_RA_HI_THRESH, buffer); + return buffer[0]; +} +/** Set high threshold value. + * @param threshold New high threshold value + * @see ADS1115_RA_HI_THRESH + */ +void ADS1115::setHighThreshold(int16_t threshold) { + I2Cdev::writeWord(devAddr, ADS1115_RA_HI_THRESH, threshold); +} + +/** Configures ALERT/RDY pin as a conversion ready pin. + * It does this by setting the MSB of the high threshold register to '1' and the MSB + * of the low threshold register to '0'. COMP_POL and COMP_QUE bits will be set to '0'. + * Note: ALERT/RDY pin requires a pull up resistor. + */ +void ADS1115::setConversionReadyPinMode() { + I2Cdev::writeBitW(devAddr, ADS1115_RA_HI_THRESH, 15, 1); + I2Cdev::writeBitW(devAddr, ADS1115_RA_LO_THRESH, 15, 0); + setComparatorPolarity(0); + setComparatorQueueMode(0); +} + +// Create a mask between two bits +unsigned createMask(unsigned a, unsigned b) { + unsigned mask = 0; + for (unsigned i=a; i<=b; i++) + mask |= 1 << i; + return mask; +} + +uint16_t shiftDown(uint16_t extractFrom, int places) { + return (extractFrom >> places); +} + + +uint16_t getValueFromBits(uint16_t extractFrom, int high, int length) { + int low= high-length +1; + uint16_t mask = createMask(low ,high); + return shiftDown(extractFrom & mask, low); +} + +/** Show all the config register settings + */ +void ADS1115::showConfigRegister() { + I2Cdev::readWord(devAddr, ADS1115_RA_CONFIG, buffer); + uint16_t configRegister =buffer[0]; + + + #ifdef ADS1115_SERIAL_DEBUG + Serial.print("Register is:"); + Serial.println(configRegister,BIN); + + Serial.print("OS:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_OS_BIT,1), BIN); + Serial.print("MUX:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_MUX_BIT,ADS1115_CFG_MUX_LENGTH), BIN); + + Serial.print("PGA:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_PGA_BIT,ADS1115_CFG_PGA_LENGTH), BIN); + + Serial.print("MODE:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_MODE_BIT,1), BIN); + + Serial.print("DR:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_DR_BIT,ADS1115_CFG_DR_LENGTH), BIN); + + Serial.print("CMP_MODE:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_COMP_MODE_BIT,1), BIN); + + Serial.print("CMP_POL:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_COMP_POL_BIT,1), BIN); + + Serial.print("CMP_LAT:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_COMP_LAT_BIT,1), BIN); + + Serial.print("CMP_QUE:\t"); + Serial.println(getValueFromBits(configRegister, + ADS1115_CFG_COMP_QUE_BIT,ADS1115_CFG_COMP_QUE_LENGTH), BIN); + #endif +}; + diff --git a/lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.h b/lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.h new file mode 100644 index 000000000..2ac68eea7 --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-ADS1115/ADS1115.h @@ -0,0 +1,200 @@ +// I2Cdev library collection - ADS1115 I2C device class header file +// Based on Texas Instruments ADS1113/4/5 datasheet, May 2009 (SBAS444B, revised October 2009) +// Note that the ADS1115 uses 16-bit registers, not 8-bit registers. +// 8/2/2011 by Jeff Rowberg +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2013-05-05 - Add debug information. Clean up Single Shot implementation +// 2011-10-29 - added getDifferentialx() methods, F. Farzanegan +// 2011-08-02 - initial release + + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation 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 +furnished 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 FOR 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. +=============================================== +*/ + +#ifndef _ADS1115_H_ +#define _ADS1115_H_ + +#include "I2Cdev.h" + +// ----------------------------------------------------------------------------- +// Arduino-style "Serial.print" debug constant (uncomment to enable) +// ----------------------------------------------------------------------------- +//#define ADS1115_SERIAL_DEBUG + +#define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND) +#define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC) +#define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin +#define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin +#define ADS1115_DEFAULT_ADDRESS ADS1115_ADDRESS_ADDR_GND + +#define ADS1115_RA_CONVERSION 0x00 +#define ADS1115_RA_CONFIG 0x01 +#define ADS1115_RA_LO_THRESH 0x02 +#define ADS1115_RA_HI_THRESH 0x03 + +#define ADS1115_CFG_OS_BIT 15 +#define ADS1115_CFG_MUX_BIT 14 +#define ADS1115_CFG_MUX_LENGTH 3 +#define ADS1115_CFG_PGA_BIT 11 +#define ADS1115_CFG_PGA_LENGTH 3 +#define ADS1115_CFG_MODE_BIT 8 +#define ADS1115_CFG_DR_BIT 7 +#define ADS1115_CFG_DR_LENGTH 3 +#define ADS1115_CFG_COMP_MODE_BIT 4 +#define ADS1115_CFG_COMP_POL_BIT 3 +#define ADS1115_CFG_COMP_LAT_BIT 2 +#define ADS1115_CFG_COMP_QUE_BIT 1 +#define ADS1115_CFG_COMP_QUE_LENGTH 2 + + +#define ADS1115_MUX_P0_N1 0x00 // default +#define ADS1115_MUX_P0_N3 0x01 +#define ADS1115_MUX_P1_N3 0x02 +#define ADS1115_MUX_P2_N3 0x03 +#define ADS1115_MUX_P0_NG 0x04 +#define ADS1115_MUX_P1_NG 0x05 +#define ADS1115_MUX_P2_NG 0x06 +#define ADS1115_MUX_P3_NG 0x07 + +#define ADS1115_PGA_6P144 0x00 +#define ADS1115_PGA_4P096 0x01 +#define ADS1115_PGA_2P048 0x02 // default +#define ADS1115_PGA_1P024 0x03 +#define ADS1115_PGA_0P512 0x04 +#define ADS1115_PGA_0P256 0x05 +#define ADS1115_PGA_0P256B 0x06 +#define ADS1115_PGA_0P256C 0x07 + +#define ADS1115_MV_6P144 0.187500 +#define ADS1115_MV_4P096 0.125000 +#define ADS1115_MV_2P048 0.062500 // default +#define ADS1115_MV_1P024 0.031250 +#define ADS1115_MV_0P512 0.015625 +#define ADS1115_MV_0P256 0.007813 +#define ADS1115_MV_0P256B 0.007813 +#define ADS1115_MV_0P256C 0.007813 + +#define ADS1115_MODE_CONTINUOUS 0x00 +#define ADS1115_MODE_SINGLESHOT 0x01 // default + +#define ADS1115_RATE_8 0x00 +#define ADS1115_RATE_16 0x01 +#define ADS1115_RATE_32 0x02 +#define ADS1115_RATE_64 0x03 +#define ADS1115_RATE_128 0x04 // default +#define ADS1115_RATE_250 0x05 +#define ADS1115_RATE_475 0x06 +#define ADS1115_RATE_860 0x07 + +#define ADS1115_COMP_MODE_HYSTERESIS 0x00 // default +#define ADS1115_COMP_MODE_WINDOW 0x01 + +#define ADS1115_COMP_POL_ACTIVE_LOW 0x00 // default +#define ADS1115_COMP_POL_ACTIVE_HIGH 0x01 + +#define ADS1115_COMP_LAT_NON_LATCHING 0x00 // default +#define ADS1115_COMP_LAT_LATCHING 0x01 + +#define ADS1115_COMP_QUE_ASSERT1 0x00 +#define ADS1115_COMP_QUE_ASSERT2 0x01 +#define ADS1115_COMP_QUE_ASSERT4 0x02 +#define ADS1115_COMP_QUE_DISABLE 0x03 // default + +// ----------------------------------------------------------------------------- +// Arduino-style "Serial.print" debug constant (uncomment to enable) +// ----------------------------------------------------------------------------- +//#define ADS1115_SERIAL_DEBUG + + +class ADS1115 { + public: + ADS1115(); + ADS1115(uint8_t address); + + void initialize(); + bool testConnection(); + + // SINGLE SHOT utilities + bool pollConversion(uint16_t max_retries); + void triggerConversion(); + + // Read the current CONVERSION register + int16_t getConversion(bool triggerAndPoll=true); + + // Differential + int16_t getConversionP0N1(); + int16_t getConversionP0N3(); + int16_t getConversionP1N3(); + int16_t getConversionP2N3(); + + // Single-ended + int16_t getConversionP0GND(); + int16_t getConversionP1GND(); + int16_t getConversionP2GND(); + int16_t getConversionP3GND(); + + // Utility + float getMilliVolts(bool triggerAndPoll=true); + float getMvPerCount(); + + // CONFIG register + bool isConversionReady(); + uint8_t getMultiplexer(); + void setMultiplexer(uint8_t mux); + uint8_t getGain(); + void setGain(uint8_t gain); + bool getMode(); + void setMode(bool mode); + uint8_t getRate(); + void setRate(uint8_t rate); + bool getComparatorMode(); + void setComparatorMode(bool mode); + bool getComparatorPolarity(); + void setComparatorPolarity(bool polarity); + bool getComparatorLatchEnabled(); + void setComparatorLatchEnabled(bool enabled); + uint8_t getComparatorQueueMode(); + void setComparatorQueueMode(uint8_t mode); + void setConversionReadyPinMode(); + + // *_THRESH registers + int16_t getLowThreshold(); + void setLowThreshold(int16_t threshold); + int16_t getHighThreshold(); + void setHighThreshold(int16_t threshold); + + // DEBUG + void showConfigRegister(); + + private: + uint8_t devAddr; + uint16_t buffer[2]; + bool devMode; + uint8_t muxMode; + uint8_t pgaMode; +}; + +#endif /* _ADS1115_H_ */ diff --git a/lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_differential/ADS1115_differential.ino b/lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_differential/ADS1115_differential.ino new file mode 100644 index 000000000..a67b77bf0 --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_differential/ADS1115_differential.ino @@ -0,0 +1,91 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class +// Example of reading two differential inputs of the ADS1115 and showing the value in mV +// 06 May 2013 by Frederick Farzanegan (frederick1@farzanegan.org) +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2013-05-13 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation 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 +furnished 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 FOR 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 "ADS1115.h" + +ADS1115 adc0(ADS1115_DEFAULT_ADDRESS); + +void setup() { + Wire.begin(); // join I2C bus + Serial.begin(19200); // initialize serial communication + Serial.println("Initializing I2C devices..."); + adc0.initialize(); // initialize ADS1115 16 bit A/D chip + + Serial.println("Testing device connections..."); + Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed"); + + // To get output from this method, you'll need to turn on the + //#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file + adc0.showConfigRegister(); + + // We're going to do continuous sampling + adc0.setMode(ADS1115_MODE_CONTINUOUS); +} + +void loop() { + + // Sensor is on P0/N1 (pins 4/5) + Serial.println("Sensor 1 ************************"); + // Set the gain (PGA) +/- 1.024v + adc0.setGain(ADS1115_PGA_1P024); + + // Get the number of counts of the accumulator + Serial.print("Counts for sensor 1 is:"); + + // The below method sets the mux and gets a reading. + int sensorOneCounts=adc0.getConversionP0N1(); // counts up to 16-bits + Serial.println(sensorOneCounts); + + // To turn the counts into a voltage, we can use + Serial.print("Voltage for sensor 1 is:"); + Serial.println(sensorOneCounts*adc0.getMvPerCount()); + + Serial.println(); + + + // 2nd sensor is on P2/N3 (pins 6/7) + Serial.println("Sensor 2 ************************"); + // Set the gain (PGA) +/- 0.256v + adc0.setGain(ADS1115_PGA_0P256); + + // Manually set the MUX // could have used the getConversionP* above + adc0.setMultiplexer(ADS1115_MUX_P2_N3); + Serial.print("Counts for sensor 2 is:"); + Serial.println(adc0.getConversion()); + + Serial.print("mVoltage sensor 2 is:"); + Serial.println(adc0.getMilliVolts()); // Convenience method to calculate voltage + + Serial.println(); + + delay(500); +} + diff --git a/lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino b/lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino new file mode 100644 index 000000000..4059ac1eb --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino @@ -0,0 +1,110 @@ +// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class +// Example of reading two differential inputs of the ADS1115 and showing the value in mV +// 2016-03-22 by Eadf (https://github.com/eadf) +// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib +// +// Changelog: +// 2016-03-22 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2011 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation 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 +furnished 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 FOR 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 "ADS1115.h" + +ADS1115 adc0(ADS1115_DEFAULT_ADDRESS); + +// Wire ADS1115 ALERT/RDY pin to Arduino pin 2 +const int alertReadyPin = 2; + +void setup() { + //I2Cdev::begin(); // join I2C bus + Wire.begin(); + Serial.begin(115200); // initialize serial communication + + Serial.println("Testing device connections..."); + Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed"); + + adc0.initialize(); // initialize ADS1115 16 bit A/D chip + + // We're going to do single shot sampling + adc0.setMode(ADS1115_MODE_SINGLESHOT); + + // Slow things down so that we can see that the "poll for conversion" code works + adc0.setRate(ADS1115_RATE_8); + + // Set the gain (PGA) +/- 6.144V + // Note that any analog input must be higher than –0.3V and less than VDD +0.3 + adc0.setGain(ADS1115_PGA_6P144); + // ALERT/RDY pin will indicate when conversion is ready + + pinMode(alertReadyPin,INPUT_PULLUP); + adc0.setConversionReadyPinMode(); + + // To get output from this method, you'll need to turn on the + //#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file + #ifdef ADS1115_SERIAL_DEBUG + adc0.showConfigRegister(); + Serial.print("HighThreshold="); Serial.println(adc0.getHighThreshold(),BIN); + Serial.print("LowThreshold="); Serial.println(adc0.getLowThreshold(),BIN); + #endif +} + +/** Poll the assigned pin for conversion status + */ +void pollAlertReadyPin() { + for (uint32_t i = 0; i<100000; i++) + if (!digitalRead(alertReadyPin)) return; + Serial.println("Failed to wait for AlertReadyPin, it's stuck high!"); +} + +void loop() { + + // The below method sets the mux and gets a reading. + adc0.setMultiplexer(ADS1115_MUX_P0_NG); + adc0.triggerConversion(); + pollAlertReadyPin(); + Serial.print("A0: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t"); + + adc0.setMultiplexer(ADS1115_MUX_P1_NG); + adc0.triggerConversion(); + pollAlertReadyPin(); + Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t"); + + adc0.setMultiplexer(ADS1115_MUX_P2_NG); + adc0.triggerConversion(); + pollAlertReadyPin(); + Serial.print("A2: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t"); + + adc0.setMultiplexer(ADS1115_MUX_P3_NG); + // Do conversion polling via I2C on this last reading: + Serial.print("A3: "); Serial.print(adc0.getMilliVolts(true)); Serial.print("mV"); + + Serial.println(digitalRead(alertReadyPin)); + delay(500); +} + + + + + diff --git a/lib-before-5.9.1f/I2Cdevlib-ADS1115/library.json b/lib-before-5.9.1f/I2Cdevlib-ADS1115/library.json new file mode 100644 index 000000000..e3e65531b --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-ADS1115/library.json @@ -0,0 +1,18 @@ +{ + "name": "I2Cdevlib-ADS1115", + "keywords": "MUX, PGA, comparator, oscillator, reference, i2cdevlib, i2c", + "description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference", + "include": "Arduino/ADS1115", + "repository": + { + "type": "git", + "url": "https://github.com/jrowberg/i2cdevlib.git" + }, + "dependencies": + { + "name": "I2Cdevlib-Core", + "frameworks": "arduino" + }, + "frameworks": "arduino", + "platforms": "atmelavr" +} diff --git a/lib-before-5.9.1f/I2Cdevlib-Core/.library.json b/lib-before-5.9.1f/I2Cdevlib-Core/.library.json new file mode 100644 index 000000000..258acc176 --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-Core/.library.json @@ -0,0 +1,31 @@ +{ + "name": "I2Cdevlib-Core", + "repository": { + "url": "https://github.com/jrowberg/i2cdevlib.git", + "type": "git" + }, + "platforms": [ + "atmelavr" + ], + "frameworks": [ + "arduino" + ], + "version": "6744ce0ac4", + "export": { + "include": "Arduino/I2Cdev" + }, + "authors": [ + { + "maintainer": false, + "name": "Jeff Rowberg", + "url": "https://github.com/jrowberg", + "email": "jeff@rowberg.net" + } + ], + "keywords": [ + "i2cdevlib", + "i2c" + ], + "id": 11, + "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices." +} \ No newline at end of file diff --git a/lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.cpp b/lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.cpp new file mode 100644 index 000000000..db173b55a --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.cpp @@ -0,0 +1,1457 @@ +// I2Cdev library collection - Main I2C device class +// Abstracts bit and byte I2C R/W functions into a convenient class +// 2013-06-05 by Jeff Rowberg +// +// Changelog: +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation 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 +furnished 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 FOR 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 "I2Cdev.h" + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + + #ifdef I2CDEV_IMPLEMENTATION_WARNINGS + #if ARDUINO < 100 + #warning Using outdated Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #warning - Timeout detection (some Wire requests block forever) + #elif ARDUINO == 100 + #warning Using outdated Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.6.5+ with I2Cdev Fastwire implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #warning - Timeout detection (some Wire requests block forever) + #elif ARDUINO > 100 + /*#warning Using current Arduino IDE with Wire library is functionally limiting. + #warning Arduino IDE v1.6.5+ with I2CDEV_BUILTIN_FASTWIRE implementation is recommended. + #warning This I2Cdev implementation does not support: + #warning - Timeout detection (some Wire requests block forever)*/ + #endif + #endif + +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + + //#error The I2CDEV_BUILTIN_FASTWIRE implementation is known to be broken right now. Patience, Iago! + +#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + + #ifdef I2CDEV_IMPLEMENTATION_WARNINGS + #warning Using I2CDEV_BUILTIN_NBWIRE implementation may adversely affect interrupt detection. + #warning This I2Cdev implementation does not support: + #warning - Repeated starts conditions + #endif + + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + TwoWire Wire; + +#endif + +/** Default constructor. + */ +I2Cdev::I2Cdev() { +} + +/** Read a single bit from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-7) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { + uint8_t b; + uint8_t count = readByte(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read a single bit from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitNum Bit position to read (0-15) + * @param data Container for single bit value + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) { + uint16_t b; + uint8_t count = readWord(devAddr, regAddr, &b, timeout); + *data = b & (1 << bitNum); + return count; +} + +/** Read multiple bits from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-7) + * @param length Number of bits to read (not more than 8) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { + // 01101001 read byte + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 010 masked + // -> 010 shifted + uint8_t count, b; + if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + b &= mask; + b >>= (bitStart - length + 1); + *data = b; + } + return count; +} + +/** Read multiple bits from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param bitStart First bit position to read (0-15) + * @param length Number of bits to read (not more than 16) + * @param data Container for right-aligned value (i.e. '101' read from any bitStart position will equal 0x05) + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) + */ +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) { + // 1101011001101001 read byte + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 010 masked + // -> 010 shifted + uint8_t count; + uint16_t w; + if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + w &= mask; + w >>= (bitStart - length + 1); + *data = w; + } + return count; +} + +/** Read single byte from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for byte value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { + return readBytes(devAddr, regAddr, 1, data, timeout); +} + +/** Read single word from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to read from + * @param data Container for word value read from device + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Status of read operation (true = success) + */ +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) { + return readWords(devAddr, regAddr, 1, data, timeout); +} + +/** Read multiple bytes from an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of bytes to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of bytes read (-1 indicates failure) + */ +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") reading "); + Serial.print(length, DEC); + Serial.print(" bytes from 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + + int8_t count = 0; + uint32_t t1 = millis(); + + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) + + #if (ARDUINO < 100) + // Arduino v00xx (before v1.0), Wire library + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.send(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = Wire.receive(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + + Wire.endTransmission(); + } + #elif (ARDUINO == 100) + // Arduino v1.0.0, Wire library + // Adds standardized write() and read() stream methods instead of send() and receive() + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + + Wire.endTransmission(); + } + #elif (ARDUINO > 100) + // Arduino v1.0.1+, Wire library + // Adds official support for repeated start condition, yay! + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + + for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + } + } + #endif + + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + + // Fastwire library + // no loop required for fastwire + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, data, length); + if (status == 0) { + count = length; // success + } else { + count = -1; // error + } + + #endif + + // check for timeout + if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout + + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(". Done ("); + Serial.print(count, DEC); + Serial.println(" read)."); + #endif + + return count; +} + +/** Read multiple words from a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register regAddr to read from + * @param length Number of words to read + * @param data Buffer to store read data in + * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) + * @return Number of words read (-1 indicates failure) + */ +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") reading "); + Serial.print(length, DEC); + Serial.print(" words from 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + + int8_t count = 0; + uint32_t t1 = millis(); + + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) + + #if (ARDUINO < 100) + // Arduino v00xx (before v1.0), Wire library + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.send(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = Wire.receive() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= Wire.receive(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + + Wire.endTransmission(); + } + #elif (ARDUINO == 100) + // Arduino v1.0.0, Wire library + // Adds standardized write() and read() stream methods instead of send() and receive() + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = Wire.read() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + + Wire.endTransmission(); + } + #elif (ARDUINO > 100) + // Arduino v1.0.1+, Wire library + // Adds official support for repeated start condition, yay! + + // I2C/TWI subsystem uses internal buffer that breaks with large data requests + // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // smaller chunks instead of all at once + for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + Wire.beginTransmission(devAddr); + Wire.write(regAddr); + Wire.endTransmission(); + Wire.beginTransmission(devAddr); + Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + + bool msb = true; // starts with MSB, then LSB + for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + if (msb) { + // first byte is bits 15-8 (MSb=15) + data[count] = Wire.read() << 8; + } else { + // second byte is bits 7-0 (LSb=0) + data[count] |= Wire.read(); + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[count], HEX); + if (count + 1 < length) Serial.print(" "); + #endif + count++; + } + msb = !msb; + } + + Wire.endTransmission(); + } + #endif + + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + + // Fastwire library + // no loop required for fastwire + uint16_t intermediate[(uint8_t)length]; + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, (uint8_t *)intermediate, (uint8_t)(length * 2)); + if (status == 0) { + count = length; // success + for (uint8_t i = 0; i < length; i++) { + data[i] = (intermediate[2*i] << 8) | intermediate[2*i + 1]; + } + } else { + count = -1; // error + } + + #endif + + if (timeout > 0 && millis() - t1 >= timeout && count < length) count = -1; // timeout + + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(". Done ("); + Serial.print(count, DEC); + Serial.println(" read)."); + #endif + + return count; +} + +/** write a single bit in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-7) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { + uint8_t b; + readByte(devAddr, regAddr, &b); + b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); + return writeByte(devAddr, regAddr, b); +} + +/** write a single bit in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitNum Bit position to write (0-15) + * @param value New bit value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { + uint16_t w; + readWord(devAddr, regAddr, &w); + w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); + return writeWord(devAddr, regAddr, w); +} + +/** Write multiple bits in an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-7) + * @param length Number of bits to write (not more than 8) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { + // 010 value to write + // 76543210 bit numbers + // xxx args: bitStart=4, length=3 + // 00011100 mask byte + // 10101111 original value (sample) + // 10100011 original & ~mask + // 10101011 masked | value + uint8_t b; + if (readByte(devAddr, regAddr, &b) != 0) { + uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + b &= ~(mask); // zero all important bits in existing byte + b |= data; // combine data with existing byte + return writeByte(devAddr, regAddr, b); + } else { + return false; + } +} + +/** Write multiple bits in a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register regAddr to write to + * @param bitStart First bit position to write (0-15) + * @param length Number of bits to write (not more than 16) + * @param data Right-aligned value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { + // 010 value to write + // fedcba9876543210 bit numbers + // xxx args: bitStart=12, length=3 + // 0001110000000000 mask word + // 1010111110010110 original value (sample) + // 1010001110010110 original & ~mask + // 1010101110010110 masked | value + uint16_t w; + if (readWord(devAddr, regAddr, &w) != 0) { + uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); + data <<= (bitStart - length + 1); // shift data into correct position + data &= mask; // zero all non-important bits in data + w &= ~(mask); // zero all important bits in existing word + w |= data; // combine data with existing word + return writeWord(devAddr, regAddr, w); + } else { + return false; + } +} + +/** Write single byte to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New byte value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { + return writeBytes(devAddr, regAddr, 1, &data); +} + +/** Write single word to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr Register address to write to + * @param data New word value to write + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { + return writeWords(devAddr, regAddr, 1, &data); +} + +/** Write multiple bytes to an 8-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of bytes to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") writing "); + Serial.print(length, DEC); + Serial.print(" bytes to 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + uint8_t status = 0; + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.beginTransmission(devAddr); + Wire.send((uint8_t) regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.beginTransmission(devAddr); + Wire.write((uint8_t) regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::beginTransmission(devAddr); + Fastwire::write(regAddr); + #endif + for (uint8_t i = 0; i < length; i++) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[i], HEX); + if (i + 1 < length) Serial.print(" "); + #endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.send((uint8_t) data[i]); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.write((uint8_t) data[i]); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::write((uint8_t) data[i]); + #endif + } + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::stop(); + //status = Fastwire::endTransmission(); + #endif + #ifdef I2CDEV_SERIAL_DEBUG + Serial.println(". Done."); + #endif + return status == 0; +} + +/** Write multiple words to a 16-bit device register. + * @param devAddr I2C slave device address + * @param regAddr First register address to write to + * @param length Number of words to write + * @param data Buffer to copy new data from + * @return Status of operation (true = success) + */ +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print("I2C (0x"); + Serial.print(devAddr, HEX); + Serial.print(") writing "); + Serial.print(length, DEC); + Serial.print(" words to 0x"); + Serial.print(regAddr, HEX); + Serial.print("..."); + #endif + uint8_t status = 0; + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.beginTransmission(devAddr); + Wire.send(regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.beginTransmission(devAddr); + Wire.write(regAddr); // send address + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::beginTransmission(devAddr); + Fastwire::write(regAddr); + #endif + for (uint8_t i = 0; i < length * 2; i++) { + #ifdef I2CDEV_SERIAL_DEBUG + Serial.print(data[i], HEX); + if (i + 1 < length) Serial.print(" "); + #endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.send((uint8_t)(data[i] >> 8)); // send MSB + Wire.send((uint8_t)data[i++]); // send LSB + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + Wire.write((uint8_t)(data[i] >> 8)); // send MSB + Wire.write((uint8_t)data[i++]); // send LSB + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB + status = Fastwire::write((uint8_t)data[i++]); // send LSB + if (status != 0) break; + #endif + } + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) + Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) + status = Wire.endTransmission(); + #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) + Fastwire::stop(); + //status = Fastwire::endTransmission(); + #endif + #ifdef I2CDEV_SERIAL_DEBUG + Serial.println(". Done."); + #endif + return status == 0; +} + +/** Default timeout value for read operations. + * Set this to 0 to disable timeout detection. + */ +uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + // I2C library + ////////////////////// + // Copyright(C) 2012 + // Francesco Ferrara + // ferrara[at]libero[point]it + ////////////////////// + + /* + FastWire + - 0.24 added stop + - 0.23 added reset + + This is a library to help faster programs to read I2C devices. + Copyright(C) 2012 Francesco Ferrara + occhiobello at gmail dot com + [used by Jeff Rowberg for I2Cdevlib with permission] + */ + + boolean Fastwire::waitInt() { + int l = 250; + while (!(TWCR & (1 << TWINT)) && l-- > 0); + return l > 0; + } + + void Fastwire::setup(int khz, boolean pullup) { + TWCR = 0; + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // activate internal pull-ups for twi (PORTC bits 4 & 5) + // as per note from atmega8 manual pg167 + if (pullup) PORTC |= ((1 << 4) | (1 << 5)); + else PORTC &= ~((1 << 4) | (1 << 5)); + #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) + // activate internal pull-ups for twi (PORTC bits 0 & 1) + if (pullup) PORTC |= ((1 << 0) | (1 << 1)); + else PORTC &= ~((1 << 0) | (1 << 1)); + #else + // activate internal pull-ups for twi (PORTD bits 0 & 1) + // as per note from atmega128 manual pg204 + if (pullup) PORTD |= ((1 << 0) | (1 << 1)); + else PORTD &= ~((1 << 0) | (1 << 1)); + #endif + + TWSR = 0; // no prescaler => prescaler = 1 + TWBR = ((16000L / khz) - 16) / 2; // change the I2C clock rate + TWCR = 1 << TWEN; // enable twi module, no interrupt + } + + // added by Jeff Rowberg 2013-05-07: + // Arduino Wire-style "beginTransmission" function + // (takes 7-bit device address like the Wire method, NOT 8-bit: 0x68, not 0xD0/0xD1) + byte Fastwire::beginTransmission(byte device) { + byte twst, retry; + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 2; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device << 1; // send device address without read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 3; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 4; + return 0; + } + + byte Fastwire::writeBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 2; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device & 0xFE; // send device address without read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 3; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 4; + + //Serial.print(address, HEX); + //Serial.print(" "); + TWDR = address; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 5; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 6; + + for (byte i = 0; i < num; i++) { + //Serial.print(data[i], HEX); + //Serial.print(" "); + TWDR = data[i]; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 7; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 8; + } + //Serial.print("\n"); + + return 0; + } + + byte Fastwire::write(byte value) { + byte twst; + //Serial.println(value, HEX); + TWDR = value; // send data + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 1; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 2; + return 0; + } + + byte Fastwire::readBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 16; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 17; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device & 0xfe; // send device address to write + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 18; + twst = TWSR & 0xF8; + } while (twst == TW_MT_SLA_NACK && retry-- > 0); + if (twst != TW_MT_SLA_ACK) return 19; + + //Serial.print(address, HEX); + //Serial.print(" "); + TWDR = address; // send data to the previously addressed device + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 20; + twst = TWSR & 0xF8; + if (twst != TW_MT_DATA_ACK) return 21; + + /***/ + + retry = 2; + do { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); + if (!waitInt()) return 22; + twst = TWSR & 0xF8; + if (twst != TW_START && twst != TW_REP_START) return 23; + + //Serial.print(device, HEX); + //Serial.print(" "); + TWDR = device | 0x01; // send device address with the read bit (1) + TWCR = (1 << TWINT) | (1 << TWEN); + if (!waitInt()) return 24; + twst = TWSR & 0xF8; + } while (twst == TW_MR_SLA_NACK && retry-- > 0); + if (twst != TW_MR_SLA_ACK) return 25; + + for (uint8_t i = 0; i < num; i++) { + if (i == num - 1) + TWCR = (1 << TWINT) | (1 << TWEN); + else + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); + if (!waitInt()) return 26; + twst = TWSR & 0xF8; + if (twst != TW_MR_DATA_ACK && twst != TW_MR_DATA_NACK) return twst; + data[i] = TWDR; + //Serial.print(data[i], HEX); + //Serial.print(" "); + } + //Serial.print("\n"); + stop(); + + return 0; + } + + void Fastwire::reset() { + TWCR = 0; + } + + byte Fastwire::stop() { + TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); + if (!waitInt()) return 1; + return 0; + } +#endif + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + + /* + call this version 1.0 + + Offhand, the only funky part that I can think of is in nbrequestFrom, where the buffer + length and index are set *before* the data is actually read. The problem is that these + are variables local to the TwoWire object, and by the time we actually have read the + data, and know what the length actually is, we have no simple access to the object's + variables. The actual bytes read *is* given to the callback function, though. + + The ISR code for a slave receiver is commented out. I don't have that setup, and can't + verify it at this time. Save it for 2.0! + + The handling of the read and write processes here is much like in the demo sketch code: + the process is broken down into sequential functions, where each registers the next as a + callback, essentially. + + For example, for the Read process, twi_read00 just returns if TWI is not yet in a + ready state. When there's another interrupt, and the interface *is* ready, then it + sets up the read, starts it, and registers twi_read01 as the function to call after + the *next* interrupt. twi_read01, then, just returns if the interface is still in a + "reading" state. When the reading is done, it copies the information to the buffer, + cleans up, and calls the user-requested callback function with the actual number of + bytes read. + + The writing is similar. + + Questions, comments and problems can go to Gene@Telobot.com. + + Thumbs Up! + Gene Knight + + */ + + uint8_t TwoWire::rxBuffer[NBWIRE_BUFFER_LENGTH]; + uint8_t TwoWire::rxBufferIndex = 0; + uint8_t TwoWire::rxBufferLength = 0; + + uint8_t TwoWire::txAddress = 0; + uint8_t TwoWire::txBuffer[NBWIRE_BUFFER_LENGTH]; + uint8_t TwoWire::txBufferIndex = 0; + uint8_t TwoWire::txBufferLength = 0; + + //uint8_t TwoWire::transmitting = 0; + void (*TwoWire::user_onRequest)(void); + void (*TwoWire::user_onReceive)(int); + + static volatile uint8_t twi_transmitting; + static volatile uint8_t twi_state; + static uint8_t twi_slarw; + static volatile uint8_t twi_error; + static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; + static volatile uint8_t twi_masterBufferIndex; + static uint8_t twi_masterBufferLength; + static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; + static volatile uint8_t twi_rxBufferIndex; + //static volatile uint8_t twi_Interrupt_Continue_Command; + static volatile uint8_t twi_Return_Value; + static volatile uint8_t twi_Done; + void (*twi_cbendTransmissionDone)(int); + void (*twi_cbreadFromDone)(int); + + void twi_init() { + // initialize state + twi_state = TWI_READY; + + // activate internal pull-ups for twi + // as per note from atmega8 manual pg167 + sbi(PORTC, 4); + sbi(PORTC, 5); + + // initialize twi prescaler and bit rate + cbi(TWSR, TWPS0); // TWI Status Register - Prescaler bits + cbi(TWSR, TWPS1); + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ + + TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register + // enable twi module, acks, and twi interrupt + + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); + + /* TWEN - TWI Enable Bit + TWIE - TWI Interrupt Enable + TWEA - TWI Enable Acknowledge Bit + TWINT - TWI Interrupt Flag + TWSTA - TWI Start Condition + */ + } + + typedef struct { + uint8_t address; + uint8_t* data; + uint8_t length; + uint8_t wait; + uint8_t i; + } twi_Write_Vars; + + twi_Write_Vars *ptwv = 0; + static void (*fNextInterruptFunction)(void) = 0; + + void twi_Finish(byte bRetVal) { + if (ptwv) { + free(ptwv); + ptwv = 0; + } + twi_Done = 0xFF; + twi_Return_Value = bRetVal; + fNextInterruptFunction = 0; + } + + uint8_t twii_WaitForDone(uint16_t timeout) { + uint32_t endMillis = millis() + timeout; + while (!twi_Done && (timeout == 0 || millis() < endMillis)) continue; + return twi_Return_Value; + } + + void twii_SetState(uint8_t ucState) { + twi_state = ucState; + } + + void twii_SetError(uint8_t ucError) { + twi_error = ucError ; + } + + void twii_InitBuffer(uint8_t ucPos, uint8_t ucLength) { + twi_masterBufferIndex = 0; + twi_masterBufferLength = ucLength; + } + + void twii_CopyToBuf(uint8_t* pData, uint8_t ucLength) { + uint8_t i; + for (i = 0; i < ucLength; ++i) { + twi_masterBuffer[i] = pData[i]; + } + } + + void twii_CopyFromBuf(uint8_t *pData, uint8_t ucLength) { + uint8_t i; + for (i = 0; i < ucLength; ++i) { + pData[i] = twi_masterBuffer[i]; + } + } + + void twii_SetSlaRW(uint8_t ucSlaRW) { + twi_slarw = ucSlaRW; + } + + void twii_SetStart() { + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + } + + void twi_write01() { + if (TWI_MTX == twi_state) return; // blocking test + twi_transmitting = 0 ; + if (twi_error == 0xFF) + twi_Finish (0); // success + else if (twi_error == TW_MT_SLA_NACK) + twi_Finish (2); // error: address send, nack received + else if (twi_error == TW_MT_DATA_NACK) + twi_Finish (3); // error: data send, nack received + else + twi_Finish (4); // other twi error + if (twi_cbendTransmissionDone) return twi_cbendTransmissionDone(twi_Return_Value); + return; + } + + + void twi_write00() { + if (TWI_READY != twi_state) return; // blocking test + if (TWI_BUFFER_LENGTH < ptwv -> length) { + twi_Finish(1); // end write with error 1 + return; + } + twi_Done = 0x00; // show as working + twii_SetState(TWI_MTX); // to transmitting + twii_SetError(0xFF); // to No Error + twii_InitBuffer(0, ptwv -> length); // pointer and length + twii_CopyToBuf(ptwv -> data, ptwv -> length); // get the data + twii_SetSlaRW((ptwv -> address << 1) | TW_WRITE); // write command + twii_SetStart(); // start the cycle + fNextInterruptFunction = twi_write01; // next routine + return twi_write01(); + } + + void twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) { + uint8_t i; + ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); + ptwv -> address = address; + ptwv -> data = data; + ptwv -> length = length; + ptwv -> wait = wait; + fNextInterruptFunction = twi_write00; + return twi_write00(); + } + + void twi_read01() { + if (TWI_MRX == twi_state) return; // blocking test + if (twi_masterBufferIndex < ptwv -> length) ptwv -> length = twi_masterBufferIndex; + twii_CopyFromBuf(ptwv -> data, ptwv -> length); + twi_Finish(ptwv -> length); + if (twi_cbreadFromDone) return twi_cbreadFromDone(twi_Return_Value); + return; + } + + void twi_read00() { + if (TWI_READY != twi_state) return; // blocking test + if (TWI_BUFFER_LENGTH < ptwv -> length) twi_Finish(0); // error return + twi_Done = 0x00; // show as working + twii_SetState(TWI_MRX); // reading + twii_SetError(0xFF); // reset error + twii_InitBuffer(0, ptwv -> length - 1); // init to one less than length + twii_SetSlaRW((ptwv -> address << 1) | TW_READ); // read command + twii_SetStart(); // start cycle + fNextInterruptFunction = twi_read01; + return twi_read01(); + } + + void twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) { + uint8_t i; + + ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); + ptwv -> address = address; + ptwv -> data = data; + ptwv -> length = length; + fNextInterruptFunction = twi_read00; + return twi_read00(); + } + + void twi_reply(uint8_t ack) { + // transmit master read ready signal, with or without ack + if (ack){ + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); + } else { + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + } + } + + void twi_stop(void) { + // send stop condition + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + + // wait for stop condition to be exectued on bus + // TWINT is not set after a stop condition! + while (TWCR & _BV(TWSTO)) { + continue; + } + + // update twi state + twi_state = TWI_READY; + } + + void twi_releaseBus(void) { + // release bus + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + + // update twi state + twi_state = TWI_READY; + } + + SIGNAL(TWI_vect) { + switch (TW_STATUS) { + // All Master + case TW_START: // sent start condition + case TW_REP_START: // sent repeated start condition + // copy device address and r/w bit to output register and ack + TWDR = twi_slarw; + twi_reply(1); + break; + + // Master Transmitter + case TW_MT_SLA_ACK: // slave receiver acked address + case TW_MT_DATA_ACK: // slave receiver acked data + // if there is data to send, send it, otherwise stop + if (twi_masterBufferIndex < twi_masterBufferLength) { + // copy data to output register and ack + TWDR = twi_masterBuffer[twi_masterBufferIndex++]; + twi_reply(1); + } else { + twi_stop(); + } + break; + + case TW_MT_SLA_NACK: // address sent, nack received + twi_error = TW_MT_SLA_NACK; + twi_stop(); + break; + + case TW_MT_DATA_NACK: // data sent, nack received + twi_error = TW_MT_DATA_NACK; + twi_stop(); + break; + + case TW_MT_ARB_LOST: // lost bus arbitration + twi_error = TW_MT_ARB_LOST; + twi_releaseBus(); + break; + + // Master Receiver + case TW_MR_DATA_ACK: // data received, ack sent + // put byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + + case TW_MR_SLA_ACK: // address sent, ack received + // ack if more bytes are expected, otherwise nack + if (twi_masterBufferIndex < twi_masterBufferLength) { + twi_reply(1); + } else { + twi_reply(0); + } + break; + + case TW_MR_DATA_NACK: // data received, nack sent + // put final byte into buffer + twi_masterBuffer[twi_masterBufferIndex++] = TWDR; + + case TW_MR_SLA_NACK: // address sent, nack received + twi_stop(); + break; + + // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case + + // Slave Receiver (NOT IMPLEMENTED YET) + /* + case TW_SR_SLA_ACK: // addressed, returned ack + case TW_SR_GCALL_ACK: // addressed generally, returned ack + case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack + case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack + // enter slave receiver mode + twi_state = TWI_SRX; + + // indicate that rx buffer can be overwritten and ack + twi_rxBufferIndex = 0; + twi_reply(1); + break; + + case TW_SR_DATA_ACK: // data received, returned ack + case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack + // if there is still room in the rx buffer + if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { + // put byte in buffer and ack + twi_rxBuffer[twi_rxBufferIndex++] = TWDR; + twi_reply(1); + } else { + // otherwise nack + twi_reply(0); + } + break; + + case TW_SR_STOP: // stop or repeated start condition received + // put a null char after data if there's room + if (twi_rxBufferIndex < TWI_BUFFER_LENGTH) { + twi_rxBuffer[twi_rxBufferIndex] = 0; + } + + // sends ack and stops interface for clock stretching + twi_stop(); + + // callback to user defined callback + twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); + + // since we submit rx buffer to "wire" library, we can reset it + twi_rxBufferIndex = 0; + + // ack future responses and leave slave receiver state + twi_releaseBus(); + break; + + case TW_SR_DATA_NACK: // data received, returned nack + case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack + // nack back at master + twi_reply(0); + break; + + // Slave Transmitter + case TW_ST_SLA_ACK: // addressed, returned ack + case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack + // enter slave transmitter mode + twi_state = TWI_STX; + + // ready the tx buffer index for iteration + twi_txBufferIndex = 0; + + // set tx buffer length to be zero, to verify if user changes it + twi_txBufferLength = 0; + + // request for txBuffer to be filled and length to be set + // note: user must call twi_transmit(bytes, length) to do this + twi_onSlaveTransmit(); + + // if they didn't change buffer & length, initialize it + if (0 == twi_txBufferLength) { + twi_txBufferLength = 1; + twi_txBuffer[0] = 0x00; + } + + // transmit first byte from buffer, fall through + + case TW_ST_DATA_ACK: // byte sent, ack returned + // copy data to output register + TWDR = twi_txBuffer[twi_txBufferIndex++]; + + // if there is more to send, ack, otherwise nack + if (twi_txBufferIndex < twi_txBufferLength) { + twi_reply(1); + } else { + twi_reply(0); + } + break; + + case TW_ST_DATA_NACK: // received nack, we are done + case TW_ST_LAST_DATA: // received ack, but we are done already! + // ack future responses + twi_reply(1); + // leave slave receiver state + twi_state = TWI_READY; + break; + */ + + // all + case TW_NO_INFO: // no state information + break; + + case TW_BUS_ERROR: // bus error, illegal stop/start + twi_error = TW_BUS_ERROR; + twi_stop(); + break; + } + + if (fNextInterruptFunction) return fNextInterruptFunction(); + } + + TwoWire::TwoWire() { } + + void TwoWire::begin(void) { + rxBufferIndex = 0; + rxBufferLength = 0; + + txBufferIndex = 0; + txBufferLength = 0; + + twi_init(); + } + + void TwoWire::beginTransmission(uint8_t address) { + //beginTransmission((uint8_t)address); + + // indicate that we are transmitting + twi_transmitting = 1; + + // set address of targeted slave + txAddress = address; + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + } + + uint8_t TwoWire::endTransmission(uint16_t timeout) { + // transmit buffer (blocking) + //int8_t ret = + twi_cbendTransmissionDone = NULL; + twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + int8_t ret = twii_WaitForDone(timeout); + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + + // indicate that we are done transmitting + // twi_transmitting = 0; + return ret; + } + + void TwoWire::nbendTransmission(void (*function)(int)) { + twi_cbendTransmissionDone = function; + twi_writeTo(txAddress, txBuffer, txBufferLength, 1); + return; + } + + void TwoWire::send(uint8_t data) { + if (twi_transmitting) { + // in master transmitter mode + // don't bother if buffer is full + if (txBufferLength >= NBWIRE_BUFFER_LENGTH) { + return; + } + + // put byte in tx buffer + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + + // update amount in buffer + txBufferLength = txBufferIndex; + } else { + // in slave send mode + // reply to master + //twi_transmit(&data, 1); + } + } + + uint8_t TwoWire::receive(void) { + // default to returning null char + // for people using with char strings + uint8_t value = 0; + + // get each successive byte on each call + if (rxBufferIndex < rxBufferLength) { + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + } + + return value; + } + + uint8_t TwoWire::requestFrom(uint8_t address, int quantity, uint16_t timeout) { + // clamp to buffer length + if (quantity > NBWIRE_BUFFER_LENGTH) { + quantity = NBWIRE_BUFFER_LENGTH; + } + + // perform blocking read into buffer + twi_cbreadFromDone = NULL; + twi_readFrom(address, rxBuffer, quantity); + uint8_t read = twii_WaitForDone(timeout); + + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = read; + + return read; + } + + void TwoWire::nbrequestFrom(uint8_t address, int quantity, void (*function)(int)) { + // clamp to buffer length + if (quantity > NBWIRE_BUFFER_LENGTH) { + quantity = NBWIRE_BUFFER_LENGTH; + } + + // perform blocking read into buffer + twi_cbreadFromDone = function; + twi_readFrom(address, rxBuffer, quantity); + //uint8_t read = twii_WaitForDone(); + + // set rx buffer iterator vars + //rxBufferIndex = 0; + //rxBufferLength = read; + + rxBufferIndex = 0; + rxBufferLength = quantity; // this is a hack + + return; //read; + } + + uint8_t TwoWire::available(void) { + return rxBufferLength - rxBufferIndex; + } + +#endif diff --git a/lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.h b/lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.h new file mode 100644 index 000000000..4c0a2e7a2 --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-Core/I2Cdev.h @@ -0,0 +1,278 @@ +// I2Cdev library collection - Main I2C device class header file +// Abstracts bit and byte I2C R/W functions into a convenient class +// 2013-06-05 by Jeff Rowberg +// +// Changelog: +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 +// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications +// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) +// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire +// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation +// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums) +// 2011-10-03 - added automatic Arduino version detection for ease of use +// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications +// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x) +// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default +// 2011-08-02 - added support for 16-bit registers +// - fixed incorrect Doxygen comments on some methods +// - added timeout value for read operations (thanks mem @ Arduino forums) +// 2011-07-30 - changed read/write function structures to return success or byte counts +// - made all methods static for multi-device memory savings +// 2011-07-28 - initial release + +/* ============================================ +I2Cdev device library code is placed under the MIT license +Copyright (c) 2013 Jeff Rowberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation 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 +furnished 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 FOR 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. +=============================================== +*/ + +#ifndef _I2CDEV_H_ +#define _I2CDEV_H_ + +// ----------------------------------------------------------------------------- +// I2C interface implementation setting +// ----------------------------------------------------------------------------- +#ifndef I2CDEV_IMPLEMENTATION +#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE +#endif // I2CDEV_IMPLEMENTATION + +// comment this out if you are using a non-optimal IDE/implementation setting +// but want the compiler to shut up about it +#define I2CDEV_IMPLEMENTATION_WARNINGS + +// ----------------------------------------------------------------------------- +// I2C interface implementation options +// ----------------------------------------------------------------------------- +#define I2CDEV_ARDUINO_WIRE 1 // Wire object from Arduino +#define I2CDEV_BUILTIN_NBWIRE 2 // Tweaked Wire object from Gene Knight's NBWire project + // ^^^ NBWire implementation is still buggy w/some interrupts! +#define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project +#define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library + +// ----------------------------------------------------------------------------- +// Arduino-style "Serial.print" debug constant (uncomment to enable) +// ----------------------------------------------------------------------------- +//#define I2CDEV_SERIAL_DEBUG + +#ifdef ARDUINO + #if ARDUINO < 100 + #include "WProgram.h" + #else + #include "Arduino.h" + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE + #include + #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY + #include + #endif +#endif + +#ifdef SPARK + #include + #define ARDUINO 101 +#endif + + +// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") +#define I2CDEV_DEFAULT_READ_TIMEOUT 1000 + +class I2Cdev { + public: + I2Cdev(); + + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + + static uint16_t readTimeout; +}; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE + ////////////////////// + // FastWire 0.24 + // This is a library to help faster programs to read I2C devices. + // Copyright(C) 2012 + // Francesco Ferrara + ////////////////////// + + /* Master */ + #define TW_START 0x08 + #define TW_REP_START 0x10 + + /* Master Transmitter */ + #define TW_MT_SLA_ACK 0x18 + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_ACK 0x28 + #define TW_MT_DATA_NACK 0x30 + #define TW_MT_ARB_LOST 0x38 + + /* Master Receiver */ + #define TW_MR_ARB_LOST 0x38 + #define TW_MR_SLA_ACK 0x40 + #define TW_MR_SLA_NACK 0x48 + #define TW_MR_DATA_ACK 0x50 + #define TW_MR_DATA_NACK 0x58 + + #define TW_OK 0 + #define TW_ERROR 1 + + class Fastwire { + private: + static boolean waitInt(); + + public: + static void setup(int khz, boolean pullup); + static byte beginTransmission(byte device); + static byte write(byte value); + static byte writeBuf(byte device, byte address, byte *data, byte num); + static byte readBuf(byte device, byte address, byte *data, byte num); + static void reset(); + static byte stop(); + }; +#endif + +#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + // NBWire implementation based heavily on code by Gene Knight + // Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html + // Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html + + #define NBWIRE_BUFFER_LENGTH 32 + + class TwoWire { + private: + static uint8_t rxBuffer[]; + static uint8_t rxBufferIndex; + static uint8_t rxBufferLength; + + static uint8_t txAddress; + static uint8_t txBuffer[]; + static uint8_t txBufferIndex; + static uint8_t txBufferLength; + + // static uint8_t transmitting; + static void (*user_onRequest)(void); + static void (*user_onReceive)(int); + static void onRequestService(void); + static void onReceiveService(uint8_t*, int); + + public: + TwoWire(); + void begin(); + void begin(uint8_t); + void begin(int); + void beginTransmission(uint8_t); + //void beginTransmission(int); + uint8_t endTransmission(uint16_t timeout=0); + void nbendTransmission(void (*function)(int)) ; + uint8_t requestFrom(uint8_t, int, uint16_t timeout=0); + //uint8_t requestFrom(int, int); + void nbrequestFrom(uint8_t, int, void (*function)(int)); + void send(uint8_t); + void send(uint8_t*, uint8_t); + //void send(int); + void send(char*); + uint8_t available(void); + uint8_t receive(void); + void onReceive(void (*)(int)); + void onRequest(void (*)(void)); + }; + + #define TWI_READY 0 + #define TWI_MRX 1 + #define TWI_MTX 2 + #define TWI_SRX 3 + #define TWI_STX 4 + + #define TW_WRITE 0 + #define TW_READ 1 + + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_NACK 0x30 + + #define CPU_FREQ 16000000L + #define TWI_FREQ 100000L + #define TWI_BUFFER_LENGTH 32 + + /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ + + #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) + #define TW_STATUS (TWSR & TW_STATUS_MASK) + #define TW_START 0x08 + #define TW_REP_START 0x10 + #define TW_MT_SLA_ACK 0x18 + #define TW_MT_SLA_NACK 0x20 + #define TW_MT_DATA_ACK 0x28 + #define TW_MT_DATA_NACK 0x30 + #define TW_MT_ARB_LOST 0x38 + #define TW_MR_ARB_LOST 0x38 + #define TW_MR_SLA_ACK 0x40 + #define TW_MR_SLA_NACK 0x48 + #define TW_MR_DATA_ACK 0x50 + #define TW_MR_DATA_NACK 0x58 + #define TW_ST_SLA_ACK 0xA8 + #define TW_ST_ARB_LOST_SLA_ACK 0xB0 + #define TW_ST_DATA_ACK 0xB8 + #define TW_ST_DATA_NACK 0xC0 + #define TW_ST_LAST_DATA 0xC8 + #define TW_SR_SLA_ACK 0x60 + #define TW_SR_ARB_LOST_SLA_ACK 0x68 + #define TW_SR_GCALL_ACK 0x70 + #define TW_SR_ARB_LOST_GCALL_ACK 0x78 + #define TW_SR_DATA_ACK 0x80 + #define TW_SR_DATA_NACK 0x88 + #define TW_SR_GCALL_DATA_ACK 0x90 + #define TW_SR_GCALL_DATA_NACK 0x98 + #define TW_SR_STOP 0xA0 + #define TW_NO_INFO 0xF8 + #define TW_BUS_ERROR 0x00 + + //#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) + //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) + + #ifndef sbi // set bit + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + #endif // sbi + + #ifndef cbi // clear bit + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) + #endif // cbi + + extern TwoWire Wire; + +#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE + +#endif /* _I2CDEV_H_ */ diff --git a/lib-before-5.9.1f/I2Cdevlib-Core/keywords.txt b/lib-before-5.9.1f/I2Cdevlib-Core/keywords.txt new file mode 100644 index 000000000..4132a06c3 --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-Core/keywords.txt @@ -0,0 +1,38 @@ +####################################### +# Syntax Coloring Map For I2Cdev +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### +I2Cdev KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +readBit KEYWORD2 +readBitW KEYWORD2 +readBits KEYWORD2 +readBitsW KEYWORD2 +readByte KEYWORD2 +readBytes KEYWORD2 +readWord KEYWORD2 +readWords KEYWORD2 +writeBit KEYWORD2 +writeBitW KEYWORD2 +writeBits KEYWORD2 +writeBitsW KEYWORD2 +writeByte KEYWORD2 +writeBytes KEYWORD2 +writeWord KEYWORD2 +writeWords KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/lib-before-5.9.1f/I2Cdevlib-Core/library.json b/lib-before-5.9.1f/I2Cdevlib-Core/library.json new file mode 100644 index 000000000..d45609604 --- /dev/null +++ b/lib-before-5.9.1f/I2Cdevlib-Core/library.json @@ -0,0 +1,13 @@ +{ + "name": "I2Cdevlib-Core", + "keywords": "i2cdevlib, i2c", + "description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.", + "include": "Arduino/I2Cdev", + "repository": + { + "type": "git", + "url": "https://github.com/jrowberg/i2cdevlib.git" + }, + "frameworks": "arduino", + "platforms": "atmelavr" +} diff --git a/lib/IRremoteESP8266/Contributors.md b/lib-before-5.9.1f/IRremoteESP8266/Contributors.md similarity index 100% rename from lib/IRremoteESP8266/Contributors.md rename to lib-before-5.9.1f/IRremoteESP8266/Contributors.md diff --git a/lib/IRremoteESP8266/IRDaikinESP.cpp b/lib-before-5.9.1f/IRremoteESP8266/IRDaikinESP.cpp similarity index 100% rename from lib/IRremoteESP8266/IRDaikinESP.cpp rename to lib-before-5.9.1f/IRremoteESP8266/IRDaikinESP.cpp diff --git a/lib/IRremoteESP8266/IRDaikinESP.h b/lib-before-5.9.1f/IRremoteESP8266/IRDaikinESP.h similarity index 100% rename from lib/IRremoteESP8266/IRDaikinESP.h rename to lib-before-5.9.1f/IRremoteESP8266/IRDaikinESP.h diff --git a/lib/IRremoteESP8266/IRKelvinator.cpp b/lib-before-5.9.1f/IRremoteESP8266/IRKelvinator.cpp similarity index 100% rename from lib/IRremoteESP8266/IRKelvinator.cpp rename to lib-before-5.9.1f/IRremoteESP8266/IRKelvinator.cpp diff --git a/lib/IRremoteESP8266/IRKelvinator.h b/lib-before-5.9.1f/IRremoteESP8266/IRKelvinator.h similarity index 100% rename from lib/IRremoteESP8266/IRKelvinator.h rename to lib-before-5.9.1f/IRremoteESP8266/IRKelvinator.h diff --git a/lib/IRremoteESP8266/IRMitsubishiAC.cpp b/lib-before-5.9.1f/IRremoteESP8266/IRMitsubishiAC.cpp similarity index 100% rename from lib/IRremoteESP8266/IRMitsubishiAC.cpp rename to lib-before-5.9.1f/IRremoteESP8266/IRMitsubishiAC.cpp diff --git a/lib/IRremoteESP8266/IRMitsubishiAC.h b/lib-before-5.9.1f/IRremoteESP8266/IRMitsubishiAC.h similarity index 100% rename from lib/IRremoteESP8266/IRMitsubishiAC.h rename to lib-before-5.9.1f/IRremoteESP8266/IRMitsubishiAC.h diff --git a/lib/IRremoteESP8266/IRremoteESP8266.cpp b/lib-before-5.9.1f/IRremoteESP8266/IRremoteESP8266.cpp similarity index 100% rename from lib/IRremoteESP8266/IRremoteESP8266.cpp rename to lib-before-5.9.1f/IRremoteESP8266/IRremoteESP8266.cpp diff --git a/lib/IRremoteESP8266/IRremoteESP8266.h b/lib-before-5.9.1f/IRremoteESP8266/IRremoteESP8266.h similarity index 100% rename from lib/IRremoteESP8266/IRremoteESP8266.h rename to lib-before-5.9.1f/IRremoteESP8266/IRremoteESP8266.h diff --git a/lib/IRremoteESP8266/IRremoteInt.h b/lib-before-5.9.1f/IRremoteESP8266/IRremoteInt.h similarity index 100% rename from lib/IRremoteESP8266/IRremoteInt.h rename to lib-before-5.9.1f/IRremoteESP8266/IRremoteInt.h diff --git a/lib/IRremoteESP8266/LICENSE.txt b/lib-before-5.9.1f/IRremoteESP8266/LICENSE.txt similarity index 100% rename from lib/IRremoteESP8266/LICENSE.txt rename to lib-before-5.9.1f/IRremoteESP8266/LICENSE.txt diff --git a/lib/IRremoteESP8266/README.md b/lib-before-5.9.1f/IRremoteESP8266/README.md similarity index 100% rename from lib/IRremoteESP8266/README.md rename to lib-before-5.9.1f/IRremoteESP8266/README.md diff --git a/lib/IRremoteESP8266/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/IRGCSendDemo/IRGCSendDemo.ino diff --git a/lib/IRremoteESP8266/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 100% rename from lib/IRremoteESP8266/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/IRGCTCPServer/IRGCTCPServer.ino diff --git a/lib/IRremoteESP8266/examples/IRServer/IRServer.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/IRServer/IRServer.ino similarity index 100% rename from lib/IRremoteESP8266/examples/IRServer/IRServer.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/IRServer/IRServer.ino diff --git a/lib/IRremoteESP8266/examples/IRrecvDemo/IRrecvDemo.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/IRrecvDemo/IRrecvDemo.ino similarity index 100% rename from lib/IRremoteESP8266/examples/IRrecvDemo/IRrecvDemo.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/IRrecvDemo/IRrecvDemo.ino diff --git a/lib/IRremoteESP8266/examples/IRrecvDump/IRrecvDump.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/IRrecvDump/IRrecvDump.ino similarity index 100% rename from lib/IRremoteESP8266/examples/IRrecvDump/IRrecvDump.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/IRrecvDump/IRrecvDump.ino diff --git a/lib/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino similarity index 100% rename from lib/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/IRrecvDumpV2/IRrecvDumpV2.ino diff --git a/lib/IRremoteESP8266/examples/IRsendDemo/IRsendDemo.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/IRsendDemo/IRsendDemo.ino similarity index 100% rename from lib/IRremoteESP8266/examples/IRsendDemo/IRsendDemo.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/IRsendDemo/IRsendDemo.ino diff --git a/lib/IRremoteESP8266/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino diff --git a/lib/IRremoteESP8266/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 100% rename from lib/IRremoteESP8266/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino diff --git a/lib/IRremoteESP8266/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 100% rename from lib/IRremoteESP8266/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino diff --git a/lib/IRremoteESP8266/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib-before-5.9.1f/IRremoteESP8266/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 100% rename from lib/IRremoteESP8266/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib-before-5.9.1f/IRremoteESP8266/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino diff --git a/lib/IRremoteESP8266/keywords.txt b/lib-before-5.9.1f/IRremoteESP8266/keywords.txt similarity index 100% rename from lib/IRremoteESP8266/keywords.txt rename to lib-before-5.9.1f/IRremoteESP8266/keywords.txt diff --git a/lib/IRremoteESP8266/library.json b/lib-before-5.9.1f/IRremoteESP8266/library.json similarity index 100% rename from lib/IRremoteESP8266/library.json rename to lib-before-5.9.1f/IRremoteESP8266/library.json diff --git a/lib/IRremoteESP8266/library.properties b/lib-before-5.9.1f/IRremoteESP8266/library.properties similarity index 100% rename from lib/IRremoteESP8266/library.properties rename to lib-before-5.9.1f/IRremoteESP8266/library.properties diff --git a/lib/NeoPixelBus_by_Makuna/COPYING b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/COPYING similarity index 100% rename from lib/NeoPixelBus_by_Makuna/COPYING rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/COPYING diff --git a/lib/NeoPixelBus_by_Makuna/ReadMe.md b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/ReadMe.md similarity index 100% rename from lib/NeoPixelBus_by_Makuna/ReadMe.md rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/ReadMe.md diff --git a/lib/NeoPixelBus_by_Makuna/examples/DotStarTest/DotStarTest.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/DotStarTest/DotStarTest.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/DotStarTest/DotStarTest.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/DotStarTest/DotStarTest.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelAnimation/NeoPixelAnimation.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelAnimation/NeoPixelAnimation.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelAnimation/NeoPixelAnimation.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelAnimation/NeoPixelAnimation.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/NeoPixelBitmap.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/NeoPixelBitmap.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/NeoPixelBitmap.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/NeoPixelBitmap.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/Strings.bmp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/Strings.bmp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/Strings.bmp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/Strings.bmp diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/StringsW.bmp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/StringsW.bmp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/StringsW.bmp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBitmap/StringsW.bmp diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBrightness/NeoPixelBrightness.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBrightness/NeoPixelBrightness.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBrightness/NeoPixelBrightness.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBrightness/NeoPixelBrightness.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/Cylon.pdn b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/Cylon.pdn similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/Cylon.pdn rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/Cylon.pdn diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrb.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrb.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrb.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrb.h diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrbw.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrbw.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrbw.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/CylonGrbw.h diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/NeoPixelBufferCylon.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/NeoPixelBufferCylon.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/NeoPixelBufferCylon.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelBufferCylon/NeoPixelBufferCylon.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelCylon/NeoPixelCylon.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelCylon/NeoPixelCylon.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelCylon/NeoPixelCylon.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelCylon/NeoPixelCylon.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelFunLoop/NeoPixelFunLoop.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelFunLoop/NeoPixelFunLoop.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelFunLoop/NeoPixelFunLoop.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelFunLoop/NeoPixelFunLoop.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelGamma/NeoPixelGamma.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelGamma/NeoPixelGamma.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelGamma/NeoPixelGamma.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelGamma/NeoPixelGamma.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicDump/NeoPixelMosaicDump.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicDump/NeoPixelMosaicDump.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicDump/NeoPixelMosaicDump.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicDump/NeoPixelMosaicDump.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicTest/NeoPixelMosaicTest.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicTest/NeoPixelMosaicTest.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicTest/NeoPixelMosaicTest.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelMosaicTest/NeoPixelMosaicTest.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelTest/NeoPixelTest.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTest/NeoPixelTest.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelTest/NeoPixelTest.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTest/NeoPixelTest.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelTilesDump/NeoPixelTilesDump.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTilesDump/NeoPixelTilesDump.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelTilesDump/NeoPixelTilesDump.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTilesDump/NeoPixelTilesDump.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelTilesTest/NeoPixelTilesTest.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTilesTest/NeoPixelTilesTest.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelTilesTest/NeoPixelTilesTest.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTilesTest/NeoPixelTilesTest.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyDump/NeoPixelTopologyDump.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyDump/NeoPixelTopologyDump.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyDump/NeoPixelTopologyDump.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyDump/NeoPixelTopologyDump.ino diff --git a/lib/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyTest/NeoPixelTopologyTest.ino b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyTest/NeoPixelTopologyTest.ino similarity index 100% rename from lib/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyTest/NeoPixelTopologyTest.ino rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/examples/NeoPixelTopologyTest/NeoPixelTopologyTest.ino diff --git a/lib/NeoPixelBus_by_Makuna/keywords.txt b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/keywords.txt similarity index 100% rename from lib/NeoPixelBus_by_Makuna/keywords.txt rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/keywords.txt diff --git a/lib/NeoPixelBus_by_Makuna/library.json b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/library.json similarity index 100% rename from lib/NeoPixelBus_by_Makuna/library.json rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/library.json diff --git a/lib/NeoPixelBus_by_Makuna/library.properties b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/library.properties similarity index 100% rename from lib/NeoPixelBus_by_Makuna/library.properties rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/library.properties diff --git a/lib/NeoPixelBus_by_Makuna/src/NeoPixelAnimator.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/NeoPixelAnimator.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/NeoPixelAnimator.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/NeoPixelAnimator.h diff --git a/lib/NeoPixelBus_by_Makuna/src/NeoPixelBrightnessBus.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/NeoPixelBrightnessBus.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/NeoPixelBrightnessBus.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/NeoPixelBrightnessBus.h diff --git a/lib/NeoPixelBus_by_Makuna/src/NeoPixelBus.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/NeoPixelBus.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/NeoPixelBus.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/NeoPixelBus.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/DotStarAvrMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarAvrMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/DotStarAvrMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarAvrMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/DotStarColorFeatures.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarColorFeatures.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/DotStarColorFeatures.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarColorFeatures.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/DotStarGenericMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarGenericMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/DotStarGenericMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarGenericMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/DotStarSpiMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarSpiMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/DotStarSpiMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/DotStarSpiMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HsbColor.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HsbColor.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HsbColor.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HsbColor.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HsbColor.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HsbColor.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HsbColor.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HsbColor.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HslColor.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HslColor.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HslColor.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HslColor.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HslColor.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HslColor.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HslColor.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HslColor.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HtmlColor.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColor.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HtmlColor.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColor.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HtmlColor.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColor.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HtmlColor.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColor.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorNameStrings.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorNames.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorNames.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorNames.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorNames.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorShortNames.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorShortNames.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/HtmlColorShortNames.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/HtmlColorShortNames.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/Layouts.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/Layouts.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/Layouts.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/Layouts.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoArmMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoArmMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoArmMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoArmMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoAvrMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoAvrMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoAvrMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoAvrMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoBitmapFile.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBitmapFile.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoBitmapFile.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBitmapFile.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoBuffer.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBuffer.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoBuffer.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBuffer.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoBufferContext.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBufferContext.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoBufferContext.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBufferContext.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoBufferMethods.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBufferMethods.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoBufferMethods.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoBufferMethods.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoColorFeatures.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoColorFeatures.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoColorFeatures.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoColorFeatures.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoEase.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEase.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoEase.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEase.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266BitBangMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266BitBangMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266BitBangMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266BitBangMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266DmaMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266DmaMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266DmaMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266DmaMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoEsp8266UartMethod.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoGamma.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoGamma.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoGamma.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoGamma.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoGamma.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoGamma.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoGamma.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoGamma.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoHueBlend.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoHueBlend.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoHueBlend.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoHueBlend.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoMosaic.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoMosaic.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoMosaic.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoMosaic.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoPixelAnimator.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoPixelAnimator.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoPixelAnimator.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoPixelAnimator.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoPixelAvr.c b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoPixelAvr.c similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoPixelAvr.c rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoPixelAvr.c diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoPixelEsp8266.c b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoPixelEsp8266.c similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoPixelEsp8266.c rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoPixelEsp8266.c diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoRingTopology.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoRingTopology.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoRingTopology.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoRingTopology.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoSpriteSheet.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoSpriteSheet.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoSpriteSheet.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoSpriteSheet.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoTiles.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoTiles.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoTiles.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoTiles.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/NeoTopology.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoTopology.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/NeoTopology.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/NeoTopology.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/RgbColor.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbColor.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/RgbColor.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbColor.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/RgbColor.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbColor.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/RgbColor.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbColor.h diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/RgbwColor.cpp b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbwColor.cpp similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/RgbwColor.cpp rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbwColor.cpp diff --git a/lib/NeoPixelBus_by_Makuna/src/internal/RgbwColor.h b/lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbwColor.h similarity index 100% rename from lib/NeoPixelBus_by_Makuna/src/internal/RgbwColor.h rename to lib-before-5.9.1f/NeoPixelBus_by_Makuna/src/internal/RgbwColor.h diff --git a/lib/OneWire/OneWire.cpp b/lib-before-5.9.1f/OneWire/OneWire.cpp similarity index 100% rename from lib/OneWire/OneWire.cpp rename to lib-before-5.9.1f/OneWire/OneWire.cpp diff --git a/lib/OneWire/OneWire.h b/lib-before-5.9.1f/OneWire/OneWire.h similarity index 100% rename from lib/OneWire/OneWire.h rename to lib-before-5.9.1f/OneWire/OneWire.h diff --git a/lib/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/lib-before-5.9.1f/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde similarity index 100% rename from lib/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde rename to lib-before-5.9.1f/OneWire/examples/DS18x20_Temperature/DS18x20_Temperature.pde diff --git a/lib/OneWire/examples/DS2408_Switch/DS2408_Switch.pde b/lib-before-5.9.1f/OneWire/examples/DS2408_Switch/DS2408_Switch.pde similarity index 100% rename from lib/OneWire/examples/DS2408_Switch/DS2408_Switch.pde rename to lib-before-5.9.1f/OneWire/examples/DS2408_Switch/DS2408_Switch.pde diff --git a/lib/OneWire/examples/DS250x_PROM/DS250x_PROM.pde b/lib-before-5.9.1f/OneWire/examples/DS250x_PROM/DS250x_PROM.pde similarity index 100% rename from lib/OneWire/examples/DS250x_PROM/DS250x_PROM.pde rename to lib-before-5.9.1f/OneWire/examples/DS250x_PROM/DS250x_PROM.pde diff --git a/lib/OneWire/keywords.txt b/lib-before-5.9.1f/OneWire/keywords.txt similarity index 100% rename from lib/OneWire/keywords.txt rename to lib-before-5.9.1f/OneWire/keywords.txt diff --git a/lib/OneWire/library.json b/lib-before-5.9.1f/OneWire/library.json similarity index 100% rename from lib/OneWire/library.json rename to lib-before-5.9.1f/OneWire/library.json diff --git a/lib/OneWire/library.properties b/lib-before-5.9.1f/OneWire/library.properties similarity index 100% rename from lib/OneWire/library.properties rename to lib-before-5.9.1f/OneWire/library.properties diff --git a/lib/PubSubClient/CHANGES.txt b/lib-before-5.9.1f/PubSubClient/CHANGES.txt similarity index 100% rename from lib/PubSubClient/CHANGES.txt rename to lib-before-5.9.1f/PubSubClient/CHANGES.txt diff --git a/lib/PubSubClient/LICENSE.txt b/lib-before-5.9.1f/PubSubClient/LICENSE.txt similarity index 100% rename from lib/PubSubClient/LICENSE.txt rename to lib-before-5.9.1f/PubSubClient/LICENSE.txt diff --git a/lib/PubSubClient/README.md b/lib-before-5.9.1f/PubSubClient/README.md similarity index 100% rename from lib/PubSubClient/README.md rename to lib-before-5.9.1f/PubSubClient/README.md diff --git a/lib/PubSubClient/examples/mqtt_auth/mqtt_auth.ino b/lib-before-5.9.1f/PubSubClient/examples/mqtt_auth/mqtt_auth.ino similarity index 100% rename from lib/PubSubClient/examples/mqtt_auth/mqtt_auth.ino rename to lib-before-5.9.1f/PubSubClient/examples/mqtt_auth/mqtt_auth.ino diff --git a/lib/PubSubClient/examples/mqtt_basic/mqtt_basic.ino b/lib-before-5.9.1f/PubSubClient/examples/mqtt_basic/mqtt_basic.ino similarity index 100% rename from lib/PubSubClient/examples/mqtt_basic/mqtt_basic.ino rename to lib-before-5.9.1f/PubSubClient/examples/mqtt_basic/mqtt_basic.ino diff --git a/lib/PubSubClient/examples/mqtt_esp8266/mqtt_esp8266.ino b/lib-before-5.9.1f/PubSubClient/examples/mqtt_esp8266/mqtt_esp8266.ino similarity index 100% rename from lib/PubSubClient/examples/mqtt_esp8266/mqtt_esp8266.ino rename to lib-before-5.9.1f/PubSubClient/examples/mqtt_esp8266/mqtt_esp8266.ino diff --git a/lib/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib-before-5.9.1f/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino similarity index 100% rename from lib/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino rename to lib-before-5.9.1f/PubSubClient/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/lib/PubSubClient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib-before-5.9.1f/PubSubClient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino similarity index 100% rename from lib/PubSubClient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino rename to lib-before-5.9.1f/PubSubClient/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino diff --git a/lib/PubSubClient/examples/mqtt_stream/mqtt_stream.ino b/lib-before-5.9.1f/PubSubClient/examples/mqtt_stream/mqtt_stream.ino similarity index 100% rename from lib/PubSubClient/examples/mqtt_stream/mqtt_stream.ino rename to lib-before-5.9.1f/PubSubClient/examples/mqtt_stream/mqtt_stream.ino diff --git a/lib/PubSubClient/keywords.txt b/lib-before-5.9.1f/PubSubClient/keywords.txt similarity index 100% rename from lib/PubSubClient/keywords.txt rename to lib-before-5.9.1f/PubSubClient/keywords.txt diff --git a/lib/PubSubClient/library.json b/lib-before-5.9.1f/PubSubClient/library.json similarity index 100% rename from lib/PubSubClient/library.json rename to lib-before-5.9.1f/PubSubClient/library.json diff --git a/lib/PubSubClient/library.properties b/lib-before-5.9.1f/PubSubClient/library.properties similarity index 100% rename from lib/PubSubClient/library.properties rename to lib-before-5.9.1f/PubSubClient/library.properties diff --git a/lib/PubSubClient/src/PubSubClient.cpp b/lib-before-5.9.1f/PubSubClient/src/PubSubClient.cpp similarity index 100% rename from lib/PubSubClient/src/PubSubClient.cpp rename to lib-before-5.9.1f/PubSubClient/src/PubSubClient.cpp diff --git a/lib/PubSubClient/src/PubSubClient.h b/lib-before-5.9.1f/PubSubClient/src/PubSubClient.h similarity index 100% rename from lib/PubSubClient/src/PubSubClient.h rename to lib-before-5.9.1f/PubSubClient/src/PubSubClient.h diff --git a/lib/PubSubClient/tests/.gitignore b/lib-before-5.9.1f/PubSubClient/tests/.gitignore similarity index 100% rename from lib/PubSubClient/tests/.gitignore rename to lib-before-5.9.1f/PubSubClient/tests/.gitignore diff --git a/lib/PubSubClient/tests/Makefile b/lib-before-5.9.1f/PubSubClient/tests/Makefile similarity index 100% rename from lib/PubSubClient/tests/Makefile rename to lib-before-5.9.1f/PubSubClient/tests/Makefile diff --git a/lib/PubSubClient/tests/README.md b/lib-before-5.9.1f/PubSubClient/tests/README.md similarity index 100% rename from lib/PubSubClient/tests/README.md rename to lib-before-5.9.1f/PubSubClient/tests/README.md diff --git a/lib/PubSubClient/tests/src/connect_spec.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/connect_spec.cpp similarity index 100% rename from lib/PubSubClient/tests/src/connect_spec.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/connect_spec.cpp diff --git a/lib/PubSubClient/tests/src/keepalive_spec.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/keepalive_spec.cpp similarity index 100% rename from lib/PubSubClient/tests/src/keepalive_spec.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/keepalive_spec.cpp diff --git a/lib/PubSubClient/tests/src/lib/Arduino.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/Arduino.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/Arduino.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/Arduino.h diff --git a/lib/PubSubClient/tests/src/lib/BDDTest.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/lib/BDDTest.cpp similarity index 100% rename from lib/PubSubClient/tests/src/lib/BDDTest.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/BDDTest.cpp diff --git a/lib/PubSubClient/tests/src/lib/BDDTest.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/BDDTest.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/BDDTest.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/BDDTest.h diff --git a/lib/PubSubClient/tests/src/lib/Buffer.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/lib/Buffer.cpp similarity index 100% rename from lib/PubSubClient/tests/src/lib/Buffer.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/Buffer.cpp diff --git a/lib/PubSubClient/tests/src/lib/Buffer.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/Buffer.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/Buffer.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/Buffer.h diff --git a/lib/PubSubClient/tests/src/lib/Client.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/Client.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/Client.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/Client.h diff --git a/lib/PubSubClient/tests/src/lib/IPAddress.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/lib/IPAddress.cpp similarity index 100% rename from lib/PubSubClient/tests/src/lib/IPAddress.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/IPAddress.cpp diff --git a/lib/PubSubClient/tests/src/lib/IPAddress.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/IPAddress.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/IPAddress.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/IPAddress.h diff --git a/lib/PubSubClient/tests/src/lib/ShimClient.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/lib/ShimClient.cpp similarity index 100% rename from lib/PubSubClient/tests/src/lib/ShimClient.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/ShimClient.cpp diff --git a/lib/PubSubClient/tests/src/lib/ShimClient.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/ShimClient.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/ShimClient.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/ShimClient.h diff --git a/lib/PubSubClient/tests/src/lib/Stream.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/lib/Stream.cpp similarity index 100% rename from lib/PubSubClient/tests/src/lib/Stream.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/Stream.cpp diff --git a/lib/PubSubClient/tests/src/lib/Stream.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/Stream.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/Stream.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/Stream.h diff --git a/lib/PubSubClient/tests/src/lib/trace.h b/lib-before-5.9.1f/PubSubClient/tests/src/lib/trace.h similarity index 100% rename from lib/PubSubClient/tests/src/lib/trace.h rename to lib-before-5.9.1f/PubSubClient/tests/src/lib/trace.h diff --git a/lib/PubSubClient/tests/src/publish_spec.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/publish_spec.cpp similarity index 100% rename from lib/PubSubClient/tests/src/publish_spec.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/publish_spec.cpp diff --git a/lib/PubSubClient/tests/src/receive_spec.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/receive_spec.cpp similarity index 100% rename from lib/PubSubClient/tests/src/receive_spec.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/receive_spec.cpp diff --git a/lib/PubSubClient/tests/src/subscribe_spec.cpp b/lib-before-5.9.1f/PubSubClient/tests/src/subscribe_spec.cpp similarity index 100% rename from lib/PubSubClient/tests/src/subscribe_spec.cpp rename to lib-before-5.9.1f/PubSubClient/tests/src/subscribe_spec.cpp diff --git a/lib/PubSubClient/tests/testcases/__init__.py b/lib-before-5.9.1f/PubSubClient/tests/testcases/__init__.py similarity index 100% rename from lib/PubSubClient/tests/testcases/__init__.py rename to lib-before-5.9.1f/PubSubClient/tests/testcases/__init__.py diff --git a/lib/PubSubClient/tests/testcases/mqtt_basic.py b/lib-before-5.9.1f/PubSubClient/tests/testcases/mqtt_basic.py similarity index 100% rename from lib/PubSubClient/tests/testcases/mqtt_basic.py rename to lib-before-5.9.1f/PubSubClient/tests/testcases/mqtt_basic.py diff --git a/lib/PubSubClient/tests/testcases/mqtt_publish_in_callback.py b/lib-before-5.9.1f/PubSubClient/tests/testcases/mqtt_publish_in_callback.py similarity index 100% rename from lib/PubSubClient/tests/testcases/mqtt_publish_in_callback.py rename to lib-before-5.9.1f/PubSubClient/tests/testcases/mqtt_publish_in_callback.py diff --git a/lib/PubSubClient/tests/testcases/settings.py b/lib-before-5.9.1f/PubSubClient/tests/testcases/settings.py similarity index 100% rename from lib/PubSubClient/tests/testcases/settings.py rename to lib-before-5.9.1f/PubSubClient/tests/testcases/settings.py diff --git a/lib/PubSubClient/tests/testsuite.py b/lib-before-5.9.1f/PubSubClient/tests/testsuite.py similarity index 100% rename from lib/PubSubClient/tests/testsuite.py rename to lib-before-5.9.1f/PubSubClient/tests/testsuite.py diff --git a/lib/ArduinoJson-5.11.2/ArduinoJson.h b/lib/ArduinoJson-5.11.2/ArduinoJson.h new file mode 100644 index 000000000..896503a6c --- /dev/null +++ b/lib/ArduinoJson-5.11.2/ArduinoJson.h @@ -0,0 +1,8 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#include "src/ArduinoJson.h" diff --git a/lib/ArduinoJson-5.11.2/CHANGELOG.md b/lib/ArduinoJson-5.11.2/CHANGELOG.md new file mode 100644 index 000000000..490e25c8c --- /dev/null +++ b/lib/ArduinoJson-5.11.2/CHANGELOG.md @@ -0,0 +1,512 @@ +ArduinoJson: change log +======================= + +v5.11.2 +------- + +* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561) +* Fixed incorrect rounding for float values (issue #588) + +v5.11.1 +------- + +* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546) +* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]" +* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544) +* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539) +* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless. +* Fixed too many decimals places in float serialization (issue #543) + +v5.11.0 +------- + +* Made `JsonBuffer` non-copyable (PR #524 by @luisrayas3) +* Added `StaticJsonBuffer::clear()` +* Added `DynamicJsonBuffer::clear()` + +v5.10.1 +------- + +* Fixed IntelliSense errors in Visual Micro (issue #483) +* Fixed compilation in IAR Embedded Workbench (issue #515) +* Fixed reading "true" as a float (issue #516) +* Added `ARDUINOJSON_DOUBLE_IS_64BITS` +* Added `ARDUINOJSON_EMBEDDED_MODE` + +v5.10.0 +------- + +* Removed configurable number of decimal places (issues #288, #427 and #506) +* Changed exponentiation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506) +* `JsonVariant::is()` now returns `true` for integers +* Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495) +* Fixed error `forming reference to reference` (issue #495) + +### BREAKING CHANGES :warning: + +| Old syntax | New syntax | +|---------------------------------|---------------------| +| `double_with_n_digits(3.14, 2)` | `3.14` | +| `float_with_n_digits(3.14, 2)` | `3.14f` | +| `obj.set("key", 3.14, 2)` | `obj["key"] = 3.14` | +| `arr.add(3.14, 2)` | `arr.add(3.14)` | + +| Input | Old output | New output | +|-----------|------------|------------| +| `3.14159` | `3.14` | `3.14159` | +| `42.0` | `42.00` | `42` | +| `0.0` | `0.00` | `0` | + +| Expression | Old result | New result | +|--------------------------------|------------|------------| +| `JsonVariant(42).is()` | `true` | `true` | +| `JsonVariant(42).is()` | `false` | `true` | +| `JsonVariant(42).is()` | `false` | `true` | + + +v5.9.0 +------ + +* Added `JsonArray::remove(iterator)` (issue #479) +* Added `JsonObject::remove(iterator)` +* Renamed `JsonArray::removeAt(size_t)` into `remove(size_t)` +* Renamed folder `include/` to `src/` +* Fixed warnings `floating constant exceeds range of float`and `floating constant truncated to zero` (issue #483) +* Removed `Print` class and converted `printTo()` to a template method (issue #276) +* Removed example `IndentedPrintExample.ino` +* Now compatible with Particle 0.6.1, thanks to Jacob Nite (issue #294 and PR #461 by @foodbag) + +v5.8.4 +------ + +* Added custom implementation of `strtod()` (issue #453) +* Added custom implementation of `strtol()` (issue #465) +* `char` is now treated as an integral type (issue #337, #370) + +v5.8.3 +------ + +* Fixed an access violation in `DynamicJsonBuffer` when memory allocation fails (issue #433) +* Added operators `==` and `!=` for two `JsonVariant`s (issue #436) +* Fixed `JsonVariant::operator[const FlashStringHelper*]` (issue #441) + +v5.8.2 +------ + +* Fixed parsing of comments (issue #421) +* Fixed ignored `Stream` timeout (issue #422) +* Made sure we don't read more that necessary (issue #422) +* Fixed error when the key of a `JsonObject` is a `char[]` (issue #423) +* Reduced code size when using `const` references +* Fixed error with string of type `unsigned char*` (issue #428) +* Added `deprecated` attribute on `asArray()`, `asObject()` and `asString()` (issue #420) + +v5.8.1 +------ + +* Fixed error when assigning a `volatile int` to a `JsonVariant` (issue #415) +* Fixed errors with Variable Length Arrays (issue #416) +* Fixed error when both `ARDUINOJSON_ENABLE_STD_STREAM` and `ARDUINOJSON_ENABLE_ARDUINO_STREAM` are set to `1` +* Fixed error "Stream does not name a type" (issue #412) + +v5.8.0 +------ + +* Added operator `==` to compare `JsonVariant` and strings (issue #402) +* Added support for `Stream` (issue #300) +* Reduced memory consumption by not duplicating spaces and comments + +### BREAKING CHANGES :warning: + +`JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`. + +This means that if you have code like: + +```c++ +void myFunction(JsonBuffer& jsonBuffer); +``` + +you need to replace it with one of the following: + +```c++ +void myFunction(DynamicJsonBuffer& jsonBuffer); +void myFunction(StaticJsonBufferBase& jsonBuffer); +template void myFunction(TJsonBuffer& jsonBuffer); +``` + + +v5.7.3 +------ + +* Added an `printTo(char[N])` and `prettyPrintTo(char[N])` (issue #292) +* Added ability to set a nested value like this: `root["A"]["B"] = "C"` (issue #352) +* Renamed `*.ipp` to `*Impl.hpp` because they were ignored by Arduino IDE (issue #396) + +v5.7.2 +------ + +* Made PROGMEM available on more platforms (issue #381) +* Fixed PROGMEM causing an exception on ESP8266 (issue #383) + +v5.7.1 +------ + +* Added support for PROGMEM (issue #76) +* Fixed compilation error when index is not an `int` (issue #381) + +v5.7.0 +------ + +* Templatized all functions using `String` or `std::string` +* Removed `ArduinoJson::String` +* Removed `JsonVariant::defaultValue()` +* Removed non-template `JsonObject::get()` and `JsonArray.get()` +* Fixed support for `StringSumHelper` (issue #184) +* Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378) +* Added example `StringExample.ino` to show where `String` can be used +* Increased default nesting limit to 50 when compiled for a computer (issue #349) + +### BREAKING CHANGES :warning: + +The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return. + +Old code: + +```c++ +#define ARDUINOJSON_USE_ARDUINO_STRING 0 +JsonVariant value1 = myObject.get("myKey"); +JsonVariant value2 = myArray.get(0); +``` + +New code: + +```c++ +#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 +#define ARDUINOJSON_ENABLE_STD_STRING 1 +JsonVariant value1 = myObject.get("myKey"); +JsonVariant value2 = myArray.get(0); +``` + + +v5.6.7 +------ + +* Fixed `array[idx].as()` and `object[key].as()` +* Fixed return value of `JsonObject::set()` (issue #350) +* Fixed undefined behavior in `Prettyfier` and `Print` (issue #354) +* Fixed parser that incorrectly rejected floats containing a `+` (issue #349) + +v5.6.6 +------ + +* Fixed `-Wparentheses` warning introduced in v5.6.5 (PR #335 by @nuket) +* Added `.mbedignore` for ARM mbdeb (PR #334 by @nuket) +* Fixed `JsonVariant::success()` which didn't propagate `JsonArray::success()` nor `JsonObject::success()` (issue #342). + +v5.6.5 +------ + +* `as()` now returns `true` when input is `null` (issue #330) + +v5.6.4 +------ + +* Fixed error in float serialization (issue #324) + +v5.6.3 +------ + +* Improved speed of float serialization (about twice faster) +* Added `as()` as a synonym for `as()`... (issue #291) +* Fixed `call of overloaded isinf(double&) is ambiguous` (issue #284) + +v5.6.2 +------ + +* Fixed build when another lib does `#undef isnan` (issue #284) + +v5.6.1 +------ + +* Added missing `#pragma once` (issue #310) + +v5.6.0 +------ + +* ArduinoJson is now a header-only library (issue #199) + +v5.5.1 +------ + +* Fixed compilation error with Intel Galileo (issue #299) + +v5.5.0 +------ + +* Added `JsonVariant::success()` (issue #279) +* Renamed `JsonVariant::invalid()` to `JsonVariant::defaultValue()` + +v5.4.0 +------ + +* Changed `::String` to `ArduinoJson::String` (issue #275) +* Changed `::Print` to `ArduinoJson::Print` too + +v5.3.0 +------ + +* Added custom implementation of `ftoa` (issues #266, #267, #269 and #270) +* Added `JsonVariant JsonBuffer::parse()` (issue #265) +* Fixed `unsigned long` printed as `signed long` (issue #170) + +v5.2.0 +------ + +* Added `JsonVariant::as()` as a synonym for `JsonVariant::as()` (issue #257) +* Added example `JsonHttpClient` (issue #256) +* Added `JsonArray::copyTo()` and `JsonArray::copyFrom()` (issue #254) +* Added `RawJson()` to insert pregenerated JSON portions (issue #259) + +v5.1.1 +------ + +* Removed `String` duplication when one replaces a value in a `JsonObject` (PR #232 by @ulion) + +v5.1.0 +------ + +* Added support of `long long` (issue #171) +* Moved all build settings to `ArduinoJson/Configuration.hpp` + +**BREAKING CHANGE**: +If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`. + +v5.0.8 +------ + +* Made the library compatible with [PlatformIO](http://platformio.org/) (issue #181) +* Fixed `JsonVariant::is()` that was incorrectly returning false (issue #214) + +v5.0.7 +------ + +* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)` +* Changed `String` to be a `typedef` of `std::string` (issues #142 and #161) + +### BREAKING CHANGES :warning: + +- `JsonVariant(true).as()` now returns `"true"` instead of `"1"` +- `JsonVariant(false).as()` now returns `"false"` instead of `"0"` + +v5.0.6 +------ + +* Added parameter to `DynamicJsonBuffer` constructor to set initial size (issue #152) +* Fixed warning about library category in Arduino 1.6.6 (issue #147) +* Examples: Added a loop to wait for serial port to be ready (issue #156) + +v5.0.5 +------ + +* Added overload `JsonObjectSuscript::set(value, decimals)` (issue #143) +* Use `float` instead of `double` to reduce the size of `JsonVariant` (issue #134) + +v5.0.4 +------ + +* Fixed ambiguous overload with `JsonArraySubscript` and `JsonObjectSubscript` (issue #122) + +v5.0.3 +------ + +* Fixed `printTo(String)` which wrote numbers instead of strings (issue #120) +* Fixed return type of `JsonArray::is()` and some others (issue #121) + +v5.0.2 +------ + +* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the + `StaticJsonBuffer` is too small to hold a copy of the string +* Fixed Clang warning "register specifier is deprecated" (issue #102) +* Fixed GCC warning "declaration shadows a member" (issue #103) +* Fixed memory alignment, which made ESP8266 crash (issue #104) +* Fixed compilation on Visual Studio 2010 and 2012 (issue #107) + +v5.0.1 +------ + +* Fixed compilation with Arduino 1.0.6 (issue #99) + +v5.0.0 +------ + +* Added support of `String` class (issues #55, #56, #70, #77) +* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57) +* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87) +* Added support of non standard JSON input (issue #44) +* Added support of comments in JSON input (issue #88) +* Added implicit cast between numerical types (issues #64, #69, #93) +* Added ability to read number values as string (issue #90) +* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) +* Switched to new the library layout (requires Arduino 1.0.6 or above) + +### BREAKING CHANGES :warning: + +- `JsonObject::add()` was renamed to `set()` +- `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` +- Number of digits of floating point value are now set with `double_with_n_digits()` + +**Personal note about the `String` class**: +Support of the `String` class has been added to the library because many people use it in their programs. +However, you should not see this as an invitation to use the `String` class. +The `String` class is **bad** because it uses dynamic memory allocation. +Compared to static allocation, it compiles to a bigger, slower program, and is less predictable. +You certainly don't want that in an embedded environment! + +v4.6 +---- + +* Fixed segmentation fault in `DynamicJsonBuffer` when memory allocation fails (issue #92) + +v4.5 +---- + +* Fixed buffer overflow when input contains a backslash followed by a terminator (issue #81) + +**Upgrading is recommended** since previous versions contain a potential security risk. + +Special thanks to [Giancarlo Canales Barreto](https://github.com/gcanalesb) for finding this nasty bug. + +v4.4 +---- + +* Added `JsonArray::measureLength()` and `JsonObject::measureLength()` (issue #75) + +v4.3 +---- + +* Added `JsonArray::removeAt()` to remove an element of an array (issue #58) +* Fixed stack-overflow in `DynamicJsonBuffer` when parsing huge JSON files (issue #65) +* Fixed wrong return value of `parseArray()` and `parseObject()` when allocation fails (issue #68) + +v4.2 +---- + +* Switched back to old library layout (issues #39, #43 and #45) +* Removed global new operator overload (issue #40, #45 and #46) +* Added an example with EthernetServer + +v4.1 +---- + +* Added DynamicJsonBuffer (issue #19) + +v4.0 +---- + +* Unified parser and generator API (issue #23) +* Updated library layout, now requires Arduino 1.0.6 or newer + +**BREAKING CHANGE**: API changed significantly, see [Migrating code to the new API](https://github.com/bblanchon/ArduinoJson/wiki/Migrating-code-to-the-new-API). + + +v3.4 +---- + +* Fixed escaped char parsing (issue #16) + + +v3.3 +---- + +* Added indented output for the JSON generator (issue #11), see example bellow. +* Added `IndentedPrint`, a decorator for `Print` to allow indented output + +Example: + + JsonOject<2> json; + json["key"] = "value"; + json.prettyPrintTo(Serial); + +v3.2 +---- + +* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1). + +v3.1 +---- + +* Calling `Generator::JsonObject::add()` twice with the same `key` now replaces the `value` +* Added `Generator::JsonObject::operator[]`, see bellow the new API +* Added `Generator::JsonObject::remove()` (issue #9) + +Old generator API: + + JsonObject<3> root; + root.add("sensor", "gps"); + root.add("time", 1351824120); + root.add("data", array); + +New generator API: + + JsonObject<3> root; + root["sensor"] = "gps"; + root["time"] = 1351824120; + root["data"] = array; + +v3.0 +---- + +* New parser API, see bellow +* Renamed `JsonHashTable` into `JsonObject` +* Added iterators for `JsonArray` and `JsonObject` (issue #4) + +Old parser API: + + JsonHashTable root = parser.parseHashTable(json); + + char* sensor = root.getString("sensor"); + long time = root.getLong("time"); + double latitude = root.getArray("data").getDouble(0); + double longitude = root.getArray("data").getDouble(1); + +New parser API: + + JsonObject root = parser.parse(json); + + char* sensor = root["sensor"]; + long time = root["time"]; + double latitude = root["data"][0]; + double longitude = root["data"][1]; + +v2.1 +---- + +* Fixed case `#include "jsmn.cpp"` which caused an error in Linux (issue #6) +* Fixed a buffer overrun in JSON Parser (issue #5) + +v2.0 +---- + +* Added JSON encoding (issue #2) +* Renamed the library `ArduinoJsonParser` becomes `ArduinoJson` + +**Breaking change**: you need to add the following line at the top of your program. + + using namespace ArduinoJson::Parser; + +v1.2 +---- + +* Fixed error in JSON parser example (issue #1) + +v1.1 +---- + +* Example: changed `char* json` into `char[] json` so that the bytes are not write protected +* Fixed parsing bug when the JSON contains multi-dimensional arrays + +v1.0 +---- + +Initial release diff --git a/lib/ArduinoJson-5.11.2/LICENSE.md b/lib/ArduinoJson-5.11.2/LICENSE.md new file mode 100644 index 000000000..9f35ed446 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/LICENSE.md @@ -0,0 +1,10 @@ +The MIT License (MIT) +--------------------- + +Copyright © 2014-2017 Benoit BLANCHON + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 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 furnished 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 FOR 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. diff --git a/lib/ArduinoJson-5.11.2/README.md b/lib/ArduinoJson-5.11.2/README.md new file mode 100644 index 000000000..6ee8a37a6 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/README.md @@ -0,0 +1,130 @@ +[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/master?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson) + +![ArduinoJson's logo](banner.svg) + +ArduinoJson - C++ JSON library for IoT +==================== + +*An elegant and efficient JSON library for embedded systems.* + +It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc). + +It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project. +For instance, it supports Aduino's `String` and `Stream`, but also `std::string`, `std::istream` and `std::ostream`. + +Features +-------- + +* JSON decoding (comments are supported) +* JSON encoding (with optional indentation) +* Elegant API, very easy to use +* Fixed memory allocation (zero malloc) +* No data duplication (zero copy) +* Portable (written in C++98) +* Self-contained (no external dependency) +* Small footprint +* Header-only library +* MIT License + +Works on +-------- + +* Arduino boards: Uno, Due, Mini, Micro, Yun... +* ESP8266, ESP32 +* Teensy +* RedBearLab boards (BLE Nano...) +* Intel Edison and Galileo +* WeMos boards: D1... +* Computers: Windows, Linux, OSX... +* PlatformIO +* Particle +* Energia + +Quick start +----------- + +#### Decoding / Parsing + +```c++ +char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; + +StaticJsonBuffer<200> jsonBuffer; + +JsonObject& root = jsonBuffer.parseObject(json); + +const char* sensor = root["sensor"]; +long time = root["time"]; +double latitude = root["data"][0]; +double longitude = root["data"][1]; +``` + +[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino) + +Use [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) to compute the buffer size. + +#### Encoding / Generating + +```c++ +StaticJsonBuffer<200> jsonBuffer; + +JsonObject& root = jsonBuffer.createObject(); +root["sensor"] = "gps"; +root["time"] = 1351824120; + +JsonArray& data = root.createNestedArray("data"); +data.add(48.756080); +data.add(2.302038); + +root.printTo(Serial); +// This prints: +// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} +``` + +[See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino) + +Use [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) to compute the buffer size. + + +Documentation +------------- + +The documentation is available online in the [ArduinoJson Website](https://bblanchon.github.io/ArduinoJson/). + +The [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) helps you get started with the library. + + +Donators +-------- + +Special thanks to the following persons and companies who made generous donations to the library author: + +* Robert Murphy USA +* Surge Communications USA +* Alex Scott United Kingdom +* Firepick Services LLC USA +* A B Doodkorte Netherlands +* Scott Smith USA +* Johann Stieger Austria +* Gustavo Donizeti Gini Brazil +* Charles-Henri Hallard France +* Martijn van den Burg Netherlands +* Nick Koumaris Greece +* Jon Williams USA +* Kestutis Liaugminas Lithuania +* Darlington Adibe Nigeria +* Yoeri Kroon Netherlands +* Andrew Melvin United Kingdom +* Doanh Luong Vietnam +* Christoph Schmidt Germany +* OpenEVSE LLC USA +* Prokhoryatov Alexey Russia +* Google Inc. USA +* Charles Haynes Australia +* Charles Walker USA +* Günther Jehle Liechtenstein +* Patrick Elliott + + +--- + +Found this library useful? Please star this project or [help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile: diff --git a/lib/ArduinoJson-5.11.2/examples/JsonGeneratorExample/JsonGeneratorExample.ino b/lib/ArduinoJson-5.11.2/examples/JsonGeneratorExample/JsonGeneratorExample.ino new file mode 100644 index 000000000..0f636faf8 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/examples/JsonGeneratorExample/JsonGeneratorExample.ino @@ -0,0 +1,70 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#include + +void setup() { + Serial.begin(9600); + while (!Serial) { + // wait serial port initialization + } + + // Memory pool for JSON object tree. + // + // Inside the brackets, 200 is the size of the pool in bytes. + // If the JSON object is more complex, you need to increase that value. + // See https://bblanchon.github.io/ArduinoJson/assistant/ + StaticJsonBuffer<200> jsonBuffer; + + // StaticJsonBuffer allocates memory on the stack, it can be + // replaced by DynamicJsonBuffer which allocates in the heap. + // + // DynamicJsonBuffer jsonBuffer(200); + + // Create the root of the object tree. + // + // It's a reference to the JsonObject, the actual bytes are inside the + // JsonBuffer with all the other nodes of the object tree. + // Memory is freed when jsonBuffer goes out of scope. + JsonObject& root = jsonBuffer.createObject(); + + // Add values in the object + // + // Most of the time, you can rely on the implicit casts. + // In other case, you can do root.set("time", 1351824120); + root["sensor"] = "gps"; + root["time"] = 1351824120; + + // Add a nested array. + // + // It's also possible to create the array separately and add it to the + // JsonObject but it's less efficient. + JsonArray& data = root.createNestedArray("data"); + data.add(48.756080); + data.add(2.302038); + + root.printTo(Serial); + // This prints: + // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} + + Serial.println(); + + root.prettyPrintTo(Serial); + // This prints: + // { + // "sensor": "gps", + // "time": 1351824120, + // "data": [ + // 48.756080, + // 2.302038 + // ] + // } +} + +void loop() { + // not used in this example +} diff --git a/lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino b/lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino new file mode 100644 index 000000000..5edb817f1 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/examples/JsonHttpClient/JsonHttpClient.ino @@ -0,0 +1,184 @@ +// Sample Arduino Json Web Client +// Downloads and parse http://jsonplaceholder.typicode.com/users/1 +// +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#include +#include +#include + +EthernetClient client; + +const char* server = "jsonplaceholder.typicode.com"; // server's address +const char* resource = "/users/1"; // http resource +const unsigned long BAUD_RATE = 9600; // serial connection speed +const unsigned long HTTP_TIMEOUT = 10000; // max respone time from server +const size_t MAX_CONTENT_SIZE = 512; // max size of the HTTP response + +// The type of data that we want to extract from the page +struct UserData { + char name[32]; + char company[32]; +}; + +// ARDUINO entry point #1: runs once when you press reset or power the board +void setup() { + initSerial(); + initEthernet(); +} + +// ARDUINO entry point #2: runs over and over again forever +void loop() { + if (connect(server)) { + if (sendRequest(server, resource) && skipResponseHeaders()) { + UserData userData; + if (readReponseContent(&userData)) { + printUserData(&userData); + } + } + } + disconnect(); + wait(); +} + +// Initialize Serial port +void initSerial() { + Serial.begin(BAUD_RATE); + while (!Serial) { + ; // wait for serial port to initialize + } + Serial.println("Serial ready"); +} + +// Initialize Ethernet library +void initEthernet() { + byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; + if (!Ethernet.begin(mac)) { + Serial.println("Failed to configure Ethernet"); + return; + } + Serial.println("Ethernet ready"); + delay(1000); +} + +// Open connection to the HTTP server +bool connect(const char* hostName) { + Serial.print("Connect to "); + Serial.println(hostName); + + bool ok = client.connect(hostName, 80); + + Serial.println(ok ? "Connected" : "Connection Failed!"); + return ok; +} + +// Send the HTTP GET request to the server +bool sendRequest(const char* host, const char* resource) { + Serial.print("GET "); + Serial.println(resource); + + client.print("GET "); + client.print(resource); + client.println(" HTTP/1.0"); + client.print("Host: "); + client.println(host); + client.println("Connection: close"); + client.println(); + + return true; +} + +// Skip HTTP headers so that we are at the beginning of the response's body +bool skipResponseHeaders() { + // HTTP headers end with an empty line + char endOfHeaders[] = "\r\n\r\n"; + + client.setTimeout(HTTP_TIMEOUT); + bool ok = client.find(endOfHeaders); + + if (!ok) { + Serial.println("No response or invalid response!"); + } + + return ok; +} + +// Parse the JSON from the input string and extract the interesting values +// Here is the JSON we need to parse +// { +// "id": 1, +// "name": "Leanne Graham", +// "username": "Bret", +// "email": "Sincere@april.biz", +// "address": { +// "street": "Kulas Light", +// "suite": "Apt. 556", +// "city": "Gwenborough", +// "zipcode": "92998-3874", +// "geo": { +// "lat": "-37.3159", +// "lng": "81.1496" +// } +// }, +// "phone": "1-770-736-8031 x56442", +// "website": "hildegard.org", +// "company": { +// "name": "Romaguera-Crona", +// "catchPhrase": "Multi-layered client-server neural-net", +// "bs": "harness real-time e-markets" +// } +// } +bool readReponseContent(struct UserData* userData) { + // Compute optimal size of the JSON buffer according to what we need to parse. + // See https://bblanchon.github.io/ArduinoJson/assistant/ + const size_t BUFFER_SIZE = + JSON_OBJECT_SIZE(8) // the root object has 8 elements + + JSON_OBJECT_SIZE(5) // the "address" object has 5 elements + + JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements + + JSON_OBJECT_SIZE(3) // the "company" object has 3 elements + + MAX_CONTENT_SIZE; // additional space for strings + + // Allocate a temporary memory pool + DynamicJsonBuffer jsonBuffer(BUFFER_SIZE); + + JsonObject& root = jsonBuffer.parseObject(client); + + if (!root.success()) { + Serial.println("JSON parsing failed!"); + return false; + } + + // Here were copy the strings we're interested in + strcpy(userData->name, root["name"]); + strcpy(userData->company, root["company"]["name"]); + // It's not mandatory to make a copy, you could just use the pointers + // Since, they are pointing inside the "content" buffer, so you need to make + // sure it's still in memory when you read the string + + return true; +} + +// Print the data extracted from the JSON +void printUserData(const struct UserData* userData) { + Serial.print("Name = "); + Serial.println(userData->name); + Serial.print("Company = "); + Serial.println(userData->company); +} + +// Close the connection with the HTTP server +void disconnect() { + Serial.println("Disconnect"); + client.stop(); +} + +// Pause for a 1 minute +void wait() { + Serial.println("Wait 60 seconds"); + delay(60000); +} diff --git a/lib/ArduinoJson-5.11.2/examples/JsonParserExample/JsonParserExample.ino b/lib/ArduinoJson-5.11.2/examples/JsonParserExample/JsonParserExample.ino new file mode 100644 index 000000000..719d2ee28 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/examples/JsonParserExample/JsonParserExample.ino @@ -0,0 +1,67 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#include + +void setup() { + Serial.begin(9600); + while (!Serial) { + // wait serial port initialization + } + + // Memory pool for JSON object tree. + // + // Inside the brackets, 200 is the size of the pool in bytes, + // If the JSON object is more complex, you need to increase that value. + // See https://bblanchon.github.io/ArduinoJson/assistant/ + StaticJsonBuffer<200> jsonBuffer; + + // StaticJsonBuffer allocates memory on the stack, it can be + // replaced by DynamicJsonBuffer which allocates in the heap. + // + // DynamicJsonBuffer jsonBuffer(200); + + // JSON input string. + // + // It's better to use a char[] as shown here. + // If you use a const char* or a String, ArduinoJson will + // have to make a copy of the input in the JsonBuffer. + char json[] = + "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; + + // Root of the object tree. + // + // It's a reference to the JsonObject, the actual bytes are inside the + // JsonBuffer with all the other nodes of the object tree. + // Memory is freed when jsonBuffer goes out of scope. + JsonObject& root = jsonBuffer.parseObject(json); + + // Test if parsing succeeds. + if (!root.success()) { + Serial.println("parseObject() failed"); + return; + } + + // Fetch values. + // + // Most of the time, you can rely on the implicit casts. + // In other case, you can do root["time"].as(); + const char* sensor = root["sensor"]; + long time = root["time"]; + double latitude = root["data"][0]; + double longitude = root["data"][1]; + + // Print values. + Serial.println(sensor); + Serial.println(time); + Serial.println(latitude, 6); + Serial.println(longitude, 6); +} + +void loop() { + // not used in this example +} diff --git a/lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino b/lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino new file mode 100644 index 000000000..555842b82 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/examples/JsonServer/JsonServer.ino @@ -0,0 +1,76 @@ +// Sample Arduino Json Web Server +// Created by Benoit Blanchon. +// Heavily inspired by "Web Server" from David A. Mellis and Tom Igoe + +#include +#include +#include + +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +IPAddress ip(192, 168, 0, 177); +EthernetServer server(80); + +bool readRequest(EthernetClient& client) { + bool currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + if (c == '\n' && currentLineIsBlank) { + return true; + } else if (c == '\n') { + currentLineIsBlank = true; + } else if (c != '\r') { + currentLineIsBlank = false; + } + } + } + return false; +} + +JsonObject& prepareResponse(JsonBuffer& jsonBuffer) { + JsonObject& root = jsonBuffer.createObject(); + + JsonArray& analogValues = root.createNestedArray("analog"); + for (int pin = 0; pin < 6; pin++) { + int value = analogRead(pin); + analogValues.add(value); + } + + JsonArray& digitalValues = root.createNestedArray("digital"); + for (int pin = 0; pin < 14; pin++) { + int value = digitalRead(pin); + digitalValues.add(value); + } + + return root; +} + +void writeResponse(EthernetClient& client, JsonObject& json) { + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: application/json"); + client.println("Connection: close"); + client.println(); + + json.prettyPrintTo(client); +} + +void setup() { + Ethernet.begin(mac, ip); + server.begin(); +} + +void loop() { + EthernetClient client = server.available(); + if (client) { + bool success = readRequest(client); + if (success) { + // Use https://bblanchon.github.io/ArduinoJson/assistant/ to + // compute the right size for the buffer + StaticJsonBuffer<500> jsonBuffer; + JsonObject& json = prepareResponse(jsonBuffer); + writeResponse(client, json); + } + delay(1); + client.stop(); + } +} diff --git a/lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino b/lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino new file mode 100644 index 000000000..b3bd5fc50 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/examples/JsonUdpBeacon/JsonUdpBeacon.ino @@ -0,0 +1,57 @@ +// Send a JSON object on UDP at regular interval +// +// You can easily test this program with netcat: +// $ nc -ulp 8888 +// +// by Benoit Blanchon, MIT License 2015-2017 + +#include +#include +#include + +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +IPAddress localIp(192, 168, 0, 177); +IPAddress remoteIp(192, 168, 0, 109); +unsigned int remotePort = 8888; +unsigned localPort = 8888; +EthernetUDP udp; + +JsonObject& buildJson(JsonBuffer& jsonBuffer) { + JsonObject& root = jsonBuffer.createObject(); + + JsonArray& analogValues = root.createNestedArray("analog"); + for (int pin = 0; pin < 6; pin++) { + int value = analogRead(pin); + analogValues.add(value); + } + + JsonArray& digitalValues = root.createNestedArray("digital"); + for (int pin = 0; pin < 14; pin++) { + int value = digitalRead(pin); + digitalValues.add(value); + } + + return root; +} + +void sendJson(JsonObject& json) { + udp.beginPacket(remoteIp, remotePort); + json.printTo(udp); + udp.println(); + udp.endPacket(); +} + +void setup() { + Ethernet.begin(mac, localIp); + udp.begin(localPort); +} + +void loop() { + delay(1000); + + // Use https://bblanchon.github.io/ArduinoJson/assistant/ to + // compute the right size for the buffer + StaticJsonBuffer<300> jsonBuffer; + JsonObject& json = buildJson(jsonBuffer); + sendJson(json); +} diff --git a/lib/ArduinoJson-5.11.2/examples/ProgmemExample/ProgmemExample.ino b/lib/ArduinoJson-5.11.2/examples/ProgmemExample/ProgmemExample.ino new file mode 100644 index 000000000..195b014fb --- /dev/null +++ b/lib/ArduinoJson-5.11.2/examples/ProgmemExample/ProgmemExample.ino @@ -0,0 +1,56 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#include + +// About +// ----- +// This example shows the different ways you can use PROGMEM with ArduinoJson. +// Please don't see this as an invitation to use PROGMEM. +// On the contrary, you should always use char[] when possible, it's much more +// efficient in term of code size, speed and memory usage. + +void setup() { +#ifdef PROGMEM + DynamicJsonBuffer jsonBuffer; + + // You can use a Flash String as your JSON input. + // WARNING: the content of the Flash String will be duplicated in the + // JsonBuffer. + JsonObject& root = + jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120," + "\"data\":[48.756080,2.302038]}")); + + // You can use a Flash String to get an element of a JsonObject + // No duplication is done. + long time = root[F("time")]; + + // You can use a Flash String to set an element of a JsonObject + // WARNING: the content of the Flash String will be duplicated in the + // JsonBuffer. + root[F("time")] = time; + + // You can set a Flash String to a JsonObject or JsonArray: + // WARNING: the content of the Flash String will be duplicated in the + // JsonBuffer. + root["sensor"] = F("gps"); + + // You can compare the content of a JsonVariant to a Flash String + if (root["sensor"] == F("gps")) { + // ... + } + +#else + +#warning PROGMEM is not supported on this platform + +#endif +} + +void loop() { + // not used in this example +} diff --git a/lib/ArduinoJson-5.11.2/examples/StringExample/StringExample.ino b/lib/ArduinoJson-5.11.2/examples/StringExample/StringExample.ino new file mode 100644 index 000000000..50b8db6ec --- /dev/null +++ b/lib/ArduinoJson-5.11.2/examples/StringExample/StringExample.ino @@ -0,0 +1,63 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#include + +// About +// ----- +// This example shows the different ways you can use String with ArduinoJson. +// Please don't see this as an invitation to use String. +// On the contrary, you should always use char[] when possible, it's much more +// efficient in term of code size, speed and memory usage. + +void setup() { + DynamicJsonBuffer jsonBuffer; + + // You can use a String as your JSON input. + // WARNING: the content of the String will be duplicated in the JsonBuffer. + String input = + "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; + JsonObject& root = jsonBuffer.parseObject(input); + + // You can use a String to get an element of a JsonObject + // No duplication is done. + long time = root[String("time")]; + + // You can use a String to set an element of a JsonObject + // WARNING: the content of the String will be duplicated in the JsonBuffer. + root[String("time")] = time; + + // You can get a String from a JsonObject or JsonArray: + // No duplication is done, at least not in the JsonBuffer. + String sensor = root["sensor"]; + + // Unfortunately, the following doesn't work (issue #118): + // sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='" + // As a workaround, you need to replace by: + sensor = root["sensor"].as(); + + // You can set a String to a JsonObject or JsonArray: + // WARNING: the content of the String will be duplicated in the JsonBuffer. + root["sensor"] = sensor; + + // You can also concatenate strings + // WARNING: the content of the String will be duplicated in the JsonBuffer. + root[String("sen") + "sor"] = String("gp") + "s"; + + // You can compare the content of a JsonObject with a String + if (root["sensor"] == sensor) { + // ... + } + + // Lastly, you can print the resulting JSON to a String + String output; + root.printTo(output); +} + +void loop() { + // not used in this example +} diff --git a/lib/ArduinoJson-5.11.2/keywords.txt b/lib/ArduinoJson-5.11.2/keywords.txt new file mode 100644 index 000000000..833cddb73 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/keywords.txt @@ -0,0 +1,15 @@ +JsonArray KEYWORD1 +JsonObject KEYWORD1 +JsonVariant KEYWORD1 +StaticJsonBuffer KEYWORD1 +DynamicJsonBuffer KEYWORD1 +add KEYWORD2 +createArray KEYWORD2 +createNestedArray KEYWORD2 +createNestedObject KEYWORD2 +createObject KEYWORD2 +parseArray KEYWORD2 +parseObject KEYWORD2 +prettyPrintTo KEYWORD2 +printTo KEYWORD2 +success KEYWORD2 diff --git a/lib/ArduinoJson-5.11.2/library.properties b/lib/ArduinoJson-5.11.2/library.properties new file mode 100644 index 000000000..9809a3c0b --- /dev/null +++ b/lib/ArduinoJson-5.11.2/library.properties @@ -0,0 +1,9 @@ +name=ArduinoJson +version=5.11.2 +author=Benoit Blanchon +maintainer=Benoit Blanchon +sentence=An efficient and elegant JSON library for Arduino. +paragraph=Like this project? Please star it on GitHub! +category=Data Processing +url=https://bblanchon.github.io/ArduinoJson/ +architectures=* diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson.h b/lib/ArduinoJson-5.11.2/src/ArduinoJson.h new file mode 100644 index 000000000..c1ec7c02f --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson.h @@ -0,0 +1,12 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "ArduinoJson.hpp" + +using namespace ArduinoJson; diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp new file mode 100644 index 000000000..949fa5ca0 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson.hpp @@ -0,0 +1,20 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "ArduinoJson/DynamicJsonBuffer.hpp" +#include "ArduinoJson/JsonArray.hpp" +#include "ArduinoJson/JsonObject.hpp" +#include "ArduinoJson/StaticJsonBuffer.hpp" + +#include "ArduinoJson/Deserialization/JsonParserImpl.hpp" +#include "ArduinoJson/JsonArrayImpl.hpp" +#include "ArduinoJson/JsonBufferImpl.hpp" +#include "ArduinoJson/JsonObjectImpl.hpp" +#include "ArduinoJson/JsonVariantImpl.hpp" +#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp" diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Configuration.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Configuration.hpp new file mode 100644 index 000000000..a1015a6f3 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Configuration.hpp @@ -0,0 +1,153 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +// Small or big machine? +#ifndef ARDUINOJSON_EMBEDDED_MODE +#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) +#define ARDUINOJSON_EMBEDDED_MODE 1 +#else +#define ARDUINOJSON_EMBEDDED_MODE 0 +#endif +#endif + +#if ARDUINOJSON_EMBEDDED_MODE + +// Store floats by default to reduce the memory usage (issue #134) +#ifndef ARDUINOJSON_USE_DOUBLE +#define ARDUINOJSON_USE_DOUBLE 0 +#endif + +// Store longs by default, because they usually match the size of a float. +#ifndef ARDUINOJSON_USE_LONG_LONG +#define ARDUINOJSON_USE_LONG_LONG 0 +#endif +#ifndef ARDUINOJSON_USE_INT64 +#define ARDUINOJSON_USE_INT64 0 +#endif + +// Embedded systems usually don't have std::string +#ifndef ARDUINOJSON_ENABLE_STD_STRING +#define ARDUINOJSON_ENABLE_STD_STRING 0 +#endif + +// Embedded systems usually don't have std::stream +#ifndef ARDUINOJSON_ENABLE_STD_STREAM +#define ARDUINOJSON_ENABLE_STD_STREAM 0 +#endif + +// Limit nesting as the stack is likely to be small +#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT +#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 +#endif + +#else // ARDUINOJSON_EMBEDDED_MODE + +// On a computer we have plenty of memory so we can use doubles +#ifndef ARDUINOJSON_USE_DOUBLE +#define ARDUINOJSON_USE_DOUBLE 1 +#endif + +// Use long long when available +#ifndef ARDUINOJSON_USE_LONG_LONG +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) +#define ARDUINOJSON_USE_LONG_LONG 1 +#else +#define ARDUINOJSON_USE_LONG_LONG 0 +#endif +#endif + +// Use _int64 on old versions of Visual Studio +#ifndef ARDUINOJSON_USE_INT64 +#if defined(_MSC_VER) && _MSC_VER <= 1700 +#define ARDUINOJSON_USE_INT64 1 +#else +#define ARDUINOJSON_USE_INT64 0 +#endif +#endif + +// On a computer, we can use std::string +#ifndef ARDUINOJSON_ENABLE_STD_STRING +#define ARDUINOJSON_ENABLE_STD_STRING 1 +#endif + +// On a computer, we can assume std::stream +#ifndef ARDUINOJSON_ENABLE_STD_STREAM +#define ARDUINOJSON_ENABLE_STD_STREAM 1 +#endif + +// On a computer, the stack is large so we can increase nesting limit +#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT +#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 +#endif + +#endif // ARDUINOJSON_EMBEDDED_MODE + +#ifdef ARDUINO + +// Enable support for Arduino String +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 +#endif + +// Enable support for Arduino Stream +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM +#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 +#endif + +#else // ARDUINO + +// Disable support for Arduino String +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 +#endif + +// Disable support for Arduino Stream +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM +#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 +#endif + +#endif // ARDUINO + +#ifndef ARDUINOJSON_ENABLE_PROGMEM +#ifdef PROGMEM +#define ARDUINOJSON_ENABLE_PROGMEM 1 +#else +#define ARDUINOJSON_ENABLE_PROGMEM 0 +#endif +#endif + +#ifndef ARDUINOJSON_ENABLE_ALIGNMENT +#ifdef ARDUINO_ARCH_AVR +// alignment isn't needed for 8-bit AVR +#define ARDUINOJSON_ENABLE_ALIGNMENT 0 +#else +// but most processors need pointers to be align on word size +#define ARDUINOJSON_ENABLE_ALIGNMENT 1 +#endif +#endif + +// Enable deprecated functions by default +#ifndef ARDUINOJSON_ENABLE_DEPRECATED +#define ARDUINOJSON_ENABLE_DEPRECATED 1 +#endif + +// Control the exponentiation threshold for big numbers +// CAUTION: cannot be more that 1e9 !!!! +#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD +#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 +#endif + +// Control the exponentiation threshold for small numbers +#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD +#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 +#endif + +#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64 +#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/Encoding.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/Encoding.hpp new file mode 100644 index 000000000..dba785aae --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/Encoding.hpp @@ -0,0 +1,40 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +class Encoding { + public: + // Optimized for code size on a 8-bit AVR + static char escapeChar(char c) { + const char *p = escapeTable(false); + while (p[0] && p[1] != c) { + p += 2; + } + return p[0]; + } + + // Optimized for code size on a 8-bit AVR + static char unescapeChar(char c) { + const char *p = escapeTable(true); + for (;;) { + if (p[0] == '\0') return c; + if (p[0] == c) return p[1]; + p += 2; + } + } + + private: + static const char *escapeTable(bool excludeIdenticals) { + return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0]; + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonBufferAllocated.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonBufferAllocated.hpp new file mode 100644 index 000000000..ff74adc55 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonBufferAllocated.hpp @@ -0,0 +1,25 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../JsonBuffer.hpp" + +namespace ArduinoJson { +namespace Internals { + +class JsonBufferAllocated { + public: + void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() { + if (!jsonBuffer) return NULL; + return jsonBuffer->alloc(n); + } + + void operator delete(void *, JsonBuffer *)throw(); +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonFloat.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonFloat.hpp new file mode 100644 index 000000000..a4a8e937f --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonFloat.hpp @@ -0,0 +1,21 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../Configuration.hpp" + +namespace ArduinoJson { +namespace Internals { + +#if ARDUINOJSON_USE_DOUBLE +typedef double JsonFloat; +#else +typedef float JsonFloat; +#endif +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonInteger.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonInteger.hpp new file mode 100644 index 000000000..574a5e109 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonInteger.hpp @@ -0,0 +1,26 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../Configuration.hpp" + +namespace ArduinoJson { +namespace Internals { + +#if ARDUINOJSON_USE_LONG_LONG +typedef long long JsonInteger; +typedef unsigned long long JsonUInt; +#elif ARDUINOJSON_USE_INT64 +typedef __int64 JsonInteger; +typedef unsigned _int64 JsonUInt; +#else +typedef long JsonInteger; +typedef unsigned long JsonUInt; +#endif +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantAs.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantAs.hpp new file mode 100644 index 000000000..3f19fd23a --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantAs.hpp @@ -0,0 +1,45 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +// A metafunction that returns the type of the value returned by +// JsonVariant::as() +template +struct JsonVariantAs { + typedef T type; +}; + +template <> +struct JsonVariantAs { + typedef const char* type; +}; + +template <> +struct JsonVariantAs { + typedef JsonArray& type; +}; + +template <> +struct JsonVariantAs { + typedef const JsonArray& type; +}; + +template <> +struct JsonVariantAs { + typedef JsonObject& type; +}; + +template <> +struct JsonVariantAs { + typedef const JsonObject& type; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantContent.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantContent.hpp new file mode 100644 index 000000000..b27716299 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantContent.hpp @@ -0,0 +1,30 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonFloat.hpp" +#include "JsonInteger.hpp" + +namespace ArduinoJson { + +// Forward declarations +class JsonArray; +class JsonObject; + +namespace Internals { +// A union that defines the actual content of a JsonVariant. +// The enum JsonVariantType determines which member is in use. +union JsonVariantContent { + JsonFloat asFloat; // used for double and float + JsonUInt asInteger; // used for bool, char, short, int and longs + const char* asString; // asString can be null + JsonArray* asArray; // asArray cannot be null + JsonObject* asObject; // asObject cannot be null +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantDefault.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantDefault.hpp new file mode 100644 index 000000000..a59fd46c9 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantDefault.hpp @@ -0,0 +1,26 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +template +struct JsonVariantDefault { + static T get() { + return T(); + } +}; + +template +struct JsonVariantDefault : JsonVariantDefault {}; + +template +struct JsonVariantDefault : JsonVariantDefault {}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantType.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantType.hpp new file mode 100644 index 000000000..ba6a24999 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/JsonVariantType.hpp @@ -0,0 +1,30 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +class JsonArray; +class JsonObject; + +namespace Internals { + +// Enumerated type to know the current type of a JsonVariant. +// The value determines which member of JsonVariantContent is used. +enum JsonVariantType { + JSON_UNDEFINED, // JsonVariant has not been initialized + JSON_UNPARSED, // JsonVariant contains an unparsed string + JSON_STRING, // JsonVariant stores a const char* + JSON_BOOLEAN, // JsonVariant stores a bool + JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt + JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated + JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray + JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject + JSON_FLOAT // JsonVariant stores a JsonFloat +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/List.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/List.hpp new file mode 100644 index 000000000..8a24666ec --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/List.hpp @@ -0,0 +1,97 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../JsonBuffer.hpp" +#include "ListConstIterator.hpp" +#include "ListIterator.hpp" + +namespace ArduinoJson { +namespace Internals { + +// A singly linked list of T. +// The linked list is composed of ListNode. +// It is derived by JsonArray and JsonObject +template +class List { + public: + typedef T value_type; + typedef ListNode node_type; + typedef ListIterator iterator; + typedef ListConstIterator const_iterator; + + // Creates an empty List attached to a JsonBuffer. + // The JsonBuffer allows to allocate new nodes. + // When buffer is NULL, the List is not able to grow and success() returns + // false. This is used to identify bad memory allocations and parsing + // failures. + explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {} + + // Returns true if the object is valid + // Would return false in the following situation: + // - the memory allocation failed (StaticJsonBuffer was too small) + // - the JSON parsing failed + bool success() const { + return _buffer != NULL; + } + + // Returns the numbers of elements in the list. + // For a JsonObject, it would return the number of key-value pairs + size_t size() const { + size_t nodeCount = 0; + for (node_type *node = _firstNode; node; node = node->next) nodeCount++; + return nodeCount; + } + + iterator add() { + node_type *newNode = new (_buffer) node_type(); + + if (_firstNode) { + node_type *lastNode = _firstNode; + while (lastNode->next) lastNode = lastNode->next; + lastNode->next = newNode; + } else { + _firstNode = newNode; + } + + return iterator(newNode); + } + + iterator begin() { + return iterator(_firstNode); + } + iterator end() { + return iterator(NULL); + } + + const_iterator begin() const { + return const_iterator(_firstNode); + } + const_iterator end() const { + return const_iterator(NULL); + } + + void remove(iterator it) { + node_type *nodeToRemove = it._node; + if (!nodeToRemove) return; + if (nodeToRemove == _firstNode) { + _firstNode = nodeToRemove->next; + } else { + for (node_type *node = _firstNode; node; node = node->next) + if (node->next == nodeToRemove) node->next = nodeToRemove->next; + } + } + + protected: + JsonBuffer *_buffer; + + private: + node_type *_firstNode; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListConstIterator.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListConstIterator.hpp new file mode 100644 index 000000000..bce1bfa5e --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListConstIterator.hpp @@ -0,0 +1,53 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "ListNode.hpp" + +namespace ArduinoJson { +namespace Internals { + +// A read-only forward itertor for List +template +class ListConstIterator { + public: + explicit ListConstIterator(const ListNode *node = NULL) : _node(node) {} + + const T &operator*() const { + return _node->content; + } + const T *operator->() { + return &_node->content; + } + + bool operator==(const ListConstIterator &other) const { + return _node == other._node; + } + + bool operator!=(const ListConstIterator &other) const { + return _node != other._node; + } + + ListConstIterator &operator++() { + if (_node) _node = _node->next; + return *this; + } + + ListConstIterator &operator+=(size_t distance) { + while (_node && distance) { + _node = _node->next; + --distance; + } + return *this; + } + + private: + const ListNode *_node; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListIterator.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListIterator.hpp new file mode 100644 index 000000000..a491866f0 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListIterator.hpp @@ -0,0 +1,63 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "ListConstIterator.hpp" +#include "ListNode.hpp" + +namespace ArduinoJson { +namespace Internals { + +template +class List; + +// A read-write forward iterator for List +template +class ListIterator { + friend class List; + + public: + explicit ListIterator(ListNode *node = NULL) : _node(node) {} + + T &operator*() const { + return _node->content; + } + T *operator->() { + return &_node->content; + } + + bool operator==(const ListIterator &other) const { + return _node == other._node; + } + + bool operator!=(const ListIterator &other) const { + return _node != other._node; + } + + ListIterator &operator++() { + if (_node) _node = _node->next; + return *this; + } + + ListIterator &operator+=(size_t distance) { + while (_node && distance) { + _node = _node->next; + --distance; + } + return *this; + } + + operator ListConstIterator() const { + return ListConstIterator(_node); + } + + private: + ListNode *_node; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListNode.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListNode.hpp new file mode 100644 index 000000000..712e15e1f --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ListNode.hpp @@ -0,0 +1,27 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include // for NULL + +#include "JsonBufferAllocated.hpp" + +namespace ArduinoJson { +namespace Internals { + +// A node for a singly-linked list. +// Used by List and its iterators. +template +struct ListNode : public Internals::JsonBufferAllocated { + ListNode() throw() : next(NULL) {} + + ListNode *next; + T content; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/NonCopyable.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/NonCopyable.hpp new file mode 100644 index 000000000..98ebd8fb3 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/NonCopyable.hpp @@ -0,0 +1,26 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +// A type that cannot be copied +class NonCopyable { + protected: + NonCopyable() {} + + private: + // copy constructor is private + NonCopyable(const NonCopyable&); + + // copy operator is private + NonCopyable& operator=(const NonCopyable&); +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ReferenceType.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ReferenceType.hpp new file mode 100644 index 000000000..bbc9046be --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ReferenceType.hpp @@ -0,0 +1,27 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +// A type that is meant to be used by reference only (JsonArray and JsonObject) +class ReferenceType { + public: + bool operator==(const ReferenceType& other) const { + // two JsonArray are equal if they are the same instance + // (we don't compare the content) + return this == &other; + } + + bool operator!=(const ReferenceType& other) const { + return this != &other; + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp new file mode 100644 index 000000000..7eb3ed63b --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Data/ValueSetter.hpp @@ -0,0 +1,51 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../JsonBuffer.hpp" +#include "../JsonVariant.hpp" +#include "../StringTraits/StringTraits.hpp" +#include "../TypeTraits/EnableIf.hpp" + +namespace ArduinoJson { +namespace Internals { + +template +struct ValueSetter { + template + static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) { + destination = source; + return true; + } +}; + +template +struct ValueSetter::should_duplicate>::type> { + template + static bool set(JsonBuffer* buffer, TDestination& destination, + TSourceRef source) { + const char* copy = buffer->strdup(source); + if (!copy) return false; + destination = copy; + return true; + } +}; + +template +struct ValueSetter::should_duplicate>::type> { + template + static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) { + // unsigned char* -> char* + destination = reinterpret_cast(source); + return true; + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/Comments.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/Comments.hpp new file mode 100644 index 000000000..9f281da49 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/Comments.hpp @@ -0,0 +1,64 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { +template +void skipSpacesAndComments(TInput& input) { + for (;;) { + switch (input.current()) { + // spaces + case ' ': + case '\t': + case '\r': + case '\n': + input.move(); + continue; + + // comments + case '/': + switch (input.next()) { + // C-style block comment + case '*': + input.move(); // skip '/' + // no need to skip '*' + for (;;) { + input.move(); + if (input.current() == '\0') return; + if (input.current() == '*' && input.next() == '/') { + input.move(); // skip '*' + input.move(); // skip '/' + break; + } + } + break; + + // C++-style line comment + case '/': + // not need to skip "//" + for (;;) { + input.move(); + if (input.current() == '\0') return; + if (input.current() == '\n') break; + } + break; + + // not a comment, just a '/' + default: + return; + } + break; + + default: + return; + } + } +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParser.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParser.hpp new file mode 100644 index 000000000..3e605ef25 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParser.hpp @@ -0,0 +1,107 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../JsonBuffer.hpp" +#include "../JsonVariant.hpp" +#include "../TypeTraits/IsConst.hpp" +#include "StringWriter.hpp" + +namespace ArduinoJson { +namespace Internals { + +// Parse JSON string to create JsonArrays and JsonObjects +// This internal class is not indended to be used directly. +// Instead, use JsonBuffer.parseArray() or .parseObject() +template +class JsonParser { + public: + JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer, + uint8_t nestingLimit) + : _buffer(buffer), + _reader(reader), + _writer(writer), + _nestingLimit(nestingLimit) {} + + JsonArray &parseArray(); + JsonObject &parseObject(); + + JsonVariant parseVariant() { + JsonVariant result; + parseAnythingTo(&result); + return result; + } + + private: + JsonParser &operator=(const JsonParser &); // non-copiable + + static bool eat(TReader &, char charToSkip); + FORCE_INLINE bool eat(char charToSkip) { + return eat(_reader, charToSkip); + } + + const char *parseString(); + bool parseAnythingTo(JsonVariant *destination); + FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination); + + inline bool parseArrayTo(JsonVariant *destination); + inline bool parseObjectTo(JsonVariant *destination); + inline bool parseStringTo(JsonVariant *destination); + + static inline bool isInRange(char c, char min, char max) { + return min <= c && c <= max; + } + + static inline bool isLetterOrNumber(char c) { + return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') || + isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.'; + } + + static inline bool isQuote(char c) { + return c == '\'' || c == '\"'; + } + + JsonBuffer *_buffer; + TReader _reader; + TWriter _writer; + uint8_t _nestingLimit; +}; + +template +struct JsonParserBuilder { + typedef typename Internals::StringTraits::Reader InputReader; + typedef JsonParser TParser; + + static TParser makeParser(TJsonBuffer *buffer, TString &json, + uint8_t nestingLimit) { + return TParser(buffer, InputReader(json), *buffer, nestingLimit); + } +}; + +template +struct JsonParserBuilder< + TJsonBuffer, TChar *, + typename TypeTraits::EnableIf::value>::type> { + typedef typename Internals::StringTraits::Reader TReader; + typedef StringWriter TWriter; + typedef JsonParser TParser; + + static TParser makeParser(TJsonBuffer *buffer, TChar *json, + uint8_t nestingLimit) { + return TParser(buffer, TReader(json), TWriter(json), nestingLimit); + } +}; + +template +inline typename JsonParserBuilder::TParser makeParser( + TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) { + return JsonParserBuilder::makeParser(buffer, json, + nestingLimit); +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParserImpl.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParserImpl.hpp new file mode 100644 index 000000000..1c41bdaac --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/JsonParserImpl.hpp @@ -0,0 +1,194 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Comments.hpp" +#include "JsonParser.hpp" + +template +inline bool ArduinoJson::Internals::JsonParser::eat( + TReader &reader, char charToSkip) { + skipSpacesAndComments(reader); + if (reader.current() != charToSkip) return false; + reader.move(); + return true; +} + +template +inline bool ArduinoJson::Internals::JsonParser< + TReader, TWriter>::parseAnythingTo(JsonVariant *destination) { + if (_nestingLimit == 0) return false; + _nestingLimit--; + bool success = parseAnythingToUnsafe(destination); + _nestingLimit++; + return success; +} + +template +inline bool ArduinoJson::Internals::JsonParser< + TReader, TWriter>::parseAnythingToUnsafe(JsonVariant *destination) { + skipSpacesAndComments(_reader); + + switch (_reader.current()) { + case '[': + return parseArrayTo(destination); + + case '{': + return parseObjectTo(destination); + + default: + return parseStringTo(destination); + } +} + +template +inline ArduinoJson::JsonArray & +ArduinoJson::Internals::JsonParser::parseArray() { + // Create an empty array + JsonArray &array = _buffer->createArray(); + + // Check opening braket + if (!eat('[')) goto ERROR_MISSING_BRACKET; + if (eat(']')) goto SUCCESS_EMPTY_ARRAY; + + // Read each value + for (;;) { + // 1 - Parse value + JsonVariant value; + if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; + if (!array.add(value)) goto ERROR_NO_MEMORY; + + // 2 - More values? + if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY; + if (!eat(',')) goto ERROR_MISSING_COMMA; + } + +SUCCESS_EMPTY_ARRAY: +SUCCES_NON_EMPTY_ARRAY: + return array; + +ERROR_INVALID_VALUE: +ERROR_MISSING_BRACKET: +ERROR_MISSING_COMMA: +ERROR_NO_MEMORY: + return JsonArray::invalid(); +} + +template +inline bool ArduinoJson::Internals::JsonParser::parseArrayTo( + JsonVariant *destination) { + JsonArray &array = parseArray(); + if (!array.success()) return false; + + *destination = array; + return true; +} + +template +inline ArduinoJson::JsonObject & +ArduinoJson::Internals::JsonParser::parseObject() { + // Create an empty object + JsonObject &object = _buffer->createObject(); + + // Check opening brace + if (!eat('{')) goto ERROR_MISSING_BRACE; + if (eat('}')) goto SUCCESS_EMPTY_OBJECT; + + // Read each key value pair + for (;;) { + // 1 - Parse key + const char *key = parseString(); + if (!key) goto ERROR_INVALID_KEY; + if (!eat(':')) goto ERROR_MISSING_COLON; + + // 2 - Parse value + JsonVariant value; + if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; + if (!object.set(key, value)) goto ERROR_NO_MEMORY; + + // 3 - More keys/values? + if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT; + if (!eat(',')) goto ERROR_MISSING_COMMA; + } + +SUCCESS_EMPTY_OBJECT: +SUCCESS_NON_EMPTY_OBJECT: + return object; + +ERROR_INVALID_KEY: +ERROR_INVALID_VALUE: +ERROR_MISSING_BRACE: +ERROR_MISSING_COLON: +ERROR_MISSING_COMMA: +ERROR_NO_MEMORY: + return JsonObject::invalid(); +} + +template +inline bool ArduinoJson::Internals::JsonParser::parseObjectTo( + JsonVariant *destination) { + JsonObject &object = parseObject(); + if (!object.success()) return false; + + *destination = object; + return true; +} + +template +inline const char * +ArduinoJson::Internals::JsonParser::parseString() { + typename TypeTraits::RemoveReference::type::String str = + _writer.startString(); + + skipSpacesAndComments(_reader); + char c = _reader.current(); + + if (isQuote(c)) { // quotes + _reader.move(); + char stopChar = c; + for (;;) { + c = _reader.current(); + if (c == '\0') break; + _reader.move(); + + if (c == stopChar) break; + + if (c == '\\') { + // replace char + c = Encoding::unescapeChar(_reader.current()); + if (c == '\0') break; + _reader.move(); + } + + str.append(c); + } + } else { // no quotes + for (;;) { + if (!isLetterOrNumber(c)) break; + _reader.move(); + str.append(c); + c = _reader.current(); + } + } + + return str.c_str(); +} + +template +inline bool ArduinoJson::Internals::JsonParser::parseStringTo( + JsonVariant *destination) { + bool hasQuotes = isQuote(_reader.current()); + const char *value = parseString(); + if (value == NULL) return false; + if (hasQuotes) { + *destination = value; + } else { + *destination = RawJson(value); + } + return true; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/StringWriter.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/StringWriter.hpp new file mode 100644 index 000000000..42ee640d8 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Deserialization/StringWriter.hpp @@ -0,0 +1,44 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +template +class StringWriter { + public: + class String { + public: + String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {} + + void append(char c) { + *(*_writePtr)++ = TChar(c); + } + + const char* c_str() const { + *(*_writePtr)++ = 0; + return reinterpret_cast(_startPtr); + } + + private: + TChar** _writePtr; + TChar* _startPtr; + }; + + StringWriter(TChar* buffer) : _ptr(buffer) {} + + String startString() { + return String(&_ptr); + } + + private: + TChar* _ptr; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/DynamicJsonBuffer.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/DynamicJsonBuffer.hpp new file mode 100644 index 000000000..65e744bf2 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/DynamicJsonBuffer.hpp @@ -0,0 +1,170 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonBufferBase.hpp" + +#include + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnon-virtual-dtor" +#elif defined(__GNUC__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic push +#endif +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +namespace ArduinoJson { +class DefaultAllocator { + public: + void* allocate(size_t size) { + return malloc(size); + } + void deallocate(void* pointer) { + free(pointer); + } +}; + +template +class DynamicJsonBufferBase + : public JsonBufferBase > { + struct Block; + struct EmptyBlock { + Block* next; + size_t capacity; + size_t size; + }; + struct Block : EmptyBlock { + uint8_t data[1]; + }; + + public: + enum { EmptyBlockSize = sizeof(EmptyBlock) }; + + DynamicJsonBufferBase(size_t initialSize = 256) + : _head(NULL), _nextBlockCapacity(initialSize) {} + + ~DynamicJsonBufferBase() { + clear(); + } + + // Gets the number of bytes occupied in the buffer + size_t size() const { + size_t total = 0; + for (const Block* b = _head; b; b = b->next) total += b->size; + return total; + } + + // Allocates the specified amount of bytes in the buffer + virtual void* alloc(size_t bytes) { + alignNextAlloc(); + return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); + } + + // Resets the buffer. + // USE WITH CAUTION: this invalidates all previously allocated data + void clear() { + Block* currentBlock = _head; + while (currentBlock != NULL) { + _nextBlockCapacity = currentBlock->capacity; + Block* nextBlock = currentBlock->next; + _allocator.deallocate(currentBlock); + currentBlock = nextBlock; + } + _head = 0; + } + + class String { + public: + String(DynamicJsonBufferBase* parent) + : _parent(parent), _start(NULL), _length(0) {} + + void append(char c) { + if (_parent->canAllocInHead(1)) { + char* end = static_cast(_parent->allocInHead(1)); + *end = c; + if (_length == 0) _start = end; + } else { + char* newStart = + static_cast(_parent->allocInNewBlock(_length + 1)); + if (_start && newStart) memcpy(newStart, _start, _length); + if (newStart) newStart[_length] = c; + _start = newStart; + } + _length++; + } + + const char* c_str() { + append(0); + return _start; + } + + private: + DynamicJsonBufferBase* _parent; + char* _start; + size_t _length; + }; + + String startString() { + return String(this); + } + + private: + void alignNextAlloc() { + if (_head) _head->size = this->round_size_up(_head->size); + } + + bool canAllocInHead(size_t bytes) const { + return _head != NULL && _head->size + bytes <= _head->capacity; + } + + void* allocInHead(size_t bytes) { + void* p = _head->data + _head->size; + _head->size += bytes; + return p; + } + + void* allocInNewBlock(size_t bytes) { + size_t capacity = _nextBlockCapacity; + if (bytes > capacity) capacity = bytes; + if (!addNewBlock(capacity)) return NULL; + _nextBlockCapacity *= 2; + return allocInHead(bytes); + } + + bool addNewBlock(size_t capacity) { + size_t bytes = EmptyBlockSize + capacity; + Block* block = static_cast(_allocator.allocate(bytes)); + if (block == NULL) return false; + block->capacity = capacity; + block->size = 0; + block->next = _head; + _head = block; + return true; + } + + TAllocator _allocator; + Block* _head; + size_t _nextBlockCapacity; +}; + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic pop +#endif +#endif + +// Implements a JsonBuffer with dynamic memory allocation. +// You are strongly encouraged to consider using StaticJsonBuffer which is much +// more suitable for embedded systems. +typedef DynamicJsonBufferBase DynamicJsonBuffer; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArray.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArray.hpp new file mode 100644 index 000000000..27404fb7b --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArray.hpp @@ -0,0 +1,233 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Data/JsonBufferAllocated.hpp" +#include "Data/List.hpp" +#include "Data/ReferenceType.hpp" +#include "Data/ValueSetter.hpp" +#include "JsonVariant.hpp" +#include "Serialization/JsonPrintable.hpp" +#include "StringTraits/StringTraits.hpp" +#include "TypeTraits/EnableIf.hpp" +#include "TypeTraits/IsArray.hpp" +#include "TypeTraits/IsFloatingPoint.hpp" +#include "TypeTraits/IsSame.hpp" + +// Returns the size (in bytes) of an array with n elements. +// Can be very handy to determine the size of a StaticJsonBuffer. +#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \ + (sizeof(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type)) + +namespace ArduinoJson { + +// Forward declarations +class JsonObject; +class JsonBuffer; +class JsonArraySubscript; + +// An array of JsonVariant. +// +// The constructor is private, instances must be created via +// JsonBuffer::createArray() or JsonBuffer::parseArray(). +// A JsonArray can be serialized to a JSON string via JsonArray::printTo(). +// It can also be deserialized from a JSON string via JsonBuffer::parseArray(). +class JsonArray : public Internals::JsonPrintable, + public Internals::ReferenceType, + public Internals::NonCopyable, + public Internals::List, + public Internals::JsonBufferAllocated { + public: + // Create an empty JsonArray attached to the specified JsonBuffer. + // You should not call this constructor directly. + // Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray(). + explicit JsonArray(JsonBuffer *buffer) throw() + : Internals::List(buffer) {} + + // Gets the value at the specified index + const JsonArraySubscript operator[](size_t index) const; + + // Gets or sets the value at specified index + JsonArraySubscript operator[](size_t index); + + // Adds the specified value at the end of the array. + // + // bool add(TValue); + // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + typename TypeTraits::EnableIf::value, bool>::type add( + const T &value) { + return add_impl(value); + } + // + // bool add(TValue); + // TValue = const char*, const char[N], const FlashStringHelper* + template + bool add(const T *value) { + return add_impl(value); + } + // + // bool add(TValue value, uint8_t decimals); + // TValue = float, double + template + DEPRECATED("Second argument is not supported anymore") + bool add(T value, uint8_t) { + return add_impl(JsonVariant(value)); + } + + // Sets the value at specified index. + // + // bool add(size_t index, TValue); + // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + typename TypeTraits::EnableIf::value, bool>::type set( + size_t index, const T &value) { + return set_impl(index, value); + } + // + // bool add(size_t index, TValue); + // TValue = const char*, const char[N], const FlashStringHelper* + template + bool set(size_t index, const T *value) { + return set_impl(index, value); + } + // + // bool set(size_t index, TValue value, uint8_t decimals); + // TValue = float, double + template + typename TypeTraits::EnableIf::value, + bool>::type + set(size_t index, T value, uint8_t decimals) { + return set_impl(index, JsonVariant(value, decimals)); + } + + // Gets the value at the specified index. + template + typename Internals::JsonVariantAs::type get(size_t index) const { + const_iterator it = begin() += index; + return it != end() ? it->as() : Internals::JsonVariantDefault::get(); + } + + // Check the type of the value at specified index. + template + bool is(size_t index) const { + const_iterator it = begin() += index; + return it != end() ? it->is() : false; + } + + // Creates a JsonArray and adds a reference at the end of the array. + // It's a shortcut for JsonBuffer::createArray() and JsonArray::add() + JsonArray &createNestedArray(); + + // Creates a JsonObject and adds a reference at the end of the array. + // It's a shortcut for JsonBuffer::createObject() and JsonArray::add() + JsonObject &createNestedObject(); + + // Removes element at specified index. + void remove(size_t index) { + remove(begin() += index); + } + using Internals::List::remove; + + // Returns a reference an invalid JsonArray. + // This object is meant to replace a NULL pointer. + // This is used when memory allocation or JSON parsing fail. + static JsonArray &invalid() { + static JsonArray instance(NULL); + return instance; + } + + // Imports a 1D array + template + bool copyFrom(T (&array)[N]) { + return copyFrom(array, N); + } + + // Imports a 1D array + template + bool copyFrom(T *array, size_t len) { + bool ok = true; + for (size_t i = 0; i < len; i++) { + ok &= add(array[i]); + } + return ok; + } + + // Imports a 2D array + template + bool copyFrom(T (&array)[N1][N2]) { + bool ok = true; + for (size_t i = 0; i < N1; i++) { + JsonArray &nestedArray = createNestedArray(); + for (size_t j = 0; j < N2; j++) { + ok &= nestedArray.add(array[i][j]); + } + } + return ok; + } + + // Exports a 1D array + template + size_t copyTo(T (&array)[N]) const { + return copyTo(array, N); + } + + // Exports a 1D array + template + size_t copyTo(T *array, size_t len) const { + size_t i = 0; + for (const_iterator it = begin(); it != end() && i < len; ++it) + array[i++] = *it; + return i; + } + + // Exports a 2D array + template + void copyTo(T (&array)[N1][N2]) const { + size_t i = 0; + for (const_iterator it = begin(); it != end() && i < N1; ++it) { + it->as().copyTo(array[i++]); + } + } + +#if ARDUINOJSON_ENABLE_DEPRECATED + DEPRECATED("use remove() instead") + FORCE_INLINE void removeAt(size_t index) { + return remove(index); + } +#endif + + private: + template + bool set_impl(size_t index, TValueRef value) { + iterator it = begin() += index; + if (it == end()) return false; + return Internals::ValueSetter::set(_buffer, *it, value); + } + + template + bool add_impl(TValueRef value) { + iterator it = Internals::List::add(); + if (it == end()) return false; + return Internals::ValueSetter::set(_buffer, *it, value); + } +}; + +namespace Internals { +template <> +struct JsonVariantDefault { + static JsonArray &get() { + return JsonArray::invalid(); + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArrayImpl.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArrayImpl.hpp new file mode 100644 index 000000000..6ebd39baa --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArrayImpl.hpp @@ -0,0 +1,29 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonArray.hpp" +#include "JsonArraySubscript.hpp" +#include "JsonObject.hpp" + +namespace ArduinoJson { + +inline JsonArray &JsonArray::createNestedArray() { + if (!_buffer) return JsonArray::invalid(); + JsonArray &array = _buffer->createArray(); + add(array); + return array; +} + +inline JsonObject &JsonArray::createNestedObject() { + if (!_buffer) return JsonObject::invalid(); + JsonObject &object = _buffer->createObject(); + add(object); + return object; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArraySubscript.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArraySubscript.hpp new file mode 100644 index 000000000..5bd6208a5 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonArraySubscript.hpp @@ -0,0 +1,125 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Configuration.hpp" +#include "JsonVariantBase.hpp" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4522) +#endif + +namespace ArduinoJson { +class JsonArraySubscript : public JsonVariantBase { + public: + FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) + : _array(array), _index(index) {} + + FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) { + _array.set(_index, src); + return *this; + } + + // Replaces the value + // + // operator=(TValue) + // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + FORCE_INLINE JsonArraySubscript& operator=(const T& src) { + _array.set(_index, src); + return *this; + } + // + // operator=(TValue) + // TValue = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE JsonArraySubscript& operator=(const T* src) { + _array.set(_index, src); + return *this; + } + + FORCE_INLINE bool success() const { + return _index < _array.size(); + } + + template + FORCE_INLINE typename Internals::JsonVariantAs::type as() const { + return _array.get(_index); + } + + template + FORCE_INLINE bool is() const { + return _array.is(_index); + } + + // Replaces the value + // + // bool set(TValue) + // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + FORCE_INLINE bool set(const TValue& value) { + return _array.set(_index, value); + } + // + // bool set(TValue) + // TValue = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE bool set(const TValue* value) { + return _array.set(_index, value); + } + // + // bool set(TValue, uint8_t decimals); + // TValue = float, double + template + DEPRECATED("Second argument is not supported anymore") + FORCE_INLINE bool set(const TValue& value, uint8_t) { + return _array.set(_index, value); + } + + private: + JsonArray& _array; + const size_t _index; +}; + +#if ARDUINOJSON_ENABLE_STD_STREAM +inline std::ostream& operator<<(std::ostream& os, + const JsonArraySubscript& source) { + return source.printTo(os); +} +#endif + +inline JsonArraySubscript JsonArray::operator[](size_t index) { + return JsonArraySubscript(*this, index); +} + +inline const JsonArraySubscript JsonArray::operator[](size_t index) const { + return JsonArraySubscript(*const_cast(this), index); +} + +template +inline JsonArraySubscript JsonVariantSubscripts::operator[]( + size_t index) { + return impl()->template as()[index]; +} + +template +inline const JsonArraySubscript JsonVariantSubscripts::operator[]( + size_t index) const { + return impl()->template as()[index]; +} + +} // namespace ArduinoJson + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBuffer.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBuffer.hpp new file mode 100644 index 000000000..06bda0ef4 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBuffer.hpp @@ -0,0 +1,80 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include // for size_t +#include // for uint8_t +#include + +#include "Data/NonCopyable.hpp" +#include "JsonVariant.hpp" +#include "TypeTraits/EnableIf.hpp" +#include "TypeTraits/IsArray.hpp" + +namespace ArduinoJson { +class JsonArray; +class JsonObject; + +// Entry point for using the library. +// +// Handle the memory management (done in derived classes) and calls the parser. +// This abstract class is implemented by StaticJsonBuffer which implements a +// fixed memory allocation. +class JsonBuffer : Internals::NonCopyable { + public: + // Allocates an empty JsonArray. + // + // Returns a reference to the new JsonArray or JsonArray::invalid() if the + // allocation fails. + JsonArray &createArray(); + + // Allocates an empty JsonObject. + // + // Returns a reference to the new JsonObject or JsonObject::invalid() if the + // allocation fails. + JsonObject &createObject(); + + // Duplicates a string + // + // char* strdup(TValue); + // TValue = const std::string&, const String&, + template + typename TypeTraits::EnableIf::value, + char *>::type + strdup(const TString &src) { + return Internals::StringTraits::duplicate(src, this); + } + // + // char* strdup(TValue); + // TValue = const char*, const char[N], const FlashStringHelper* + template + char *strdup(const TString *src) { + return Internals::StringTraits::duplicate(src, this); + } + + // Allocates n bytes in the JsonBuffer. + // Return a pointer to the allocated memory or NULL if allocation fails. + virtual void *alloc(size_t size) = 0; + + protected: + // CAUTION: NO VIRTUAL DESTRUCTOR! + // If we add a virtual constructor the Arduino compiler will add malloc() + // and free() to the binary, adding 706 useless bytes. + ~JsonBuffer() {} + + // Preserve aligment if necessary + static FORCE_INLINE size_t round_size_up(size_t bytes) { +#if ARDUINOJSON_ENABLE_ALIGNMENT + const size_t x = sizeof(void *) - 1; + return (bytes + x) & ~x; +#else + return bytes; +#endif + } +}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferBase.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferBase.hpp new file mode 100644 index 000000000..480cd8307 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferBase.hpp @@ -0,0 +1,128 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Deserialization/JsonParser.hpp" + +namespace ArduinoJson { +template +class JsonBufferBase : public JsonBuffer { + public: + // Allocates and populate a JsonArray from a JSON string. + // + // The First argument is a pointer to the JSON string, the memory must be + // writable + // because the parser will insert null-terminators and replace escaped chars. + // + // The second argument set the nesting limit + // + // Returns a reference to the new JsonObject or JsonObject::invalid() if the + // allocation fails. + // With this overload, the JsonBuffer will make a copy of the string + // + // JsonArray& parseArray(TString); + // TString = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + JsonArray &>::type + parseArray(const TString &json, + uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseArray(); + } + // + // JsonArray& parseArray(TString); + // TString = const char*, const char[N], const FlashStringHelper* + template + JsonArray &parseArray( + TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseArray(); + } + // + // JsonArray& parseArray(TString); + // TString = std::istream&, Stream& + template + JsonArray &parseArray( + TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseArray(); + } + + // Allocates and populate a JsonObject from a JSON string. + // + // The First argument is a pointer to the JSON string, the memory must be + // writable + // because the parser will insert null-terminators and replace escaped chars. + // + // The second argument set the nesting limit + // + // Returns a reference to the new JsonObject or JsonObject::invalid() if the + // allocation fails. + // + // JsonObject& parseObject(TString); + // TString = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + JsonObject &>::type + parseObject(const TString &json, + uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseObject(); + } + // + // JsonObject& parseObject(TString); + // TString = const char*, const char[N], const FlashStringHelper* + template + JsonObject &parseObject( + TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseObject(); + } + // + // JsonObject& parseObject(TString); + // TString = std::istream&, Stream& + template + JsonObject &parseObject( + TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseObject(); + } + + // Generalized version of parseArray() and parseObject(), also works for + // integral types. + // + // JsonVariant parse(TString); + // TString = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + JsonVariant>::type + parse(const TString &json, + uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseVariant(); + } + // + // JsonVariant parse(TString); + // TString = const char*, const char[N], const FlashStringHelper* + template + JsonVariant parse(TString *json, + uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseVariant(); + } + // + // JsonVariant parse(TString); + // TString = std::istream&, Stream& + template + JsonVariant parse(TString &json, + uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { + return Internals::makeParser(that(), json, nestingLimit).parseVariant(); + } + + protected: + ~JsonBufferBase() {} + + private: + TDerived *that() { + return static_cast(this); + } +}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferImpl.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferImpl.hpp new file mode 100644 index 000000000..98d5de595 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonBufferImpl.hpp @@ -0,0 +1,20 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Deserialization/JsonParser.hpp" + +inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() { + JsonArray *ptr = new (this) JsonArray(this); + return ptr ? *ptr : JsonArray::invalid(); +} + +inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() { + JsonObject *ptr = new (this) JsonObject(this); + return ptr ? *ptr : JsonObject::invalid(); +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObject.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObject.hpp new file mode 100644 index 000000000..a3e30ab27 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObject.hpp @@ -0,0 +1,351 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Data/JsonBufferAllocated.hpp" +#include "Data/List.hpp" +#include "Data/ReferenceType.hpp" +#include "Data/ValueSetter.hpp" +#include "JsonPair.hpp" +#include "Serialization/JsonPrintable.hpp" +#include "StringTraits/StringTraits.hpp" +#include "TypeTraits/EnableIf.hpp" +#include "TypeTraits/IsArray.hpp" +#include "TypeTraits/IsFloatingPoint.hpp" +#include "TypeTraits/IsSame.hpp" + +// Returns the size (in bytes) of an object with n elements. +// Can be very handy to determine the size of a StaticJsonBuffer. +#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \ + (sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type)) + +namespace ArduinoJson { + +// Forward declarations +class JsonArray; +class JsonBuffer; + +// A dictionary of JsonVariant indexed by string (char*) +// +// The constructor is private, instances must be created via +// JsonBuffer::createObject() or JsonBuffer::parseObject(). +// A JsonObject can be serialized to a JSON string via JsonObject::printTo(). +// It can also be deserialized from a JSON string via JsonBuffer::parseObject(). +class JsonObject : public Internals::JsonPrintable, + public Internals::ReferenceType, + public Internals::NonCopyable, + public Internals::List, + public Internals::JsonBufferAllocated { + public: + // Create an empty JsonArray attached to the specified JsonBuffer. + // You should not use this constructor directly. + // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject(). + explicit JsonObject(JsonBuffer* buffer) throw() + : Internals::List(buffer) {} + + // Gets or sets the value associated with the specified key. + // + // JsonObjectSubscript operator[](TKey) + // TKey = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + JsonObjectSubscript >::type + operator[](const TString& key) { + return JsonObjectSubscript(*this, key); + } + // + // JsonObjectSubscript operator[](TKey) + // TKey = const char*, const char[N], const FlashStringHelper* + template + JsonObjectSubscript operator[](const TString* key) { + return JsonObjectSubscript(*this, key); + } + + // Gets the value associated with the specified key. + // + // const JsonObjectSubscript operator[](TKey) const; + // TKey = const std::string&, const String& + template + typename TypeTraits::EnableIf< + !TypeTraits::IsArray::value, + const JsonObjectSubscript >::type + operator[](const TString& key) const { + return JsonObjectSubscript(*const_cast(this), + key); + } + // + // const JsonObjectSubscript operator[](TKey) const; + // TKey = const char*, const char[N], const FlashStringHelper* + template + const JsonObjectSubscript operator[]( + const TString* key) const { + return JsonObjectSubscript(*const_cast(this), + key); + } + + // Sets the specified key with the specified value. + // + // bool set(TKey, TValue); + // TKey = const std::string&, const String& + // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + typename TypeTraits::EnableIf::value && + !TypeTraits::IsArray::value, + bool>::type + set(const TString& key, const TValue& value) { + return set_impl(key, value); + } + // + // bool set(TKey, TValue); + // TKey = const std::string&, const String& + // TValue = const char*, const char[N], const FlashStringHelper* + template + typename TypeTraits::EnableIf::value, + bool>::type + set(const TString& key, const TValue* value) { + return set_impl(key, value); + } + // + // bool set(TKey, TValue); + // TKey = const char*, const char[N], const FlashStringHelper* + // TValue = bool, long, int, short, float, double, RawJson, JsonVariant, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + typename TypeTraits::EnableIf::value, bool>::type + set(const TString* key, const TValue& value) { + return set_impl(key, value); + } + // + // bool set(TKey, TValue); + // TKey = const char*, const char[N], const FlashStringHelper* + // TValue = const char*, const char[N], const FlashStringHelper* + template + bool set(const TString* key, const TValue* value) { + return set_impl(key, value); + } + // + // bool set(TKey, TValue, uint8_t decimals); + // TKey = const std::string&, const String& + // TValue = float, double + template + DEPRECATED("Second argument is not supported anymore") + typename TypeTraits::EnableIf::value && + !TypeTraits::IsArray::value, + bool>::type + set(const TString& key, TValue value, uint8_t) { + return set_impl(key, + JsonVariant(value)); + } + // + // bool set(TKey, TValue, uint8_t decimals); + // TKey = const char*, const char[N], const FlashStringHelper* + // TValue = float, double + template + DEPRECATED("Second argument is not supported anymore") + typename TypeTraits::EnableIf::value, + bool>::type + set(const TString* key, TValue value, uint8_t) { + return set_impl(key, + JsonVariant(value)); + } + + // Gets the value associated with the specified key. + // + // TValue get(TKey); + // TKey = const std::string&, const String& + // TValue = bool, char, long, int, short, float, double, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + typename TypeTraits::EnableIf< + !TypeTraits::IsArray::value, + typename Internals::JsonVariantAs::type>::type + get(const TString& key) const { + return get_impl(key); + } + // + // TValue get(TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + // TValue = bool, char, long, int, short, float, double, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + typename Internals::JsonVariantAs::type get( + const TString* key) const { + return get_impl(key); + } + + // Checks the type of the value associated with the specified key. + // + // + // bool is(TKey) const; + // TKey = const std::string&, const String& + // TValue = bool, char, long, int, short, float, double, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + typename TypeTraits::EnableIf::value, + bool>::type + is(const TString& key) const { + return is_impl(key); + } + // + // bool is(TKey) const; + // TKey = const char*, const char[N], const FlashStringHelper* + // TValue = bool, char, long, int, short, float, double, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + bool is(const TString* key) const { + return is_impl(key); + } + + // Creates and adds a JsonArray. + // + // JsonArray& createNestedArray(TKey); + // TKey = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + JsonArray&>::type + createNestedArray(const TString& key) { + return createNestedArray_impl(key); + } + // JsonArray& createNestedArray(TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + JsonArray& createNestedArray(const TString* key) { + return createNestedArray_impl(key); + } + + // Creates and adds a JsonObject. + // + // JsonObject& createNestedObject(TKey); + // TKey = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + JsonObject&>::type + createNestedObject(const TString& key) { + return createNestedObject_impl(key); + } + // + // JsonObject& createNestedObject(TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + JsonObject& createNestedObject(const TString* key) { + return createNestedObject_impl(key); + } + + // Tells weither the specified key is present and associated with a value. + // + // bool containsKey(TKey); + // TKey = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + bool>::type + containsKey(const TString& key) const { + return findKey(key) != end(); + } + // + // bool containsKey(TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + bool containsKey(const TString* key) const { + return findKey(key) != end(); + } + + // Removes the specified key and the associated value. + // + // void remove(TKey); + // TKey = const std::string&, const String& + template + typename TypeTraits::EnableIf::value, + void>::type + remove(const TString& key) { + remove(findKey(key)); + } + // + // void remove(TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + void remove(const TString* key) { + remove(findKey(key)); + } + // + // void remove(iterator) + using Internals::List::remove; + + // Returns a reference an invalid JsonObject. + // This object is meant to replace a NULL pointer. + // This is used when memory allocation or JSON parsing fail. + static JsonObject& invalid() { + static JsonObject instance(NULL); + return instance; + } + + private: + // Returns the list node that matches the specified key. + template + iterator findKey(TStringRef key) { + iterator it; + for (it = begin(); it != end(); ++it) { + if (Internals::StringTraits::equals(key, it->key)) break; + } + return it; + } + template + const_iterator findKey(TStringRef key) const { + return const_cast(this)->findKey(key); + } + + template + typename Internals::JsonVariantAs::type get_impl( + TStringRef key) const { + const_iterator it = findKey(key); + return it != end() ? it->value.as() + : Internals::JsonVariantDefault::get(); + } + + template + bool set_impl(TStringRef key, TValueRef value) { + iterator it = findKey(key); + if (it == end()) { + it = Internals::List::add(); + if (it == end()) return false; + + bool key_ok = + Internals::ValueSetter::set(_buffer, it->key, key); + if (!key_ok) return false; + } + return Internals::ValueSetter::set(_buffer, it->value, value); + } + + template + bool is_impl(TStringRef key) const { + const_iterator it = findKey(key); + return it != end() ? it->value.is() : false; + } + + template + JsonArray& createNestedArray_impl(TStringRef key); + + template + JsonObject& createNestedObject_impl(TStringRef key); +}; + +namespace Internals { +template <> +struct JsonVariantDefault { + static JsonObject& get() { + return JsonObject::invalid(); + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectImpl.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectImpl.hpp new file mode 100644 index 000000000..9741bfadd --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectImpl.hpp @@ -0,0 +1,31 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonArray.hpp" +#include "JsonObject.hpp" +#include "JsonObjectSubscript.hpp" + +namespace ArduinoJson { + +template +inline JsonArray &JsonObject::createNestedArray_impl(TStringRef key) { + if (!_buffer) return JsonArray::invalid(); + JsonArray &array = _buffer->createArray(); + set(key, array); + return array; +} + +template +inline JsonObject &JsonObject::createNestedObject_impl(TStringRef key) { + if (!_buffer) return JsonObject::invalid(); + JsonObject &object = _buffer->createObject(); + set(key, object); + return object; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectSubscript.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectSubscript.hpp new file mode 100644 index 000000000..99dfe7cd0 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonObjectSubscript.hpp @@ -0,0 +1,117 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Configuration.hpp" +#include "JsonVariantBase.hpp" +#include "TypeTraits/EnableIf.hpp" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4522) +#endif + +namespace ArduinoJson { + +template +class JsonObjectSubscript + : public JsonVariantBase > { + typedef JsonObjectSubscript this_type; + + public: + FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key) + : _object(object), _key(key) {} + + FORCE_INLINE this_type& operator=(const this_type& src) { + _object.set(_key, src); + return *this; + } + + // Set the specified value + // + // operator=(TValue); + // TValue = bool, char, long, int, short, float, double, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + FORCE_INLINE + typename TypeTraits::EnableIf::value, + this_type&>::type + operator=(const TValue& src) { + _object.set(_key, src); + return *this; + } + // + // operator=(TValue); + // TValue = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE this_type& operator=(const TValue* src) { + _object.set(_key, src); + return *this; + } + + FORCE_INLINE bool success() const { + return _object.containsKey(_key); + } + + template + FORCE_INLINE typename Internals::JsonVariantAs::type as() const { + return _object.get(_key); + } + + template + FORCE_INLINE bool is() const { + return _object.is(_key); + } + + // Sets the specified value. + // + // bool set(TValue); + // TValue = bool, char, long, int, short, float, double, RawJson, JsonVariant, + // const std::string&, const String&, + // const JsonArray&, const JsonObject& + template + FORCE_INLINE + typename TypeTraits::EnableIf::value, + bool>::type + set(const TValue& value) { + return _object.set(_key, value); + } + // + // bool set(TValue); + // TValue = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE bool set(const TValue* value) { + return _object.set(_key, value); + } + // + // bool set(TValue, uint8_t decimals); + // TValue = float, double + template + DEPRECATED("Second argument is not supported anymore") + FORCE_INLINE bool set(const TValue& value, uint8_t) { + return _object.set(_key, value); + } + + private: + JsonObject& _object; + TStringRef _key; +}; + +#if ARDUINOJSON_ENABLE_STD_STREAM +template +inline std::ostream& operator<<(std::ostream& os, + const JsonObjectSubscript& source) { + return source.printTo(os); +} +#endif +} // namespace ArduinoJson + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonPair.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonPair.hpp new file mode 100644 index 000000000..5a32601c0 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonPair.hpp @@ -0,0 +1,19 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonVariant.hpp" + +namespace ArduinoJson { + +// A key value pair for JsonObject. +struct JsonPair { + const char* key; + JsonVariant value; +}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariant.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariant.hpp new file mode 100644 index 000000000..9037d54d1 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariant.hpp @@ -0,0 +1,360 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include +#include // for uint8_t + +#include "Data/JsonVariantContent.hpp" +#include "Data/JsonVariantDefault.hpp" +#include "Data/JsonVariantType.hpp" +#include "JsonVariantBase.hpp" +#include "RawJson.hpp" +#include "Serialization/JsonPrintable.hpp" +#include "TypeTraits/EnableIf.hpp" +#include "TypeTraits/IsChar.hpp" +#include "TypeTraits/IsFloatingPoint.hpp" +#include "TypeTraits/IsIntegral.hpp" +#include "TypeTraits/IsSame.hpp" +#include "TypeTraits/IsSignedIntegral.hpp" +#include "TypeTraits/IsUnsignedIntegral.hpp" +#include "TypeTraits/RemoveConst.hpp" +#include "TypeTraits/RemoveReference.hpp" + +namespace ArduinoJson { + +// Forward declarations. +class JsonArray; +class JsonObject; + +// A variant that can be a any value serializable to a JSON value. +// +// It can be set to: +// - a boolean +// - a char, short, int or a long (signed or unsigned) +// - a string (const char*) +// - a reference to a JsonArray or JsonObject +class JsonVariant : public JsonVariantBase { + template + friend class Internals::JsonSerializer; + + public: + // Creates an uninitialized JsonVariant + JsonVariant() : _type(Internals::JSON_UNDEFINED) {} + + // Create a JsonVariant containing a boolean value. + // It will be serialized as "true" or "false" in JSON. + JsonVariant(bool value) { + using namespace Internals; + _type = JSON_BOOLEAN; + _content.asInteger = static_cast(value); + } + + // Create a JsonVariant containing a floating point value. + // JsonVariant(double value); + // JsonVariant(float value); + template + JsonVariant(T value, typename TypeTraits::EnableIf< + TypeTraits::IsFloatingPoint::value>::type * = 0) { + using namespace Internals; + _type = JSON_FLOAT; + _content.asFloat = static_cast(value); + } + template + DEPRECATED("Second argument is not supported anymore") + JsonVariant(T value, uint8_t, + typename TypeTraits::EnableIf< + TypeTraits::IsFloatingPoint::value>::type * = 0) { + using namespace Internals; + _type = JSON_FLOAT; + _content.asFloat = static_cast(value); + } + + // Create a JsonVariant containing an integer value. + // JsonVariant(char) + // JsonVariant(signed short) + // JsonVariant(signed int) + // JsonVariant(signed long) + // JsonVariant(signed char) + template + JsonVariant(T value, typename TypeTraits::EnableIf< + TypeTraits::IsSignedIntegral::value || + TypeTraits::IsSame::value>::type * = 0) { + using namespace Internals; + if (value >= 0) { + _type = JSON_POSITIVE_INTEGER; + _content.asInteger = static_cast(value); + } else { + _type = JSON_NEGATIVE_INTEGER; + _content.asInteger = static_cast(-value); + } + } + // JsonVariant(unsigned short) + // JsonVariant(unsigned int) + // JsonVariant(unsigned long) + template + JsonVariant(T value, + typename TypeTraits::EnableIf< + TypeTraits::IsUnsignedIntegral::value>::type * = 0) { + using namespace Internals; + _type = JSON_POSITIVE_INTEGER; + _content.asInteger = static_cast(value); + } + + // Create a JsonVariant containing a string. + // JsonVariant(const char*); + // JsonVariant(const signed char*); + // JsonVariant(const unsigned char*); + template + JsonVariant( + const TChar *value, + typename TypeTraits::EnableIf::value>::type * = + 0) { + _type = Internals::JSON_STRING; + _content.asString = reinterpret_cast(value); + } + + // Create a JsonVariant containing an unparsed string + JsonVariant(RawJson value) { + _type = Internals::JSON_UNPARSED; + _content.asString = value; + } + + // Create a JsonVariant containing a reference to an array. + // CAUTION: we are lying about constness, because the array can be modified if + // the variant is converted back to a JsonArray& + JsonVariant(const JsonArray &array); + + // Create a JsonVariant containing a reference to an object. + // CAUTION: we are lying about constness, because the object can be modified + // if the variant is converted back to a JsonObject& + JsonVariant(const JsonObject &object); + + // Get the variant as the specified type. + // + // char as() const; + // signed char as() const; + // signed short as() const; + // signed int as() const; + // signed long as() const; + // unsigned char as() const; + // unsigned short as() const; + // unsigned int as() const; + // unsigned long as() const; + template + const typename TypeTraits::EnableIf::value, T>::type + as() const { + return variantAsInteger(); + } + // bool as() const + template + const typename TypeTraits::EnableIf::value, + T>::type + as() const { + return variantAsInteger() != 0; + } + // + // double as() const; + // float as() const; + template + const typename TypeTraits::EnableIf::value, + T>::type + as() const { + return variantAsFloat(); + } + // + // const char* as() const; + // const char* as() const; + template + typename TypeTraits::EnableIf::value || + TypeTraits::IsSame::value, + const char *>::type + as() const { + return variantAsString(); + } + // + // std::string as() const; + // String as() const; + template + typename TypeTraits::EnableIf::has_append, T>::type + as() const { + const char *cstr = variantAsString(); + if (cstr) return T(cstr); + T s; + printTo(s); + return s; + } + // + // JsonArray& as const; + // JsonArray& as const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame::type, + JsonArray>::value, + JsonArray &>::type + as() const { + return variantAsArray(); + } + // + // const JsonArray& as const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame::type, + const JsonArray>::value, + const JsonArray &>::type + as() const { + return variantAsArray(); + } + // + // JsonObject& as const; + // JsonObject& as const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame::type, + JsonObject>::value, + JsonObject &>::type + as() const { + return variantAsObject(); + } + // + // JsonObject& as const; + // JsonObject& as const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame::type, + const JsonObject>::value, + const JsonObject &>::type + as() const { + return variantAsObject(); + } + // + // JsonVariant as const; + template + typename TypeTraits::EnableIf::value, + T>::type + as() const { + return *this; + } + + // Tells weither the variant has the specified type. + // Returns true if the variant has type type T, false otherwise. + // + // bool is() const; + // bool is() const; + // bool is() const; + // bool is() const; + // bool is() const; + // bool is() const; + // bool is() const; + // bool is() const; + // bool is() const; + template + typename TypeTraits::EnableIf::value, bool>::type + is() const { + return variantIsInteger(); + } + // + // bool is() const; + // bool is() const; + template + typename TypeTraits::EnableIf::value, + bool>::type + is() const { + return variantIsFloat(); + } + // + // bool is() const + template + typename TypeTraits::EnableIf::value, bool>::type + is() const { + return variantIsBoolean(); + } + // + // bool is() const; + // bool is() const; + template + typename TypeTraits::EnableIf::value || + TypeTraits::IsSame::value, + bool>::type + is() const { + return variantIsString(); + } + // + // bool is const; + // bool is const; + // bool is const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame< + typename TypeTraits::RemoveConst< + typename TypeTraits::RemoveReference::type>::type, + JsonArray>::value, + bool>::type + is() const { + return variantIsArray(); + } + // + // bool is const; + // bool is const; + // bool is const; + template + typename TypeTraits::EnableIf< + TypeTraits::IsSame< + typename TypeTraits::RemoveConst< + typename TypeTraits::RemoveReference::type>::type, + JsonObject>::value, + bool>::type + is() const { + return variantIsObject(); + } + + // Returns true if the variant has a value + bool success() const { + return _type != Internals::JSON_UNDEFINED; + } + + private: + JsonArray &variantAsArray() const; + JsonObject &variantAsObject() const; + const char *variantAsString() const; + template + T variantAsFloat() const; + template + T variantAsInteger() const; + bool variantIsBoolean() const; + bool variantIsFloat() const; + bool variantIsInteger() const; + bool variantIsArray() const { + return _type == Internals::JSON_ARRAY; + } + bool variantIsObject() const { + return _type == Internals::JSON_OBJECT; + } + bool variantIsString() const { + return _type == Internals::JSON_STRING || + (_type == Internals::JSON_UNPARSED && _content.asString && + !strcmp("null", _content.asString)); + } + + // The current type of the variant + Internals::JsonVariantType _type; + + // The various alternatives for the value of the variant. + Internals::JsonVariantContent _content; +}; + +DEPRECATED("Decimal places are ignored, use the float value instead") +inline JsonVariant float_with_n_digits(float value, uint8_t) { + return JsonVariant(value); +} + +DEPRECATED("Decimal places are ignored, use the double value instead") +inline JsonVariant double_with_n_digits(double value, uint8_t) { + return JsonVariant(value); +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantBase.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantBase.hpp new file mode 100644 index 000000000..a010e253f --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantBase.hpp @@ -0,0 +1,23 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonVariantCasts.hpp" +#include "JsonVariantComparisons.hpp" +#include "JsonVariantSubscripts.hpp" +#include "Serialization/JsonPrintable.hpp" + +namespace ArduinoJson { + +template +class JsonVariantBase : public Internals::JsonPrintable, + public JsonVariantCasts, + public JsonVariantComparisons, + public JsonVariantSubscripts, + public TypeTraits::JsonVariantTag {}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantCasts.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantCasts.hpp new file mode 100644 index 000000000..b3b41b4ba --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantCasts.hpp @@ -0,0 +1,60 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Data/JsonVariantAs.hpp" +#include "Polyfills/attributes.hpp" + +namespace ArduinoJson { + +template +class JsonVariantCasts { + public: +#if ARDUINOJSON_ENABLE_DEPRECATED + DEPRECATED("use as() instead") + FORCE_INLINE JsonArray &asArray() const { + return impl()->template as(); + } + + DEPRECATED("use as() instead") + FORCE_INLINE JsonObject &asObject() const { + return impl()->template as(); + } + + DEPRECATED("use as() instead") + FORCE_INLINE const char *asString() const { + return impl()->template as(); + } +#endif + + // Gets the variant as an array. + // Returns a reference to the JsonArray or JsonArray::invalid() if the + // variant + // is not an array. + FORCE_INLINE operator JsonArray &() const { + return impl()->template as(); + } + + // Gets the variant as an object. + // Returns a reference to the JsonObject or JsonObject::invalid() if the + // variant is not an object. + FORCE_INLINE operator JsonObject &() const { + return impl()->template as(); + } + + template + FORCE_INLINE operator T() const { + return impl()->template as(); + } + + private: + const TImpl *impl() const { + return static_cast(this); + } +}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantComparisons.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantComparisons.hpp new file mode 100644 index 000000000..eb0ef5c2c --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantComparisons.hpp @@ -0,0 +1,144 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "StringTraits/StringTraits.hpp" +#include "TypeTraits/EnableIf.hpp" +#include "TypeTraits/IsVariant.hpp" + +namespace ArduinoJson { + +template +class JsonVariantComparisons { + public: + template + friend bool operator==(const JsonVariantComparisons &variant, + TComparand comparand) { + return variant.equals(comparand); + } + + template + friend + typename TypeTraits::EnableIf::value, + bool>::type + operator==(TComparand comparand, const JsonVariantComparisons &variant) { + return variant.equals(comparand); + } + + template + friend bool operator!=(const JsonVariantComparisons &variant, + TComparand comparand) { + return !variant.equals(comparand); + } + + template + friend + typename TypeTraits::EnableIf::value, + bool>::type + operator!=(TComparand comparand, const JsonVariantComparisons &variant) { + return !variant.equals(comparand); + } + + template + friend bool operator<=(const JsonVariantComparisons &left, TComparand right) { + return left.as() <= right; + } + + template + friend bool operator<=(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand <= variant.as(); + } + + template + friend bool operator>=(const JsonVariantComparisons &variant, + TComparand comparand) { + return variant.as() >= comparand; + } + + template + friend bool operator>=(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand >= variant.as(); + } + + template + friend bool operator<(const JsonVariantComparisons &varian, + TComparand comparand) { + return varian.as() < comparand; + } + + template + friend bool operator<(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand < variant.as(); + } + + template + friend bool operator>(const JsonVariantComparisons &variant, + TComparand comparand) { + return variant.as() > comparand; + } + + template + friend bool operator>(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand > variant.as(); + } + + private: + const TImpl *impl() const { + return static_cast(this); + } + + template + const typename Internals::JsonVariantAs::type as() const { + return impl()->template as(); + } + + template + bool is() const { + return impl()->template is(); + } + + template + typename TypeTraits::EnableIf::value, + bool>::type + equals(const TString &comparand) const { + const char *value = as(); + return Internals::StringTraits::equals(comparand, value); + } + + template + typename TypeTraits::EnableIf::value && + !TypeTraits::IsString::value, + bool>::type + equals(const TComparand &comparand) const { + return as() == comparand; + } + + template + bool equals(const JsonVariantComparisons &right) const { + using namespace Internals; + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return strcmp(as(), right.template as()) == 0; + + return false; + } +}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantImpl.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantImpl.hpp new file mode 100644 index 000000000..eb6a4735d --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantImpl.hpp @@ -0,0 +1,129 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Configuration.hpp" +#include "JsonArray.hpp" +#include "JsonObject.hpp" +#include "JsonVariant.hpp" +#include "Polyfills/isFloat.hpp" +#include "Polyfills/isInteger.hpp" +#include "Polyfills/parseFloat.hpp" +#include "Polyfills/parseInteger.hpp" + +#include // for strcmp + +namespace ArduinoJson { + +inline JsonVariant::JsonVariant(const JsonArray &array) { + if (array.success()) { + _type = Internals::JSON_ARRAY; + _content.asArray = const_cast(&array); + } else { + _type = Internals::JSON_UNDEFINED; + } +} + +inline JsonVariant::JsonVariant(const JsonObject &object) { + if (object.success()) { + _type = Internals::JSON_OBJECT; + _content.asObject = const_cast(&object); + } else { + _type = Internals::JSON_UNDEFINED; + } +} + +inline JsonArray &JsonVariant::variantAsArray() const { + if (_type == Internals::JSON_ARRAY) return *_content.asArray; + return JsonArray::invalid(); +} + +inline JsonObject &JsonVariant::variantAsObject() const { + if (_type == Internals::JSON_OBJECT) return *_content.asObject; + return JsonObject::invalid(); +} + +template +inline T JsonVariant::variantAsInteger() const { + using namespace Internals; + switch (_type) { + case JSON_UNDEFINED: + return 0; + case JSON_POSITIVE_INTEGER: + case JSON_BOOLEAN: + return T(_content.asInteger); + case JSON_NEGATIVE_INTEGER: + return T(~_content.asInteger + 1); + case JSON_STRING: + case JSON_UNPARSED: + return Polyfills::parseInteger(_content.asString); + default: + return T(_content.asFloat); + } +} + +inline const char *JsonVariant::variantAsString() const { + using namespace Internals; + if (_type == JSON_UNPARSED && _content.asString && + !strcmp("null", _content.asString)) + return NULL; + if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString; + return NULL; +} + +template +inline T JsonVariant::variantAsFloat() const { + using namespace Internals; + switch (_type) { + case JSON_UNDEFINED: + return 0; + case JSON_POSITIVE_INTEGER: + case JSON_BOOLEAN: + return static_cast(_content.asInteger); + case JSON_NEGATIVE_INTEGER: + return -static_cast(_content.asInteger); + case JSON_STRING: + case JSON_UNPARSED: + return Polyfills::parseFloat(_content.asString); + default: + return static_cast(_content.asFloat); + } +} + +inline bool JsonVariant::variantIsBoolean() const { + using namespace Internals; + if (_type == JSON_BOOLEAN) return true; + + if (_type != JSON_UNPARSED || _content.asString == NULL) return false; + + return !strcmp(_content.asString, "true") || + !strcmp(_content.asString, "false"); +} + +inline bool JsonVariant::variantIsInteger() const { + using namespace Internals; + + return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER || + (_type == JSON_UNPARSED && Polyfills::isInteger(_content.asString)); +} + +inline bool JsonVariant::variantIsFloat() const { + using namespace Internals; + + return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER || + _type == JSON_NEGATIVE_INTEGER || + (_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString)); +} + +#if ARDUINOJSON_ENABLE_STD_STREAM +inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) { + return source.printTo(os); +} +#endif + +} // namespace ArduinoJson diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantSubscripts.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantSubscripts.hpp new file mode 100644 index 000000000..2143236a6 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/JsonVariantSubscripts.hpp @@ -0,0 +1,89 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Data/JsonVariantAs.hpp" +#include "Polyfills/attributes.hpp" +#include "StringTraits/StringTraits.hpp" +#include "TypeTraits/EnableIf.hpp" + +namespace ArduinoJson { + +// Forward declarations. +class JsonArraySubscript; +template +class JsonObjectSubscript; + +template +class JsonVariantSubscripts { + public: + // Mimics an array or an object. + // Returns the size of the array or object if the variant has that type. + // Returns 0 if the variant is neither an array nor an object + size_t size() const { + return impl()->template as().size() + + impl()->template as().size(); + } + + // Mimics an array. + // Returns the element at specified index if the variant is an array. + // Returns JsonVariant::invalid() if the variant is not an array. + FORCE_INLINE const JsonArraySubscript operator[](size_t index) const; + FORCE_INLINE JsonArraySubscript operator[](size_t index); + + // Mimics an object. + // Returns the value associated with the specified key if the variant is + // an object. + // Return JsonVariant::invalid() if the variant is not an object. + // + // const JsonObjectSubscript operator[](TKey) const; + // TKey = const std::string&, const String& + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + const JsonObjectSubscript >::type + operator[](const TString &key) const { + return impl()->template as()[key]; + } + // + // const JsonObjectSubscript operator[](TKey) const; + // TKey = const std::string&, const String& + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + JsonObjectSubscript >::type + operator[](const TString &key) { + return impl()->template as()[key]; + } + // + // JsonObjectSubscript operator[](TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + JsonObjectSubscript >::type + operator[](const TString *key) { + return impl()->template as()[key]; + } + // + // JsonObjectSubscript operator[](TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + const JsonObjectSubscript >::type + operator[](const TString *key) const { + return impl()->template as()[key]; + } + + private: + const TImpl *impl() const { + return static_cast(this); + } +}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/attributes.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/attributes.hpp new file mode 100644 index 000000000..e4f9406ac --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/attributes.hpp @@ -0,0 +1,32 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#ifdef _MSC_VER // Visual Studio + +#define FORCE_INLINE __forceinline +#define NO_INLINE __declspec(noinline) +#define DEPRECATED(msg) __declspec(deprecated(msg)) + +#elif defined(__GNUC__) // GCC or Clang + +#define FORCE_INLINE __attribute__((always_inline)) +#define NO_INLINE __attribute__((noinline)) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#define DEPRECATED(msg) __attribute__((deprecated(msg))) +#else +#define DEPRECATED(msg) __attribute__((deprecated)) +#endif + +#else // Other compilers + +#define FORCE_INLINE +#define NO_INLINE +#define DEPRECATED(msg) + +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/ctype.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/ctype.hpp new file mode 100644 index 000000000..f13e3edf6 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/ctype.hpp @@ -0,0 +1,21 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Polyfills { + +inline bool isdigit(char c) { + return '0' <= c && c <= '9'; +} + +inline bool issign(char c) { + return '-' == c || c == '+'; +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isFloat.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isFloat.hpp new file mode 100644 index 000000000..f6b9c97d9 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isFloat.hpp @@ -0,0 +1,41 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include // for strcmp +#include "./ctype.hpp" + +namespace ArduinoJson { +namespace Polyfills { + +inline bool isFloat(const char* s) { + if (!s) return false; + + if (!strcmp(s, "NaN")) return true; + if (issign(*s)) s++; + if (!strcmp(s, "Infinity")) return true; + if (*s == '\0') return false; + + while (isdigit(*s)) s++; + + if (*s == '.') { + s++; + while (isdigit(*s)) s++; + } + + if (*s == 'e' || *s == 'E') { + s++; + if (issign(*s)) s++; + if (!isdigit(*s)) return false; + while (isdigit(*s)) s++; + } + + return *s == '\0'; +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp new file mode 100644 index 000000000..ea39f2a63 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/isInteger.hpp @@ -0,0 +1,22 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "./ctype.hpp" + +namespace ArduinoJson { +namespace Polyfills { + +inline bool isInteger(const char* s) { + if (!s) return false; + if (issign(*s)) s++; + while (isdigit(*s)) s++; + return *s == '\0'; +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/math.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/math.hpp new file mode 100644 index 000000000..9dbd161d6 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/math.hpp @@ -0,0 +1,22 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Polyfills { +template +bool isNaN(T x) { + return x != x; +} + +template +bool isInfinity(T x) { + return x != 0.0 && x * 2 == x; +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseFloat.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseFloat.hpp new file mode 100644 index 000000000..e5d99f1bf --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseFloat.hpp @@ -0,0 +1,93 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../TypeTraits/FloatTraits.hpp" +#include "./ctype.hpp" +#include "./math.hpp" + +namespace ArduinoJson { +namespace Polyfills { + +template +inline T parseFloat(const char* s) { + typedef TypeTraits::FloatTraits traits; + typedef typename traits::mantissa_type mantissa_t; + typedef typename traits::exponent_type exponent_t; + + if (!s) return 0; // NULL + + bool negative_result = false; + switch (*s) { + case '-': + negative_result = true; + s++; + break; + case '+': + s++; + break; + } + + if (*s == 't') return 1; // true + if (*s == 'n' || *s == 'N') return traits::nan(); + if (*s == 'i' || *s == 'I') + return negative_result ? -traits::inf() : traits::inf(); + + mantissa_t mantissa = 0; + exponent_t exponent_offset = 0; + + while (isdigit(*s)) { + if (mantissa < traits::mantissa_max / 10) + mantissa = mantissa * 10 + (*s - '0'); + else + exponent_offset++; + s++; + } + + if (*s == '.') { + s++; + while (isdigit(*s)) { + if (mantissa < traits::mantissa_max / 10) { + mantissa = mantissa * 10 + (*s - '0'); + exponent_offset--; + } + s++; + } + } + + int exponent = 0; + if (*s == 'e' || *s == 'E') { + s++; + bool negative_exponent = false; + if (*s == '-') { + negative_exponent = true; + s++; + } else if (*s == '+') { + s++; + } + + while (isdigit(*s)) { + exponent = exponent * 10 + (*s - '0'); + if (exponent + exponent_offset > traits::exponent_max) { + if (negative_exponent) + return negative_result ? -0.0f : 0.0f; + else + return negative_result ? -traits::inf() : traits::inf(); + } + s++; + } + if (negative_exponent) exponent = -exponent; + } + exponent += exponent_offset; + + T result = traits::make_float(static_cast(mantissa), exponent); + + return negative_result ? -result : result; +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseInteger.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseInteger.hpp new file mode 100644 index 000000000..023d7bcbd --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Polyfills/parseInteger.hpp @@ -0,0 +1,44 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include + +#include "../Configuration.hpp" +#include "./ctype.hpp" + +namespace ArduinoJson { +namespace Polyfills { +template +T parseInteger(const char *s) { + if (!s) return 0; // NULL + + if (*s == 't') return 1; // "true" + + T result = 0; + bool negative_result = false; + + switch (*s) { + case '-': + negative_result = true; + s++; + break; + case '+': + s++; + break; + } + + while (isdigit(*s)) { + result = T(result * 10 + T(*s - '0')); + s++; + } + + return negative_result ? T(~result + 1) : result; +} +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp new file mode 100644 index 000000000..6db195c32 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/RawJson.hpp @@ -0,0 +1,23 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { + +// A special type of data that can be used to insert pregenerated JSON portions. +class RawJson { + public: + explicit RawJson(const char* str) : _str(str) {} + operator const char*() const { + return _str; + } + + private: + const char* _str; +}; +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DummyPrint.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DummyPrint.hpp new file mode 100644 index 000000000..656aa9ed6 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DummyPrint.hpp @@ -0,0 +1,25 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +// A dummy Print implementation used in JsonPrintable::measureLength() +class DummyPrint { + public: + size_t print(char) { + return 1; + } + + size_t print(const char* s) { + return strlen(s); + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp new file mode 100644 index 000000000..a344588de --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/DynamicStringBuilder.hpp @@ -0,0 +1,38 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../StringTraits/StringTraits.hpp" + +namespace ArduinoJson { +namespace Internals { + +// A Print implementation that allows to write in a String +template +class DynamicStringBuilder { + public: + DynamicStringBuilder(TString &str) : _str(str) {} + + size_t print(char c) { + StringTraits::append(_str, c); + return 1; + } + + size_t print(const char *s) { + size_t initialLen = _str.length(); + StringTraits::append(_str, s); + return _str.length() - initialLen; + } + + private: + DynamicStringBuilder &operator=(const DynamicStringBuilder &); + + TString &_str; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/FloatParts.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/FloatParts.hpp new file mode 100644 index 000000000..fa650723d --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/FloatParts.hpp @@ -0,0 +1,92 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../Configuration.hpp" +#include "../Polyfills/math.hpp" +#include "../TypeTraits/FloatTraits.hpp" + +namespace ArduinoJson { +namespace Internals { + +template +struct FloatParts { + uint32_t integral; + uint32_t decimal; + int16_t exponent; + int8_t decimalPlaces; + + FloatParts(TFloat value) { + uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000; + decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6; + + exponent = normalize(value); + + integral = uint32_t(value); + // reduce number of decimal places by the number of integral places + for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) { + maxDecimalPart /= 10; + decimalPlaces--; + } + + TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart); + + decimal = uint32_t(remainder); + remainder = remainder - TFloat(decimal); + + // rounding: + // increment by 1 if remainder >= 0.5 + decimal += uint32_t(remainder * 2); + if (decimal >= maxDecimalPart) { + decimal = 0; + integral++; + if (exponent && integral >= 10) { + exponent++; + integral = 1; + } + } + + // remove trailing zeros + while (decimal % 10 == 0 && decimalPlaces > 0) { + decimal /= 10; + decimalPlaces--; + } + } + + static int16_t normalize(TFloat& value) { + typedef TypeTraits::FloatTraits traits; + int16_t powersOf10 = 0; + + int8_t index = sizeof(TFloat) == 8 ? 8 : 5; + int bit = 1 << index; + + if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) { + for (; index >= 0; index--) { + if (value >= traits::positiveBinaryPowerOfTen(index)) { + value *= traits::negativeBinaryPowerOfTen(index); + powersOf10 = int16_t(powersOf10 + bit); + } + bit >>= 1; + } + } + + if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) { + for (; index >= 0; index--) { + if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) { + value *= traits::positiveBinaryPowerOfTen(index); + powersOf10 = int16_t(powersOf10 - bit); + } + bit >>= 1; + } + } + + return powersOf10; + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/IndentedPrint.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/IndentedPrint.hpp new file mode 100644 index 000000000..66ca6ac2f --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/IndentedPrint.hpp @@ -0,0 +1,71 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +// Decorator on top of Print to allow indented output. +// This class is used by JsonPrintable::prettyPrintTo() but can also be used +// for your own purpose, like logging. +template +class IndentedPrint { + public: + explicit IndentedPrint(Print &p) : sink(&p) { + level = 0; + tabSize = 2; + isNewLine = true; + } + + size_t print(char c) { + size_t n = 0; + if (isNewLine) n += writeTabs(); + n += sink->print(c); + isNewLine = c == '\n'; + return n; + } + + size_t print(const char *s) { + // TODO: optimize + size_t n = 0; + while (*s) n += print(*s++); + return n; + } + + // Adds one level of indentation + void indent() { + if (level < MAX_LEVEL) level++; + } + + // Removes one level of indentation + void unindent() { + if (level > 0) level--; + } + + // Set the number of space printed for each level of indentation + void setTabSize(uint8_t n) { + if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE; + } + + private: + Print *sink; + uint8_t level : 4; + uint8_t tabSize : 3; + bool isNewLine : 1; + + size_t writeTabs() { + size_t n = 0; + for (int i = 0; i < level * tabSize; i++) n += sink->print(' '); + return n; + } + + static const int MAX_LEVEL = 15; // because it's only 4 bits + static const int MAX_TAB_SIZE = 7; // because it's only 3 bits +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonPrintable.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonPrintable.hpp new file mode 100644 index 000000000..f33e5584e --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonPrintable.hpp @@ -0,0 +1,122 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../Configuration.hpp" +#include "../TypeTraits/EnableIf.hpp" +#include "DummyPrint.hpp" +#include "DynamicStringBuilder.hpp" +#include "IndentedPrint.hpp" +#include "JsonSerializer.hpp" +#include "JsonWriter.hpp" +#include "Prettyfier.hpp" +#include "StaticStringBuilder.hpp" + +#if ARDUINOJSON_ENABLE_STD_STREAM +#include "StreamPrintAdapter.hpp" +#endif + +namespace ArduinoJson { +namespace Internals { + +// Implements all the overloads of printTo() and prettyPrintTo() +// Caution: this class use a template parameter to avoid virtual methods. +// This is a bit curious but allows to reduce the size of JsonVariant, JsonArray +// and JsonObject. +template +class JsonPrintable { + public: + template + typename TypeTraits::EnableIf::value, + size_t>::type + printTo(Print &print) const { + JsonWriter writer(print); + JsonSerializer >::serialize(downcast(), writer); + return writer.bytesWritten(); + } + +#if ARDUINOJSON_ENABLE_STD_STREAM + std::ostream &printTo(std::ostream &os) const { + StreamPrintAdapter adapter(os); + printTo(adapter); + return os; + } +#endif + + size_t printTo(char *buffer, size_t bufferSize) const { + StaticStringBuilder sb(buffer, bufferSize); + return printTo(sb); + } + + template + size_t printTo(char (&buffer)[N]) const { + return printTo(buffer, N); + } + + template + typename TypeTraits::EnableIf::has_append, size_t>::type + printTo(TString &str) const { + DynamicStringBuilder sb(str); + return printTo(sb); + } + + template + size_t prettyPrintTo(IndentedPrint &print) const { + Prettyfier p(print); + return printTo(p); + } + + size_t prettyPrintTo(char *buffer, size_t bufferSize) const { + StaticStringBuilder sb(buffer, bufferSize); + return prettyPrintTo(sb); + } + + template + size_t prettyPrintTo(char (&buffer)[N]) const { + return prettyPrintTo(buffer, N); + } + + template + typename TypeTraits::EnableIf::value, + size_t>::type + prettyPrintTo(Print &print) const { + IndentedPrint indentedPrint(print); + return prettyPrintTo(indentedPrint); + } + + template + typename TypeTraits::EnableIf::has_append, size_t>::type + prettyPrintTo(TString &str) const { + DynamicStringBuilder sb(str); + return prettyPrintTo(sb); + } + + size_t measureLength() const { + DummyPrint dp; + return printTo(dp); + } + + size_t measurePrettyLength() const { + DummyPrint dp; + return prettyPrintTo(dp); + } + + private: + const T &downcast() const { + return *static_cast(this); + } +}; + +#if ARDUINOJSON_ENABLE_STD_STREAM +template +inline std::ostream &operator<<(std::ostream &os, const JsonPrintable &v) { + return v.printTo(os); +} +#endif +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializer.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializer.hpp new file mode 100644 index 000000000..86ed73ee1 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializer.hpp @@ -0,0 +1,34 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonWriter.hpp" + +namespace ArduinoJson { + +class JsonArray; +class JsonArraySubscript; +class JsonObject; +template +class JsonObjectSubscript; +class JsonVariant; + +namespace Internals { + +template +class JsonSerializer { + public: + static void serialize(const JsonArray &, Writer &); + static void serialize(const JsonArraySubscript &, Writer &); + static void serialize(const JsonObject &, Writer &); + template + static void serialize(const JsonObjectSubscript &, Writer &); + static void serialize(const JsonVariant &, Writer &); +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp new file mode 100644 index 000000000..f544488af --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp @@ -0,0 +1,106 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../JsonArray.hpp" +#include "../JsonArraySubscript.hpp" +#include "../JsonObject.hpp" +#include "../JsonObjectSubscript.hpp" +#include "../JsonVariant.hpp" +#include "JsonSerializer.hpp" + +template +inline void ArduinoJson::Internals::JsonSerializer::serialize( + const JsonArray& array, Writer& writer) { + writer.beginArray(); + + JsonArray::const_iterator it = array.begin(); + while (it != array.end()) { + serialize(*it, writer); + + ++it; + if (it == array.end()) break; + + writer.writeComma(); + } + + writer.endArray(); +} + +template +inline void ArduinoJson::Internals::JsonSerializer::serialize( + const JsonArraySubscript& arraySubscript, Writer& writer) { + serialize(arraySubscript.as(), writer); +} + +template +inline void ArduinoJson::Internals::JsonSerializer::serialize( + const JsonObject& object, Writer& writer) { + writer.beginObject(); + + JsonObject::const_iterator it = object.begin(); + while (it != object.end()) { + writer.writeString(it->key); + writer.writeColon(); + serialize(it->value, writer); + + ++it; + if (it == object.end()) break; + + writer.writeComma(); + } + + writer.endObject(); +} + +template +template +inline void ArduinoJson::Internals::JsonSerializer::serialize( + const JsonObjectSubscript& objectSubscript, Writer& writer) { + serialize(objectSubscript.template as(), writer); +} + +template +inline void ArduinoJson::Internals::JsonSerializer::serialize( + const JsonVariant& variant, Writer& writer) { + switch (variant._type) { + case JSON_FLOAT: + writer.writeFloat(variant._content.asFloat); + return; + + case JSON_ARRAY: + serialize(*variant._content.asArray, writer); + return; + + case JSON_OBJECT: + serialize(*variant._content.asObject, writer); + return; + + case JSON_STRING: + writer.writeString(variant._content.asString); + return; + + case JSON_UNPARSED: + writer.writeRaw(variant._content.asString); + return; + + case JSON_NEGATIVE_INTEGER: + writer.writeRaw('-'); // Falls through. + + case JSON_POSITIVE_INTEGER: + writer.writeInteger(variant._content.asInteger); + return; + + case JSON_BOOLEAN: + writer.writeBoolean(variant._content.asInteger != 0); + return; + + default: // JSON_UNDEFINED + return; + } +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonWriter.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonWriter.hpp new file mode 100644 index 000000000..2d54a2a0b --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/JsonWriter.hpp @@ -0,0 +1,158 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include +#include "../Data/Encoding.hpp" +#include "../Data/JsonInteger.hpp" +#include "../Polyfills/attributes.hpp" +#include "../Serialization/FloatParts.hpp" + +namespace ArduinoJson { +namespace Internals { + +// Writes the JSON tokens to a Print implementation +// This class is used by: +// - JsonArray::writeTo() +// - JsonObject::writeTo() +// - JsonVariant::writeTo() +// Its derived by PrettyJsonWriter that overrides some members to add +// indentation. +template +class JsonWriter { + public: + explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} + + // Returns the number of bytes sent to the Print implementation. + // This is very handy for implementations of printTo() that must return the + // number of bytes written. + size_t bytesWritten() const { + return _length; + } + + void beginArray() { + writeRaw('['); + } + void endArray() { + writeRaw(']'); + } + + void beginObject() { + writeRaw('{'); + } + void endObject() { + writeRaw('}'); + } + + void writeColon() { + writeRaw(':'); + } + void writeComma() { + writeRaw(','); + } + + void writeBoolean(bool value) { + writeRaw(value ? "true" : "false"); + } + + void writeString(const char *value) { + if (!value) { + writeRaw("null"); + } else { + writeRaw('\"'); + while (*value) writeChar(*value++); + writeRaw('\"'); + } + } + + void writeChar(char c) { + char specialChar = Encoding::escapeChar(c); + if (specialChar) { + writeRaw('\\'); + writeRaw(specialChar); + } else { + writeRaw(c); + } + } + + template + void writeFloat(TFloat value) { + if (Polyfills::isNaN(value)) return writeRaw("NaN"); + + if (value < 0.0) { + writeRaw('-'); + value = -value; + } + + if (Polyfills::isInfinity(value)) return writeRaw("Infinity"); + + FloatParts parts(value); + + writeInteger(parts.integral); + if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces); + + if (parts.exponent < 0) { + writeRaw("e-"); + writeInteger(-parts.exponent); + } + + if (parts.exponent > 0) { + writeRaw('e'); + writeInteger(parts.exponent); + } + } + + template + void writeInteger(UInt value) { + char buffer[22]; + char *end = buffer + sizeof(buffer) - 1; + char *ptr = end; + + *ptr = 0; + do { + *--ptr = char(value % 10 + '0'); + value = UInt(value / 10); + } while (value); + + writeRaw(ptr); + } + + void writeDecimals(uint32_t value, int8_t width) { + // buffer should be big enough for all digits, the dot and the null + // terminator + char buffer[16]; + char *ptr = buffer + sizeof(buffer) - 1; + + // write the string in reverse order + *ptr = 0; + while (width--) { + *--ptr = char(value % 10 + '0'); + value /= 10; + } + *--ptr = '.'; + + // and dump it in the right order + writeRaw(ptr); + } + + void writeRaw(const char *s) { + _length += _sink.print(s); + } + void writeRaw(char c) { + _length += _sink.print(c); + } + + protected: + Print &_sink; + size_t _length; + + private: + JsonWriter &operator=(const JsonWriter &); // cannot be assigned +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/Prettyfier.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/Prettyfier.hpp new file mode 100644 index 000000000..377138b4f --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/Prettyfier.hpp @@ -0,0 +1,136 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "IndentedPrint.hpp" + +namespace ArduinoJson { +namespace Internals { + +// Converts a compact JSON string into an indented one. +template +class Prettyfier { + public: + explicit Prettyfier(IndentedPrint& p) : _sink(p) { + _previousChar = 0; + _inString = false; + } + + size_t print(char c) { + size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); + _previousChar = c; + return n; + } + + size_t print(const char* s) { + // TODO: optimize + size_t n = 0; + while (*s) n += print(*s++); + return n; + } + + private: + Prettyfier& operator=(const Prettyfier&); // cannot be assigned + + bool inEmptyBlock() { + return _previousChar == '{' || _previousChar == '['; + } + + size_t handleStringChar(char c) { + bool isQuote = c == '"' && _previousChar != '\\'; + + if (isQuote) _inString = false; + + return _sink.print(c); + } + + size_t handleMarkupChar(char c) { + switch (c) { + case '{': + case '[': + return writeBlockOpen(c); + + case '}': + case ']': + return writeBlockClose(c); + + case ':': + return writeColon(); + + case ',': + return writeComma(); + + case '"': + return writeQuoteOpen(); + + default: + return writeNormalChar(c); + } + } + + size_t writeBlockClose(char c) { + size_t n = 0; + n += unindentIfNeeded(); + n += _sink.print(c); + return n; + } + + size_t writeBlockOpen(char c) { + size_t n = 0; + n += indentIfNeeded(); + n += _sink.print(c); + return n; + } + + size_t writeColon() { + size_t n = 0; + n += _sink.print(": "); + return n; + } + + size_t writeComma() { + size_t n = 0; + n += _sink.print(",\r\n"); + return n; + } + + size_t writeQuoteOpen() { + _inString = true; + size_t n = 0; + n += indentIfNeeded(); + n += _sink.print('"'); + return n; + } + + size_t writeNormalChar(char c) { + size_t n = 0; + n += indentIfNeeded(); + n += _sink.print(c); + return n; + } + + size_t indentIfNeeded() { + if (!inEmptyBlock()) return 0; + + _sink.indent(); + return _sink.print("\r\n"); + } + + size_t unindentIfNeeded() { + if (inEmptyBlock()) return 0; + + _sink.unindent(); + return _sink.print("\r\n"); + } + + char _previousChar; + IndentedPrint& _sink; + bool _inString; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StaticStringBuilder.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StaticStringBuilder.hpp new file mode 100644 index 000000000..2df932fd4 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StaticStringBuilder.hpp @@ -0,0 +1,39 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +// A Print implementation that allows to write in a char[] +class StaticStringBuilder { + public: + StaticStringBuilder(char *buf, size_t size) : end(buf + size - 1), p(buf) { + *p = '\0'; + } + + size_t print(char c) { + if (p >= end) return 0; + *p++ = c; + *p = '\0'; + return 1; + } + + size_t print(const char *s) { + char *begin = p; + while (p < end && *s) *p++ = *s++; + *p = '\0'; + return size_t(p - begin); + } + + private: + char *end; + char *p; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp new file mode 100644 index 000000000..9c2f86fd7 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/Serialization/StreamPrintAdapter.hpp @@ -0,0 +1,42 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../Configuration.hpp" + +#if ARDUINOJSON_ENABLE_STD_STREAM + +#include + +namespace ArduinoJson { +namespace Internals { + +class StreamPrintAdapter { + public: + explicit StreamPrintAdapter(std::ostream& os) : _os(os) {} + + size_t print(char c) { + _os << c; + return 1; + } + + size_t print(const char* s) { + _os << s; + return strlen(s); + } + + private: + // cannot be assigned + StreamPrintAdapter& operator=(const StreamPrintAdapter&); + + std::ostream& _os; +}; +} +} + +#endif // ARDUINOJSON_ENABLE_STD_STREAM diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StaticJsonBuffer.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StaticJsonBuffer.hpp new file mode 100644 index 000000000..8eaa4bb53 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StaticJsonBuffer.hpp @@ -0,0 +1,126 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "JsonBufferBase.hpp" + +namespace ArduinoJson { + +class StaticJsonBufferBase : public JsonBufferBase { + public: + class String { + public: + String(StaticJsonBufferBase* parent) : _parent(parent) { + _start = parent->_buffer + parent->_size; + } + + void append(char c) { + if (_parent->canAlloc(1)) { + char* last = static_cast(_parent->doAlloc(1)); + *last = c; + } + } + + const char* c_str() const { + if (_parent->canAlloc(1)) { + char* last = static_cast(_parent->doAlloc(1)); + *last = '\0'; + return _start; + } else { + return NULL; + } + } + + private: + StaticJsonBufferBase* _parent; + char* _start; + }; + + StaticJsonBufferBase(char* buffer, size_t capa) + : _buffer(buffer), _capacity(capa), _size(0) {} + + // Gets the capacity of the buffer in bytes + size_t capacity() const { + return _capacity; + } + + // Gets the current usage of the buffer in bytes + size_t size() const { + return _size; + } + + // Allocates the specified amount of bytes in the buffer + virtual void* alloc(size_t bytes) { + alignNextAlloc(); + if (!canAlloc(bytes)) return NULL; + return doAlloc(bytes); + } + + // Resets the buffer. + // USE WITH CAUTION: this invalidates all previously allocated data + void clear() { + _size = 0; + } + + String startString() { + return String(this); + } + + protected: + ~StaticJsonBufferBase() {} + + private: + void alignNextAlloc() { + _size = round_size_up(_size); + } + + bool canAlloc(size_t bytes) const { + return _size + bytes <= _capacity; + } + + void* doAlloc(size_t bytes) { + void* p = &_buffer[_size]; + _size += bytes; + return p; + } + + char* _buffer; + size_t _capacity; + size_t _size; +}; + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnon-virtual-dtor" +#elif defined(__GNUC__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic push +#endif +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +// Implements a JsonBuffer with fixed memory allocation. +// The template paramenter CAPACITY specifies the capacity of the buffer in +// bytes. +template +class StaticJsonBuffer : public StaticJsonBufferBase { + public: + explicit StaticJsonBuffer() : StaticJsonBufferBase(_buffer, CAPACITY) {} + + private: + char _buffer[CAPACITY]; +}; +} + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic pop +#endif +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/ArduinoStream.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/ArduinoStream.hpp new file mode 100644 index 000000000..87d1672d5 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/ArduinoStream.hpp @@ -0,0 +1,61 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#if ARDUINOJSON_ENABLE_ARDUINO_STREAM + +#include + +namespace ArduinoJson { +namespace Internals { + +struct ArduinoStreamTraits { + class Reader { + Stream& _stream; + char _current, _next; + + public: + Reader(Stream& stream) : _stream(stream), _current(0), _next(0) {} + + void move() { + _current = _next; + _next = 0; + } + + char current() { + if (!_current) _current = read(); + return _current; + } + + char next() { + // assumes that current() has been called + if (!_next) _next = read(); + return _next; + } + + private: + char read() { + // don't use _stream.read() as it ignores the timeout + char c = 0; + _stream.readBytes(&c, 1); + return c; + } + }; +}; + +template +struct StringTraits::type>::value>::type> + : ArduinoStreamTraits {}; +} +} + +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/CharPointer.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/CharPointer.hpp new file mode 100644 index 000000000..203e3924e --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/CharPointer.hpp @@ -0,0 +1,58 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace Internals { + +template +struct CharPointerTraits { + class Reader { + const TChar* _ptr; + + public: + Reader(const TChar* ptr) + : _ptr(ptr ? ptr : reinterpret_cast("")) {} + + void move() { + ++_ptr; + } + + char current() const { + return char(_ptr[0]); + } + + char next() const { + return char(_ptr[1]); + } + }; + + static bool equals(const TChar* str, const char* expected) { + return strcmp(reinterpret_cast(str), expected) == 0; + } + + template + static char* duplicate(const TChar* str, Buffer* buffer) { + if (!str) return NULL; + size_t size = strlen(reinterpret_cast(str)) + 1; + void* dup = buffer->alloc(size); + if (dup != NULL) memcpy(dup, str, size); + return static_cast(dup); + } + + static const bool has_append = false; + static const bool has_equals = true; + static const bool should_duplicate = false; +}; + +template +struct StringTraits::value>::type> + : CharPointerTraits {}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/FlashString.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/FlashString.hpp new file mode 100644 index 000000000..37e36b8d2 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/FlashString.hpp @@ -0,0 +1,56 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#if ARDUINOJSON_ENABLE_PROGMEM + +namespace ArduinoJson { +namespace Internals { +template <> +struct StringTraits { + class Reader { + const char* _ptr; + + public: + Reader(const __FlashStringHelper* ptr) + : _ptr(reinterpret_cast(ptr)) {} + + void move() { + _ptr++; + } + + char current() const { + return pgm_read_byte_near(_ptr); + } + + char next() const { + return pgm_read_byte_near(_ptr + 1); + } + }; + + static bool equals(const __FlashStringHelper* str, const char* expected) { + return strcmp_P(expected, (const char*)str) == 0; + } + + template + static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) { + if (!str) return NULL; + size_t size = strlen_P((const char*)str) + 1; + void* dup = buffer->alloc(size); + if (dup != NULL) memcpy_P(dup, (const char*)str, size); + return static_cast(dup); + } + + static const bool has_append = false; + static const bool has_equals = true; + static const bool should_duplicate = true; +}; +} +} + +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdStream.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdStream.hpp new file mode 100644 index 000000000..35049d941 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdStream.hpp @@ -0,0 +1,60 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#if ARDUINOJSON_ENABLE_STD_STREAM + +#include + +namespace ArduinoJson { +namespace Internals { + +struct StdStreamTraits { + class Reader { + std::istream& _stream; + char _current, _next; + + public: + Reader(std::istream& stream) : _stream(stream), _current(0), _next(0) {} + + void move() { + _current = _next; + _next = 0; + } + + char current() { + if (!_current) _current = read(); + return _current; + } + + char next() { + // assumes that current() has been called + if (!_next) _next = read(); + return _next; + } + + private: + Reader& operator=(const Reader&); // Visual Studio C4512 + + char read() { + return _stream.eof() ? '\0' : static_cast(_stream.get()); + } + }; +}; + +template +struct StringTraits::type>::value>::type> + : StdStreamTraits {}; +} +} + +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdString.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdString.hpp new file mode 100644 index 000000000..959c47466 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StdString.hpp @@ -0,0 +1,70 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#if ARDUINOJSON_ENABLE_STD_STRING || ARDUINOJSON_ENABLE_ARDUINO_STRING + +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +#include +#endif + +#if ARDUINOJSON_ENABLE_STD_STRING +#include +#endif + +namespace ArduinoJson { +namespace Internals { + +template +struct StdStringTraits { + template + static char* duplicate(const TString& str, Buffer* buffer) { + if (!str.c_str()) return NULL; // <- Arduino string can return NULL + size_t size = str.length() + 1; + void* dup = buffer->alloc(size); + if (dup != NULL) memcpy(dup, str.c_str(), size); + return static_cast(dup); + } + + struct Reader : CharPointerTraits::Reader { + Reader(const TString& str) : CharPointerTraits::Reader(str.c_str()) {} + }; + + static bool equals(const TString& str, const char* expected) { + return 0 == strcmp(str.c_str(), expected); + } + + static void append(TString& str, char c) { + str += c; + } + + static void append(TString& str, const char* s) { + str += s; + } + + static const bool has_append = true; + static const bool has_equals = true; + static const bool should_duplicate = true; +}; + +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +template <> +struct StringTraits : StdStringTraits {}; +template <> +struct StringTraits : StdStringTraits { +}; +#endif + +#if ARDUINOJSON_ENABLE_STD_STRING +template <> +struct StringTraits : StdStringTraits {}; +#endif +} +} + +#endif diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StringTraits.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StringTraits.hpp new file mode 100644 index 000000000..55bacca26 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/StringTraits/StringTraits.hpp @@ -0,0 +1,50 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include +#include "../Configuration.hpp" +#include "../TypeTraits/EnableIf.hpp" +#include "../TypeTraits/IsBaseOf.hpp" +#include "../TypeTraits/IsChar.hpp" +#include "../TypeTraits/RemoveReference.hpp" + +namespace ArduinoJson { +namespace Internals { + +template +struct StringTraits {}; + +template +struct StringTraits : StringTraits {}; + +template +struct StringTraits : StringTraits {}; +} +} + +#include "ArduinoStream.hpp" +#include "CharPointer.hpp" +#include "FlashString.hpp" +#include "StdStream.hpp" +#include "StdString.hpp" + +namespace ArduinoJson { +namespace TypeTraits { +template +struct IsString { + static const bool value = false; +}; + +template +struct IsString::has_equals>::type> { + static const bool value = Internals::StringTraits::has_equals; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/EnableIf.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/EnableIf.hpp new file mode 100644 index 000000000..654b308e6 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/EnableIf.hpp @@ -0,0 +1,22 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that return the type T if Condition is true. +template +struct EnableIf {}; + +template +struct EnableIf { + typedef T type; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/FloatTraits.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/FloatTraits.hpp new file mode 100644 index 000000000..a52e1e879 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/FloatTraits.hpp @@ -0,0 +1,153 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include +#include // for size_t +#include "../Configuration.hpp" +#include "../Polyfills/math.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +template +struct FloatTraits {}; + +template +struct FloatTraits { + typedef int64_t mantissa_type; + static const short mantissa_bits = 52; + static const mantissa_type mantissa_max = + (static_cast(1) << mantissa_bits) - 1; + + typedef int16_t exponent_type; + static const exponent_type exponent_max = 308; + + template + static T make_float(T m, TExponent e) { + if (e > 0) { + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= positiveBinaryPowerOfTen(index); + e >>= 1; + } + } else { + e = TExponent(-e); + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= negativeBinaryPowerOfTen(index); + e >>= 1; + } + } + return m; + } + + static T positiveBinaryPowerOfTen(int index) { + static T factors[] = { + 1e1, 1e2, 1e4, 1e8, 1e16, 1e32, + // workaround to support platforms with single precision literals + forge(0x4D384F03, 0xE93FF9F5), forge(0x5A827748, 0xF9301D32), + forge(0x75154FDD, 0x7F73BF3C)}; + return factors[index]; + } + + static T negativeBinaryPowerOfTen(int index) { + static T factors[] = { + 1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32, + // workaround to support platforms with single precision literals + forge(0x32A50FFD, 0x44F4A73D), forge(0x255BBA08, 0xCF8C979D), + forge(0x0AC80628, 0x64AC6F43)}; + return factors[index]; + } + + static T negativeBinaryPowerOfTenPlusOne(int index) { + static T factors[] = { + 1e0, 1e-1, 1e-3, 1e-7, 1e-15, 1e-31, + // workaround to support platforms with single precision literals + forge(0x32DA53FC, 0x9631D10D), forge(0x25915445, 0x81B7DEC2), + forge(0x0AFE07B2, 0x7DD78B14)}; + return factors[index]; + } + + static T nan() { + return forge(0x7ff80000, 0x00000000); + } + + static T inf() { + return forge(0x7ff00000, 0x00000000); + } + + static T forge(uint32_t msb, uint32_t lsb) { + union { + uint64_t integerBits; + T floatBits; + }; + integerBits = (uint64_t(msb) << 32) | lsb; + return floatBits; + } +}; + +template +struct FloatTraits { + typedef int32_t mantissa_type; + static const short mantissa_bits = 23; + static const mantissa_type mantissa_max = + (static_cast(1) << mantissa_bits) - 1; + + typedef int8_t exponent_type; + static const exponent_type exponent_max = 38; + + template + static T make_float(T m, TExponent e) { + if (e > 0) { + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= positiveBinaryPowerOfTen(index); + e >>= 1; + } + } else { + e = -e; + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= negativeBinaryPowerOfTen(index); + e >>= 1; + } + } + return m; + } + + static T positiveBinaryPowerOfTen(int index) { + static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}; + return factors[index]; + } + + static T negativeBinaryPowerOfTen(int index) { + static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}; + return factors[index]; + } + + static T negativeBinaryPowerOfTenPlusOne(int index) { + static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}; + return factors[index]; + } + + static T forge(uint32_t bits) { + union { + uint32_t integerBits; + T floatBits; + }; + integerBits = bits; + return floatBits; + } + + static T nan() { + return forge(0x7fc00000); + } + + static T inf() { + return forge(0x7f800000); + } +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsArray.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsArray.hpp new file mode 100644 index 000000000..713808aed --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsArray.hpp @@ -0,0 +1,27 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that return the type T without the const modifier +template +struct IsArray { + static const bool value = false; +}; +template +struct IsArray { + static const bool value = true; +}; +template +struct IsArray { + static const bool value = true; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsBaseOf.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsBaseOf.hpp new file mode 100644 index 000000000..9e68debc3 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsBaseOf.hpp @@ -0,0 +1,30 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that returns true if Derived inherits from TBase is an +// integral type. +template +class IsBaseOf { + protected: // <- to avoid GCC's "all member functions in class are private" + typedef char Yes[1]; + typedef char No[2]; + + static Yes &probe(const TBase *); + static No &probe(...); + + public: + enum { + value = sizeof(probe(reinterpret_cast(0))) == sizeof(Yes) + }; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsChar.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsChar.hpp new file mode 100644 index 000000000..bd1b5fdd5 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsChar.hpp @@ -0,0 +1,26 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "IsSame.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that returns true if T is a charater +template +struct IsChar { + static const bool value = IsSame::value || + IsSame::value || + IsSame::value; +}; + +template +struct IsChar : IsChar {}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsConst.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsConst.hpp new file mode 100644 index 000000000..7ffed8443 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsConst.hpp @@ -0,0 +1,24 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that return the type T without the const modifier +template +struct IsConst { + static const bool value = false; +}; + +template +struct IsConst { + static const bool value = true; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp new file mode 100644 index 000000000..c04ce2a63 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsFloatingPoint.hpp @@ -0,0 +1,21 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "IsSame.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that returns true if T is a floating point type +template +struct IsFloatingPoint { + static const bool value = IsSame::value || IsSame::value; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsIntegral.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsIntegral.hpp new file mode 100644 index 000000000..e34add52e --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsIntegral.hpp @@ -0,0 +1,29 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "IsSame.hpp" +#include "IsSignedIntegral.hpp" +#include "IsUnsignedIntegral.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that returns true if T is an integral type. +template +struct IsIntegral { + static const bool value = TypeTraits::IsSignedIntegral::value || + TypeTraits::IsUnsignedIntegral::value || + TypeTraits::IsSame::value; + // CAUTION: differs from std::is_integral as it doesn't include bool +}; + +template +struct IsIntegral : IsIntegral {}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSame.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSame.hpp new file mode 100644 index 000000000..d96a5b554 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSame.hpp @@ -0,0 +1,24 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that returns true if types T and U are the same. +template +struct IsSame { + static const bool value = false; +}; + +template +struct IsSame { + static const bool value = true; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp new file mode 100644 index 000000000..fde6e13b0 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsSignedIntegral.hpp @@ -0,0 +1,33 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../Configuration.hpp" +#include "IsSame.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that returns true if T is an integral type. +template +struct IsSignedIntegral { + static const bool value = TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || +#if ARDUINOJSON_USE_LONG_LONG + TypeTraits::IsSame::value || +#endif + +#if ARDUINOJSON_USE_INT64 + TypeTraits::IsSame::value || +#endif + false; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp new file mode 100644 index 000000000..173763e05 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp @@ -0,0 +1,33 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "../Configuration.hpp" +#include "IsSame.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that returns true if T is an integral type. +template +struct IsUnsignedIntegral { + static const bool value = TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || +#if ARDUINOJSON_USE_LONG_LONG + TypeTraits::IsSame::value || +#endif + +#if ARDUINOJSON_USE_INT64 + TypeTraits::IsSame::value || +#endif + false; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsVariant.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsVariant.hpp new file mode 100644 index 000000000..8297cf5cd --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/IsVariant.hpp @@ -0,0 +1,20 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "IsBaseOf.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +class JsonVariantTag {}; + +template +struct IsVariant : IsBaseOf {}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveConst.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveConst.hpp new file mode 100644 index 000000000..0186234ef --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveConst.hpp @@ -0,0 +1,23 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that return the type T without the const modifier +template +struct RemoveConst { + typedef T type; +}; +template +struct RemoveConst { + typedef T type; +}; +} +} diff --git a/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveReference.hpp b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveReference.hpp new file mode 100644 index 000000000..4968997e7 --- /dev/null +++ b/lib/ArduinoJson-5.11.2/src/ArduinoJson/TypeTraits/RemoveReference.hpp @@ -0,0 +1,23 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +namespace ArduinoJson { +namespace TypeTraits { + +// A meta-function that return the type T without the reference modifier. +template +struct RemoveReference { + typedef T type; +}; +template +struct RemoveReference { + typedef T type; +}; +} +} diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md b/lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md new file mode 100644 index 000000000..9614d90a5 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/.github/CONTRIBUTING.md @@ -0,0 +1,82 @@ +# Contributing to the IRremoteESP8266 library + +:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: + +The following is a set of guidelines for contributing to the IRremoteESP8266 library, hosted on GitHub. These are guidelines, [not rules](http://imgur.com/mSHi8). Use your best judgment, and feel free to propose changes to this document in a pull request. + +#### Table Of Contents + +[Code of Conduct](#code-of-conduct) + +[How Can I Contribute?](#how-can-i-contribute) + * [Reporting Bugs](#reporting-bugs) + * [Pull Requests](#pull-requests) + +[Styleguides](#styleguides) + * [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) + * [Git Commit Messages](#git-commit-messages) + + +## Code of Conduct + +This project and everyone participating in it is governed by the principle of ["Be excellent to each other"](http://www.imdb.com/title/tt0096928/quotes). That's it. TL;DR: _Don't be a jerk._ + +## How Can I Contribute? + +### Reporting Bugs + +This section guides you through submitting a bug report for the library. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. + +Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as much detail as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](issue_template.md), the information it asks for helps us resolve issues faster. + +> **Note:** If you find a **Closed** issue that seems like it's the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. + +#### Before Submitting A Bug Report + +* **Check the [Troubleshooting Guide](https://github.com/markszabo/IRremoteESP8266/wiki/Troubleshooting-Guide).** You might be able to find the cause of the problem and fix it yourself. Most importantly, check if you can reproduce the problem in the latest version (a.k.a. 'master') of the library. +* **Perform a [cursory search](https://github.com/issues?q=+is%3Aissue+repo%3Amarkszabo/IRremoteESP8266)** to see if the problem is already reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one. + +#### How Do I Submit A (Good) Bug Report? + +Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Create an issue and provide the following information by filling in [the template](issue_template.md). + +Explain the problem and include any additional details to help maintainers reproduce the problem: + +* **Use a clear and descriptive title** for the issue to identify the problem. +* **Describe the exact steps which reproduce the problem** in as much detail as possible. +* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). +* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. +* **Explain which behavior you expected to see instead and why.** +* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below. + +Provide more context by answering these questions: + +* **Can you reproduce the problem in one of the code examples?** +* **Did the problem start happening recently** (e.g. after updating to a new version of Arduino or the library) or was this always a problem? +* If the problem started happening recently, **can you reproduce the problem in an older version of the library?** What's the most recent version in which the problem doesn't happen? You can download older versions of the library from [the releases page](https://github.com/markszabo/IRremoteESP8266/releases). +* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens. + +Include details about your configuration, circuit and environment: + +* **Which version of the library are you using?** You can get the exact version by inspecting the `library.json` file in the root directory of the library. +* **What board are you running this on?** + +### Pull Requests + +* Do not include issue numbers in the PR title +* Include as much data and comments as practicle. +* Follow the [C++ style guide](https://google.github.io/styleguide/cppguide.html). +* Please write or ensure Unit Tests cover the change you are making, if you can. +* End all files with a newline +* Avoid platform-dependent code. +* Use c98 types where possible for better portablity. +* In almost all cases, code & documentation should be peer-reviewed by at least one other contributor. +* The code should pass all the existing testing infrastructure in Travis. e.g. Unit tests, cpplint, and basic compilation. +* State if you have tested this under real conditions if you have, and what other tests you may have carried out. + +### Git Commit Messages + +* Limit the first line to 72 characters or less +* Reference issues and pull requests liberally after the first line +* Humour is always acceptable. Be liberal with it. ;-) +* While not required, a comprehensive description of all the changes in the PR is best. diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md b/lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md new file mode 100644 index 000000000..151a0c03d --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/.github/Contributors.md @@ -0,0 +1,16 @@ +## Contributors of this project +### Main contributors & maintainers +- [Mark Szabo](https://github.com/markszabo/) : Initial IR sending on ESP8266 +- [Sébastien Warin](https://github.com/sebastienwarin/) (http://sebastien.warin.fr) : Initial IR receiving on ESP8266 +- [David Conran](https://github.com/crankyoldgit/) +- [Roi Dayan](https://github.com/roidayan/) +- [Marcos de Alcântara Marinho](https://github.com/marcosamarinho/) +- [Massimiliano Pinto](https://github.com/pintomax/) +- [Darsh Patel](https://github.com/darshkpatel/) +- [Jonny Graham](https://github.com/jonnygraham/) +- [Stu Fisher](https://github.com/stufisher/) +- [Jorge Cisneros](https://github.com/jorgecis/) + +All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors). + +### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md) diff --git a/lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md b/lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md new file mode 100644 index 000000000..664b99570 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/.github/issue_template.md @@ -0,0 +1,39 @@ +_(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. +e.g. v2.0.0, or 'master' as at 1st of June, 2017. etc._ + +### Expected behavior +_What steps did you do and what should it have done?_ + +e.g. +1. Initialise the IRsend class. +2. IRsend.sendFoobar(0xdeadbeef); +3. Foobar branded BBQ turns on and cooks me some ribs. + +### Actual behavior +_What steps did you do, and what did or didn't actually happen?_ + +e.g. +1. Initialise the IRsend class. +2. IRsend.sendFoobar(0xdeadbeef); +3. Foobar BBQ went into Cow(er)-saving mode and fried me a couple of eggs instead. + +#### Output of raw data from IRrecvDumpV2.ino (if applicable) +_Include some raw dumps of what the device saw._ + +### Steps to reproduce the behavior +_What can we do to (pref. reliably) repeat what is happening?_ + +#### Example code used +_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._ + +### 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._ + +### Other useful information +_More information is always welcome. Be verbose._ diff --git a/lib/IRremoteESP8266-2.2.1.02/.gitignore b/lib/IRremoteESP8266-2.2.1.02/.gitignore new file mode 100644 index 000000000..6d57ebaab --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/.gitignore @@ -0,0 +1,39 @@ +#----------------------------------------# +# .gitingore for IRremoteESP8266 library # +#----------------------------------------# + +### Files to ignore. + +## Editors +# vi/vim +**/*.swp + +## Build environments +# Platformio +**/.pioenvs/ +**/.piolibdeps/ +**/.clang_complete +**/.gcc-flags.json +examples/**/lib +examples/**/.travis.yml +examples/**/.gitignore +lib/readme.txt +lib/googletest/**/* + +# GCC pre-compiled headers. +**/*.gch + +# Unit Test builds +test/*.o +test/*.a +test/*_test + +# Tools builds +tools/*.o +tools/*.a +tools/gc_decode + +.pioenvs +.piolibdeps +.clang_complete +.gcc-flags.json diff --git a/lib/IRremoteESP8266-2.2.1.02/.gitmodules b/lib/IRremoteESP8266-2.2.1.02/.gitmodules new file mode 100644 index 000000000..80925b865 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/googletest"] + path = lib/googletest + url = https://github.com/google/googletest.git diff --git a/lib/IRremoteESP8266-2.2.1.02/.travis.yml b/lib/IRremoteESP8266-2.2.1.02/.travis.yml new file mode 100644 index 000000000..33d91ba47 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/.travis.yml @@ -0,0 +1,57 @@ +language: c +env: + - BD=esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M + - BD=esp8266:esp8266:d1_mini:CpuFrequency=80,FlashSize=4M3M +before_install: + - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" + - sleep 3 + - export DISPLAY=:1.0 + - wget http://downloads.arduino.cc/arduino-1.8.2-linux64.tar.xz + - tar xf arduino-1.8.2-linux64.tar.xz + - sudo mv arduino-1.8.2 /usr/local/share/arduino + - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino + - wget https://raw.githubusercontent.com/google/styleguide/gh-pages/cpplint/cpplint.py +install: + - ln -s $PWD /usr/local/share/arduino/libraries/ + - git clone https://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WiFiManager + - git clone https://github.com/knolleary/pubsubclient.git /usr/local/share/arduino/libraries/PubSubClient + - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs + - arduino --install-boards esp8266:esp8266 + - arduino --board $BD --save-prefs + - arduino --pref "compiler.warning_level=all" --save-prefs + - sudo apt-get install jq +script: + # Check that everything compiles. + - arduino --verify --board $BD $PWD/examples/IRrecvDemo/IRrecvDemo.ino + - arduino --verify --board $BD $PWD/examples/IRGCSendDemo/IRGCSendDemo.ino + - arduino --verify --board $BD $PWD/examples/IRGCTCPServer/IRGCTCPServer.ino + - arduino --verify --board $BD $PWD/examples/IRServer/IRServer.ino + - arduino --verify --board $BD $PWD/examples/IRrecvDumpV2/IRrecvDumpV2.ino + - arduino --verify --board $BD $PWD/examples/IRsendDemo/IRsendDemo.ino + - arduino --verify --board $BD $PWD/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino + - arduino --verify --board $BD $PWD/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino + - arduino --verify --board $BD $PWD/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino + - arduino --verify --board $BD $PWD/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino + - arduino --verify --board $BD $PWD/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino + - arduino --verify --board $BD $PWD/examples/IRsendProntoDemo/IRsendProntoDemo.ino + - arduino --verify --board $BD $PWD/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino + - arduino --verify --board $BD $PWD/examples/LGACSend/LGACSend.ino + - arduino --verify --board $BD $PWD/examples/TurnOnArgoAC/TurnOnArgoAC.ino + - arduino --verify --board $BD $PWD/examples/IRMQTTServer/IRMQTTServer.ino + # 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} + - shopt -u nullglob + # Build and run the unit tests. + - (cd test; make run) + # Check the version numbers match. + - LIB_VERSION=$(egrep "^#define\s+_IRREMOTEESP8266_VERSION_\s+" src/IRremoteESP8266.h | cut -d\" -f2) + - test ${LIB_VERSION} == "$(jq -r .version library.json)" + - grep -q "^version=${LIB_VERSION}$" library.properties + +notifications: + email: + on_success: change + on_failure: change diff --git a/lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg b/lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg new file mode 100644 index 000000000..181f5204d --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/CPPLINT.cfg @@ -0,0 +1,3 @@ +set noparent +root=src +linelength=80 diff --git a/lib/IRremoteESP8266-2.2.1.02/LICENSE.txt b/lib/IRremoteESP8266-2.2.1.02/LICENSE.txt new file mode 100644 index 000000000..77cec6dd1 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/LICENSE.txt @@ -0,0 +1,458 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + diff --git a/lib/IRremoteESP8266-2.2.1.02/README.md b/lib/IRremoteESP8266-2.2.1.02/README.md new file mode 100644 index 000000000..6b2975793 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/README.md @@ -0,0 +1,74 @@ +# 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 new file mode 100644 index 000000000..3b9bce86a --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/ReleaseNotes.md @@ -0,0 +1,112 @@ +# 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/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino new file mode 100644 index 000000000..b36938e3d --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/IRGCSendDemo.ino @@ -0,0 +1,63 @@ +/* + * IRremoteESP8266: IRsendGCDemo + * demonstrates sending Global Cache-formatted IR codes with IRsend + * Copyright 2009 Ken Shirriff + * http://arcfn.com + * + * Version 0.2 June, 2017 + * Added helpful comments + * Better includes files. + * Version 0.1 30 March, 2016 + * Based on Ken Shirriff's IrsendDemo + * Version 0.1 July, 2009 + * + * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * + * 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 + +// Codes are in Global Cache format less the emitter ID and request ID. +// 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}; + +IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) + +void setup() { + irsend.begin(); + Serial.begin(115200); +} + +void loop() { + Serial.println("Toggling power"); + irsend.sendGC(Samsung_power_toggle, 71); + delay(10000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCSendDemo/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/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino new file mode 100644 index 000000000..2fd38be42 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/IRGCTCPServer.ino @@ -0,0 +1,129 @@ +/* + * IRremoteESP8266: IRGCTCPServer - send Global Cache-formatted codes via TCP. + * An IR emitter must be connected to GPIO pin 4. + * Version 0.2 May, 2017 + * Copyright 2016 Hisham Khalifa, http://www.hishamkhalifa.com + * Copyright 2017 David Conran + * + * Example command - Samsung TV power toggle: 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\r\n + * For more codes, visit: https://irdb.globalcache.com/ + * + * How to use this program: + * 1) Update "ssid" and "password" 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. + * 4) From a client machine, connect to port 4998 on the ESP8266, using + * 'telnet', 'nc' (netcat), 'putty' or similar command, etc. + * You may need to install one. + * Unix/OSX: + * Start a shell. Then type: + * telnet 4998 + * Windows: + * Start a new CMD window, then type: + * telnet 4998 + * + * 5) Enter a Global Cache-formatted code, starting at the frequency, + * and then a return/enter at the end. No spaces. e.g.: + * + * 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 + * + * To exit the 'telnet' command: + * press + <]> at the same time, then press 'q', and then . + * or: + * + might work. + * + * This program will display the ESP's IP address on the serial console, or you + * can check your wifi router for it's address. + */ + +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include +#include +#include + +const char* ssid = "..."; // Put your WIFI SSID here. +const char* password = "..."; // 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) + +void sendGCString(String str) { + int16_t index; + uint16_t count; + + // Find out how many items there are in the string. + index = -1; + count = 1; + do { + index = str.indexOf(',', index + 1); + count++; + } while (index != -1); + + // Now we know how many there are, allocate the memory to store them all. + code_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); + // Check we malloc'ed successfully. + if (code_array == NULL) { // malloc failed, so give up. + Serial.printf("\nCan't allocate %d bytes. (%d bytes free)\n", + count * sizeof(uint16_t), ESP.getFreeHeap()); + Serial.println("Giving up & forcing a reboot."); + ESP.restart(); // Reboot. + delay(500); // Wait for the restart to happen. + return; // Should never get here, but just in case. + } + + // Now convert the strings to integers and place them in code_array. + count = 0; + uint16_t start_from = 0; + do { + index = str.indexOf(',', start_from); + code_array[count] = str.substring(start_from, index).toInt(); + start_from = index + 1; + count++; + } while (index != -1); + + irsend.sendGC(code_array, count); // All done. Send it. + free(code_array); // Free up the memory allocated. +} + +void setup() { + // initialize serial: + Serial.begin(115200); + delay(100); + Serial.println(" "); + Serial.println("IR TCP Server"); + + while (WiFi.status() != WL_CONNECTED) { + delay(900); + Serial.print("."); + } + + server.begin(); + IPAddress myAddress = WiFi.localIP(); + Serial.println(myAddress); + irsend.begin(); +} + +void loop() { + while (!client) + client = server.available(); + + while (!client.connected()) { + delay(900); + client = server.available(); + } + + if (client.available()) { + String ir_code_str = client.readStringUntil('\r'); // Exclusive of \r + client.readStringUntil('\n'); // Skip new line as well + client.flush(); + sendGCString(ir_code_str); + } +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRGCTCPServer/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/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino new file mode 100644 index 000000000..e2c1f81d8 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/IRMQTTServer.ino @@ -0,0 +1,982 @@ +/* + * Send arbitary IR codes via a web server or MQTT. + * Copyright David Conran 2016 + * Version 0.3 Oct, 2017 + * + * NOTE: An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). See IR_LED + * + * WARN: This is very advanced & complicated example code. Not for beginners. + * You are strongly suggested to try & look at other example code first. + * + * # Instructions + * + * ## Before First Boot (i.e. Compile time) + * - Set the MQTT_SERVER define below to the address of your MQTT server. + * - Arduino IDE: + * o Install the following libraries via Library Manager + * - WiFiManager (https://github.com/tzapu/WiFiManager) + * - PubSubClient (https://pubsubclient.knolleary.net/) + * o You MUST change to have the following (or larger) value: + * #define MQTT_MAX_PACKET_SIZE 512 + * - PlatformIO IDE: + * If you are using PlatformIO, this should already been done for you in + * the accompanying platformio.ini file. + * + * ## First Boot (Initial setup) + * The ESP8266 board will boot into the WiFiManager's AP mode. + * i.e. It will create a WiFi Access Point with a SSID like: "ESP123456" etc. + * Connect to that SSID. Then point your browser to http://192.168.4.1/ and + * configure the ESP8266 to connect to your desired WiFi network. + * It will remember the new WiFi connection details on next boot. + * More information can be found here: + * https://github.com/tzapu/WiFiManager#how-it-works + * + * If you need to reset the WiFi settings, visit: + * http:///reset + * + * ## Normal Use (After setup) + * Enter 'http:///ir?type=7&code=E0E09966 + * http:///ir?type=4&code=0xf50&bits=12 + * http:///ir?code=C1A2E21D&repeats=8&type=19 + * http:///ir?type=31&code=40000,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1058 + * http:///ir?type=18&code=190B8050000000E0190B8070000010f0 + * http:///ir?repeats=1&type=25&code=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 + * + * or + * + * Send a MQTT message to the topic 'ir_server/send' using the following + * format (Order is important): + * protocol_num,hexcode e.g. 7,E0E09966 which is Samsung(7), Power On code, + * default bit size, default nr. of repeats. + * protocol_num,hexcode,bits e.g. 4,f50,12 which is Sony(4), Power Off code, + * 12 bits & default nr. of repeats. + * protocol_num,hexcode,bits,repeats e.g. 19,C1A2E21D,0,8 which is + * Sherwood(19), Vol Up, default bit size & + * repeated 8 times. + * 30,frequency,raw_string e.g. 30,38000,9000,4500,500,1500,500,750,500,750 + * Raw (30) @ 38kHz with a raw code of "9000,4500,500,1500,500,750,500,750" + * 31,code_string e.g. 31,40000,1,1,96,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,48,24,24,24,24,24,24,24,24,1058 + * 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 + * Kelvinator (18) Air Con on, Low Fan, 25 deg etc. + * 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. + * The optional bit size is in decimal. + * + * Unix command line usage example: + * # Install a MQTT client + * $ sudo apt install mosquitto-clients + * # Send a 32-bit NEC code of 0x1234abcd via MQTT. + * $ mosquitto_pub -h 10.20.0.253 -t ir_server/send -m '3,1234abcd,32' + * + * This server will send (back) what ever IR message it just transmitted to + * the MQTT topic 'ir_server/sent' to confirm it has been performed. This works + * for messages requested via MQTT or via HTTP. + * Note: Other status messages are also sent to 'ir_server/sent' from time to + * time. + * Unix command line usage example: + * # Listen to MQTT acknowledgements. + * $ mosquitto_sub -h 10.20.0.253 -t ir_server/sent + * + * If DEBUG is turned on, there is additional information printed on the Serial + * Port. + * + * ## Updates + * You can upload new firmware over the air (OTA) via the form on the device's + * main page. No need to connect to the device again via USB. \o/ + * Your WiFi settings should be remembered between updates. \o/ \o/ + * + * Copyright Notice: + * Code for this has been borrowed from lots of other OpenSource projects & + * resources. I'm *NOT* claiming complete Copyright ownership of all the code. + * Likewise, feel free to borrow from this as much as you want. + */ + +#define MQTT_ENABLE // Comment this out if you don't want to use MQTT at all. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef MQTT_ENABLE +// -------------------------------------------------------------------- +// * * * IMPORTANT * * * +// You must change to have the following value. +// #define MQTT_MAX_PACKET_SIZE 512 +// -------------------------------------------------------------------- +#include +#endif // MQTT_ENABLE +#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. + +#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. +// 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. + +#define MQTTprefix "ir_server" +#define MQTTack MQTTprefix "/sent" // Topic we send back acknowledgements on +#define MQTTcommand MQTTprefix "/send" // Topic we get new commands from. +#endif // MQTT_ENABLE + +// HTML arguments we will parse for IR code information. +#define argType "type" +#define argData "code" +#define argBits "bits" +#define argRepeat "repeats" +#define DEBUG True + +// Globals +ESP8266WebServer server(HTTP_PORT); +IRsend irsend = IRsend(IR_LED); +MDNSResponder mdns; +WiFiClient espClient; +WiFiManager wifiManager; + +uint16_t *codeArray; +uint32_t lastReconnectAttempt = 0; // MQTT last attemps reconnection number +bool boot = true; +bool ir_lock = false; // Primative locking for gating the IR LED. + +#ifdef MQTT_ENABLE +// MQTT client parameters +void callback(char* topic, byte* payload, unsigned int length); +PubSubClient mqtt_client(MQTT_SERVER, MQTT_PORT, callback, espClient); +// Create a unique MQTT client id. +const char* mqtt_clientid = String(MQTTprefix + + String(ESP.getChipId(), HEX)).c_str(); +#endif // MQTT_ENABLE + +// Debug messages get sent to the serial port. +void debug(String str) { +#ifdef DEBUG + uint32_t now = millis(); + Serial.printf("%07u.%03u: %s\n", now / 1000, now % 1000, str.c_str()); +#endif // DEBUG +} + +// Root web page with example usage etc. +void handleRoot() { + server.send(200, "text/html", + "IR MQTT server" + "" + "

ESP8266 IR MQTT Server

" + "

" + "

Connection details

" + "

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

" +#ifdef MQTT_ENABLE + "

MQTT server: " MQTT_SERVER ":" + String(MQTT_PORT) + " ("+ + (mqtt_client.connected() ? "Connected" : "Disconnected") + ")
" + "Command topic: " MQTTcommand "
" + "Acknowledgements topic: " MQTTack "

" +#endif // MQTT_ENABLE + "

" + "

Hardcoded examples

" + "

" + "Sherwood Amp On (GlobalCache)

" + "

" + "Sherwood Amp Off (Raw)

" + "

" + "Sherwood Amp Input TAPE (Pronto)

" + "

TV on (Samsung)

" + "

Power Off (Sony 12bit)

" + "

" + "

Send a simple IR message

" + "

" + "Type: " + "" + " Code: 0x" + " Bit size: " + "" + " Repeats: " + " " + "
" + "

" + "

Send an IRremote Raw IR message

" + "

" + "" + "String: (freq,array data) " + " " + "
" + "

" + "

Send a GlobalCache" + " IR message

" + "

" + "" + "String: 1:1,1," + " " + "
" + "

" + "

Send a Pronto code IR message

" + "

" + "" + "String (comma separated): " + " Repeats: " + " " + "
" + "

" + "

Send a Kelvinator A/C IR message

" + "

" + "" + "State code: 0x" + " " + "
" + "

" + "

Update IR Server firmware

" + "Warning:
" + "Updating your firmware may screw up your access to the device. " + "If you are going to use this, know what you are doing first " + "(and you probably do).
" + "

" + "Firmware to upload: " + "" + "
" + ""); +} + +// Reset web page +void handleReset() { + server.send(200, "text/html", + "Reset Config" + "" + "

Resetting the WiFiManager config back to defaults.

" + "

Device restarting. Try connecting in a few seconds.

" + ""); + // Do the reset. + wifiManager.resetSettings(); + delay(10); + ESP.restart(); + 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}; + 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; + if (isxdigit(c)) { + if (isdigit(c)) + codeArray[i / 2] += c - '0'; + else + codeArray[i / 2] += c - 'a' + 10; + } + if (i % 2 == 0) + codeArray[i / 2] <<= 4; + } + irsend.sendKelvinator(reinterpret_cast(codeArray)); +} + +// Count how many values are in the String. +// Args: +// str: String containing the values. +// sep: Character that separates the values. +// Returns: +// The number of values found in the String. +uint16_t countValuesInStr(const String str, char sep) { + int16_t index = -1; + uint16_t count = 1; + do { + index = str.indexOf(sep, index + 1); + count++; + } while (index != -1); + return count; +} + +// Dynamically allocate an array of uint16_t's. +// Args: +// size: Nr. of uint16_t's need to be in the new array. +// Returns: +// A Ptr to the new array. Restarts the ESP8266 if it fails. +uint16_t * newCodeArray(const uint16_t size) { + uint16_t *result; + + result = reinterpret_cast(malloc(size * sizeof(uint16_t))); + // Check we malloc'ed successfully. + if (result == NULL) { // malloc failed, so give up. + Serial.printf("\nCan't allocate %d bytes. (%d bytes free)\n", + size * sizeof(uint16_t), ESP.getFreeHeap()); + Serial.println("Giving up & forcing a reboot."); + ESP.restart(); // Reboot. + delay(500); // Wait for the restart to happen. + return result; // Should never get here, but just in case. + } + return result; +} + +// Parse a GlobalCache String/code and send it. +// Args: +// str: A GlobalCache formatted String of comma separated numbers. +// e.g. "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" +// Note: The leading "1:1,1," of normal GC codes should be removed. +void parseStringAndSendGC(const String str) { + uint16_t count; + uint16_t *code_array; + String tmp_str; + + // Remove the leading "1:1,1," if present. + if (str.startsWith("1:1,1,")) + tmp_str = str.substring(6); + else + tmp_str = str; + + // Find out how many items there are in the string. + count = countValuesInStr(tmp_str, ','); + + // Now we know how many there are, allocate the memory to store them all. + code_array = newCodeArray(count); + + // Now convert the strings to integers and place them in code_array. + count = 0; + uint16_t start_from = 0; + int16_t index = -1; + do { + index = tmp_str.indexOf(',', start_from); + code_array[count] = tmp_str.substring(start_from, index).toInt(); + start_from = index + 1; + count++; + } while (index != -1); + + irsend.sendGC(code_array, count); // All done. Send it. + free(code_array); // Free up the memory allocated. +} + +// Parse a Pronto Hex String/code and send it. +// Args: +// str: A comma-separated String of nr. of repeats, then hexidecimal 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. +// 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) { + uint16_t count; + uint16_t *code_array; + int16_t index = -1; + uint16_t start_from = 0; + + // Find out how many items there are in the string. + count = countValuesInStr(str, ','); + + // Check if we have the optional embedded repeats value in the code string. + if (str.startsWith("R") || str.startsWith("r")) { + // Grab the first value from the string, as it is the nr. of repeats. + index = str.indexOf(',', start_from); + repeats = str.substring(start_from + 1, index).toInt(); // Skip the 'R'. + start_from = index + 1; + 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; + + // Now we know how many there are, allocate the memory to store them all. + code_array = newCodeArray(count); + + // Rest of the string are values for the code array. + // Now convert the hex strings to integers and place them in code_array. + count = 0; + do { + index = str.indexOf(',', start_from); + // Convert the hexidecimal value string to an unsigned integer. + code_array[count] = strtoul(str.substring(start_from, index).c_str(), + NULL, 16); + start_from = index + 1; + count++; + } while (index != -1); + + irsend.sendPronto(code_array, count, repeats); // All done. Send it. + free(code_array); // Free up the memory allocated. +} + +// Parse a 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) { + uint16_t count; + uint16_t freq = 38000; // Default to 38kHz. + uint16_t *raw_array; + + // Find out how many items there are in the string. + count = countValuesInStr(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; + 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. + raw_array = newCodeArray(count); + + // Grab the first value from the string, as it is the frequency. + int16_t index = str.indexOf(',', 0); + freq = str.substring(0, index).toInt(); + uint16_t start_from = index + 1; + // Rest of the string are values for the raw array. + // Now convert the strings to integers and place them in raw_array. + count = 0; + do { + index = str.indexOf(',', start_from); + raw_array[count] = str.substring(start_from, index).toInt(); + start_from = index + 1; + count++; + } while (index != -1); + + irsend.sendRaw(raw_array, count, freq); // All done. Send it. + free(raw_array); // Free up the memory allocated. +} + +// Parse the URL args to find the IR code. +void handleIr() { + uint64_t data = 0; + String data_str = ""; + int ir_type = 3; // Default to NEC codes. + uint16_t nbits = 0; + uint16_t repeat = 0; + + for (uint16_t i = 0; i < server.args(); i++) { + if (server.argName(i) == argType) + ir_type = atoi(server.arg(i).c_str()); + if (server.argName(i) == argData) { + data = getUInt64fromHex(server.arg(i).c_str()); + data_str = server.arg(i); + } + if (server.argName(i) == argBits) + nbits = atoi(server.arg(i).c_str()); + if (server.argName(i) == argRepeat) + repeat = atoi(server.arg(i).c_str()); + } + debug("New code received via HTTP"); + sendIRCode(ir_type, data, data_str.c_str(), nbits, repeat); + handleRoot(); +} + +void handleNotFound() { + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET)?"GET":"POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i=0; i < server.args(); i++) + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + server.send(404, "text/plain", message); +} + +void setup_wifi() { + delay(10); + // We start by connecting to a WiFi network + + wifiManager.setTimeout(300); // Time out after 5 mins. + if (!wifiManager.autoConnect()) { + debug("Wifi failed to connect and hit timeout."); + delay(3000); + // Reboot. A.k.a. "Have you tried turning it Off and On again?" + ESP.reset(); + delay(5000); + } + + debug("WiFi connected. IP address: " + WiFi.localIP()); +} + +void setup(void) { + irsend.begin(); + + #ifdef DEBUG + Serial.begin(115200); + #endif // DEBUG + + setup_wifi(); + + // Wait a bit for things to settle. + delay(1500); + + lastReconnectAttempt = 0; + + if (mdns.begin(MQTTprefix, WiFi.localIP())) { + debug("MDNS responder started"); + } + + // Setup the root web page. + server.on("/", handleRoot); + // Setup the page to handle web-based IR codes. + server.on("/ir", handleIr); + // Setup a reset page to cause WiFiManager information to be reset. + server.on("/reset", handleReset); + + // Setup the URL to allow Over-The-Air (OTA) firmware updates. + server.on("/update", HTTP_POST, [](){ + server.sendHeader("Connection", "close"); + server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK"); + ESP.restart(); + }, [](){ + HTTPUpload& upload = server.upload(); + if (upload.status == UPLOAD_FILE_START) { + WiFiUDP::stopAll(); + debug("Update: " + upload.filename); + uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & + 0xFFFFF000; + if (!Update.begin(maxSketchSpace)) { // start with max available size +#ifdef DEBUG + Update.printError(Serial); +#endif // DEBUG + } + } else if (upload.status == UPLOAD_FILE_WRITE) { + if (Update.write(upload.buf, upload.currentSize) != + upload.currentSize) { +#ifdef DEBUG + Update.printError(Serial); +#endif // DEBUG + } + } else if (upload.status == UPLOAD_FILE_END) { + if (Update.end(true)) { // true to set the size to the current progress + debug("Update Success: " + (String) upload.totalSize + + "\nRebooting..."); + } + } + yield(); + }); + + // Set up an error page. + server.onNotFound(handleNotFound); + + server.begin(); + debug("HTTP server started"); +} + +#ifdef MQTT_ENABLE +// MQTT subscribing to topic +void subscribing(const String topic_name) { + // subscription to topic for receiving data + if (mqtt_client.subscribe(topic_name.c_str())) { + debug("Subscription OK to " + topic_name); + } +} + +bool reconnect() { + // Loop a few times or until we're reconnected + uint16_t tries = 1; + while (!mqtt_client.connected() && tries <= 3) { + int connected = false; + // Attempt to connect + debug("Attempting MQTT connection to " MQTT_SERVER ":" + String(MQTT_PORT) + + "... "); + if (mqtt_user && mqtt_password) + connected = mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_password); + else + connected = mqtt_client.connect(mqtt_clientid); + if (connected) { + // Once connected, publish an announcement... + mqtt_client.publish(MQTTack, "Connected"); + debug("connected."); + // Subscribing to topic(s) + subscribing(MQTTcommand); + } else { + debug("failed, rc=" + String(mqtt_client.state()) + + " Try again in a bit."); + // Wait for a bit before retrying + delay(tries << 7); // Linear increasing back-off (x128) + } + tries++; + } + return mqtt_client.connected(); +} +#endif // MQTT_ENABLE + +void loop(void) { + server.handleClient(); + +#ifdef MQTT_ENABLE + // 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) { + lastReconnectAttempt = now; + debug("client mqtt not connected, trying to connect"); + // Attempt to reconnect + if (reconnect()) { + lastReconnectAttempt = 0; + if (boot) { + mqtt_client.publish(MQTTack, "IR Server just booted"); + boot = false; + } else { + mqtt_client.publish(MQTTack, "IR Server just (re)connected to MQTT"); + } + } + } + } else { + // MQTT loop + mqtt_client.loop(); + } +#endif // MQTT_ENABLE + delay(100); +} + +// Arduino framework doesn't support strtoull(), so make our own one. +uint64_t getUInt64fromHex(char const *str) { + uint64_t result = 0; + uint16_t offset = 0; + // Skip any leading '0x' or '0X' prefix. + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + offset = 2; + for (; isxdigit((unsigned char)str[offset]); offset++) { + char c = str[offset]; + result *= 16; + if (isdigit(c)) /* '0' .. '9' */ + result += c - '0'; + else if (isupper(c)) /* 'A' .. 'F' */ + result += c - 'A' + 10; + else /* 'a' .. 'f'*/ + result += c - 'a' + 10; + } + return result; +} + +// Transmit the given IR message. +// +// Args: +// ir_type: enum of the protocol to be sent. +// code: Numeric payload of the IR message. Most protocols use this. +// 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, + 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; + + // send the IR message. + switch (ir_type) { + case RC5: // 1 + if (bits == 0) + bits = RC5_BITS; + irsend.sendRC5(code, bits, repeat); + break; + case RC6: // 2 + if (bits == 0) + bits = RC6_MODE0_BITS; + irsend.sendRC6(code, bits, repeat); + break; + case NEC: // 3 + if (bits == 0) + bits = NEC_BITS; + irsend.sendNEC(code, bits, repeat); + break; + case SONY: // 4 + if (bits == 0) + bits = SONY_12_BITS; + repeat = std::max(repeat, (uint16_t) SONY_MIN_REPEAT); + irsend.sendSony(code, bits, repeat); + break; + case PANASONIC: // 5 + if (bits == 0) + bits = PANASONIC_BITS; + irsend.sendPanasonic64(code, bits, repeat); + break; + case JVC: // 6 + if (bits == 0) + bits = JVC_BITS; + irsend.sendJVC(code, bits, repeat); + break; + case SAMSUNG: // 7 + if (bits == 0) + bits = SAMSUNG_BITS; + irsend.sendSAMSUNG(code, bits, repeat); + break; + case WHYNTER: // 8 + if (bits == 0) + bits = WHYNTER_BITS; + irsend.sendWhynter(code, bits, repeat); + break; + case AIWA_RC_T501: // 9 + if (bits == 0) + bits = AIWA_RC_T501_BITS; + repeat = std::max(repeat, (uint16_t) AIWA_RC_T501_MIN_REPEAT); + irsend.sendAiwaRCT501(code, bits, repeat); + break; + case LG: // 10 + if (bits == 0) + bits = LG_BITS; + irsend.sendLG(code, bits, repeat); + break; + case MITSUBISHI: // 12 + if (bits == 0) + bits = MITSUBISHI_BITS; + repeat = std::max(repeat, (uint16_t) MITSUBISHI_MIN_REPEAT); + irsend.sendMitsubishi(code, bits, repeat); + break; + case DISH: // 13 + if (bits == 0) + bits = DISH_BITS; + repeat = std::max(repeat, (uint16_t) DISH_MIN_REPEAT); + irsend.sendDISH(code, bits, repeat); + break; + case SHARP: // 14 + if (bits == 0) + bits = SHARP_BITS; + irsend.sendSharpRaw(code, bits, repeat); + break; + case COOLIX: // 15 + if (bits == 0) + bits = COOLIX_BITS; + irsend.sendCOOLIX(code, bits, repeat); + break; + case DENON: // 17 + if (bits == 0) + bits = DENON_BITS; + irsend.sendDenon(code, bits, repeat); + break; + case KELVINATOR: // 18 + parseStringAndSendKelv(code_str); + break; + case SHERWOOD: // 19 + if (bits == 0) + bits = SHERWOOD_BITS; + repeat = std::max(repeat, (uint16_t) SHERWOOD_MIN_REPEAT); + irsend.sendSherwood(code, bits, repeat); + break; + case RCMM: // 21 + if (bits == 0) + bits == RCMM_BITS; + irsend.sendRCMM(code, bits, repeat); + break; + case SANYO_LC7461: // 22 + if (bits == 0) + bits = SANYO_LC7461_BITS; + irsend.sendSanyoLC7461(code, bits, repeat); + break; + case RC5X: // 23 + if (bits == 0) + bits = RC5X_BITS; + irsend.sendRC5(code, bits, repeat); + case PRONTO: // 25 + parseStringAndSendPronto(code_str, repeat); + break; + case NIKAI: // 29 + if (bits == 0) + bits = NIKAI_BITS; + irsend.sendNikai(code, bits, repeat); + break; + case RAW: // 30 + parseStringAndSendRaw(code_str); + break; + case GLOBALCACHE: // 31 + parseStringAndSendGC(code_str); + break; + } + + // Release the lock. + ir_lock = false; + + // Indicate that we sent the message. + debug("Sent the 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. +#ifdef MQTT_ENABLE + if (ir_type == PRONTO && repeat > 0) + mqtt_client.publish(MQTTack, (String(ir_type) + ",R" + + String(repeat) + "," + + String(code_str)).c_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)); + +#ifdef MQTT_ENABLE + mqtt_client.publish(MQTTack, (String(ir_type) + "," + + uint64ToString(code, 16) + + "," + String(bits) + "," + + String(repeat)).c_str()); +#endif // MQTT_ENABLE + } +} + +#ifdef MQTT_ENABLE +void receivingMQTT(String const topic_name, String const callback_str) { + char* tok_ptr; + uint64_t code = 0; + uint16_t nbits = 0; + uint16_t repeat = 0; + + debug("Receiving data by MQTT topic " + topic_name); + + // Make a copy of the callback string as strtok destorys it. + char* callback_c_str = strdup(callback_str.c_str()); + debug("MQTT Payload (raw): " + callback_str); + + // Get the numeric protocol type. + int ir_type = strtoul(strtok_r(callback_c_str, ",", &tok_ptr), NULL, 10); + char* next = strtok_r(NULL, ",", &tok_ptr); + // If there is unparsed string left, try to convert it assuming it's hex. + if (next != NULL) { + code = getUInt64fromHex(next); + next = strtok_r(NULL, ",", &tok_ptr); + } else { + // We require at least two value in the string. Give up. + return; + } + // If there is still string left, assume it is the bit size. + if (next != NULL) { + nbits = atoi(next); + next = strtok_r(NULL, ",", &tok_ptr); + } + // If there is still string left, assume it is the repeat count. + if (next != NULL) + repeat = atoi(next); + + free(callback_c_str); + + + // send received MQTT value by IR signal + 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 +// subscribed this function is called +void callback(char* topic, byte* payload, unsigned int length) { + // In order to republish this payload, a copy must be made + // as the orignal payload buffer will be overwritten whilst + // constructing the PUBLISH packet. + // Allocate the correct amount of memory for the payload copy + byte* payload_copy = reinterpret_cast(malloc(length + 1)); + // Copy the payload to the new buffer + memcpy(payload_copy, payload, length); + + // Conversion to a printable string + payload_copy[length] = '\0'; + String callback_string = String(reinterpret_cast(payload_copy)); + String topic_name = String(reinterpret_cast(topic)); + + // launch the function to treat received data + receivingMQTT(topic_name, callback_string); + + // Free the memory + free(payload_copy); +} +#endif // MQTT_ENABLE diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini new file mode 100644 index 000000000..c87e56962 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRMQTTServer/platformio.ini @@ -0,0 +1,28 @@ +[platformio] +lib_extra_dirs = ../../ +src_dir=. + +[common] +build_flags = -DMQTT_MAX_PACKET_SIZE=512 +lib_deps_builtin = +lib_deps_external = + PubSubClient + WifiManager@0.12 + +[env:nodemcuv2] +platform = espressif8266 +framework = arduino +board = nodemcuv2 +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} + +[env:d1_mini] +platform=espressif8266 +framework=arduino +board=d1_mini +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/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino new file mode 100644 index 000000000..82f2e7dd7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/IRServer.ino @@ -0,0 +1,121 @@ +/* + * IRremoteESP8266: IRServer - demonstrates sending IR codes controlled from a webserver + * Version 0.2 June, 2017 + * Copyright 2015 Mark Szabo + * + * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). + * + * 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 +#include +#include +#include + +const char* ssid = "....."; +const char* password = "....."; +MDNSResponder mdns; + +ESP8266WebServer server(80); + +IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) + +void handleRoot() { + server.send(200, "text/html", + "" \ + "ESP8266 Demo" \ + "" \ + "

Hello from ESP8266, you can send NEC encoded IR" \ + "signals from here!

" \ + "

Send 0xFFE01F

" \ + "

Send 0xFAB123

" \ + "

Send 0xFFE896

" \ + "" \ + ""); +} + +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); + irsend.sendNEC(code, 32); + } + } + handleRoot(); +} + +void handleNotFound() { + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET)?"GET":"POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + server.send(404, "text/plain", message); +} + +void setup(void) { + irsend.begin(); + + Serial.begin(115200); + WiFi.begin(ssid, password); + Serial.println(""); + + // Wait for connection + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.print("Connected to "); + Serial.println(ssid); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + if (mdns.begin("esp8266", WiFi.localIP())) { + Serial.println("MDNS responder started"); + } + + server.on("/", handleRoot); + server.on("/ir", handleIr); + + server.on("/inline", [](){ + server.send(200, "text/plain", "this works as well"); + }); + + server.onNotFound(handleNotFound); + + server.begin(); + Serial.println("HTTP server started"); +} + +void loop(void) { + server.handleClient(); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRServer/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/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino new file mode 100644 index 000000000..ae9ed66f9 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/IRrecvDemo.ino @@ -0,0 +1,44 @@ +/* + * IRremoteESP8266: IRrecvDemo - demonstrates receiving IR codes with IRrecv + * An IR detector/demodulator must be connected to the input RECV_PIN. + * Copyright 2009 Ken Shirriff, http://arcfn.com + * Example circuit diagram: + * https://github.com/markszabo/IRremoteESP8266/wiki#ir-receiving + * Changes: + * Version 0.2 June, 2017 + * Changed GPIO pin to the same as other examples. + * Used our own method for printing a uint64_t. + * Changed the baud rate to 115200. + * Version 0.1 Sept, 2015 + * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009 + */ + +#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; + +IRrecv irrecv(RECV_PIN); + +decode_results results; + +void setup() { + Serial.begin(115200); + irrecv.enableIRIn(); // Start the receiver +} + +void loop() { + if (irrecv.decode(&results)) { + // print() & println() can't handle printing long longs. (uint64_t) + serialPrintUint64(results.value, HEX); + Serial.println(""); + irrecv.resume(); // Receive the next value + } + delay(100); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDemo/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/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino new file mode 100644 index 000000000..856449695 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/IRrecvDump.ino @@ -0,0 +1,104 @@ +/* + * IRremoteESP8266: IRrecvDump - dump details of IR codes with IRrecv + * Copyright 2009 Ken Shirriff, http://arcfn.com + * + ***** DEPRECATED - DO NOT USE ***** + * Unless you know what you are doing, you should be using the + * IRrecvDumpV2.ino sketch/example instead for capturing & decoding IR messages. + * In almost ALL ways it is BETTER, FASTER, and MORE DETAILED. + * + * This code is left only for legacy reasons, and as another simple example of + * how to use the IRremoteESP8266 library. + * + * As of November 2017 it will no longer be updated or supported. + * You have been warned. + ***** DEPRECATED - DO NOT USE ***** + * + * An IR detector/demodulator must be connected to the input RECV_PIN. + * Version 0.2 Oct 2017 + * Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009, + * 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) + */ + +#ifndef UNIT_TEST +#include +#endif +#include +#include +#include + +// an IR detector/demodulator is connected to GPIO pin 2 +uint16_t RECV_PIN = 2; + +IRrecv irrecv(RECV_PIN); + +decode_results results; + +void setup() { + Serial.begin(115200); + irrecv.enableIRIn(); // Start the receiver +} + +void dump(decode_results *results) { + // Dumps out the decode_results structure. + // Call this after IRrecv::decode() + uint16_t count = results->rawlen; + if (results->decode_type == UNKNOWN) { + Serial.print("Unknown encoding: "); + } else if (results->decode_type == NEC) { + Serial.print("Decoded NEC: "); + } else if (results->decode_type == SONY) { + Serial.print("Decoded SONY: "); + } else if (results->decode_type == RC5) { + Serial.print("Decoded RC5: "); + } else if (results->decode_type == RC5X) { + Serial.print("Decoded RC5X: "); + } else if (results->decode_type == RC6) { + Serial.print("Decoded RC6: "); + } else if (results->decode_type == RCMM) { + Serial.print("Decoded RCMM: "); + } else if (results->decode_type == PANASONIC) { + Serial.print("Decoded PANASONIC - Address: "); + Serial.print(results->address, HEX); + Serial.print(" Value: "); + } else if (results->decode_type == LG) { + Serial.print("Decoded LG: "); + } else if (results->decode_type == JVC) { + Serial.print("Decoded JVC: "); + } else if (results->decode_type == AIWA_RC_T501) { + Serial.print("Decoded AIWA RC T501: "); + } else if (results->decode_type == WHYNTER) { + Serial.print("Decoded Whynter: "); + } else if (results->decode_type == NIKAI) { + Serial.print("Decoded Nikai: "); + } + serialPrintUint64(results->value, 16); + Serial.print(" ("); + Serial.print(results->bits, DEC); + Serial.println(" bits)"); + Serial.print("Raw ("); + Serial.print(count, DEC); + Serial.print("): {"); + + for (uint16_t i = 1; i < count; i++) { + if (i % 100 == 0) + yield(); // Preemptive yield every 100th entry to feed the WDT. + if (i & 1) { + Serial.print(results->rawbuf[i] * RAWTICK, DEC); + } else { + Serial.print(", "); + Serial.print((uint32_t) results->rawbuf[i] * RAWTICK, DEC); + } + } + Serial.println("};"); +} + +void loop() { + if (irrecv.decode(&results)) { + dump(&results); + Serial.println("DEPRECATED: Please use IRrecvDumpV2.ino instead!"); + irrecv.resume(); // Receive the next value + } +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDump/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/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino new file mode 100644 index 000000000..bb86a5f9d --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -0,0 +1,199 @@ +/* + * 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/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRrecvDumpV2/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/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino new file mode 100644 index 000000000..1a688cba3 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/IRsendDemo.ino @@ -0,0 +1,62 @@ +/* IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend. + * + * Version 1.0 April, 2017 + * 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). + * + * 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 + +IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) + +// Example of data captured by IRrecvDumpV2.ino +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}; + +void setup() { + irsend.begin(); + Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); +} + +void loop() { + Serial.println("NEC"); + irsend.sendNEC(0x00FFE01FUL, 32); + delay(2000); + Serial.println("Sony"); + irsend.sendSony(0xa90, 12, 2); + delay(2000); + Serial.println("a rawData capture from IRrecvDumpV2"); + irsend.sendRaw(rawData, 67, 38); // Send a raw data capture at 38kHz. + delay(2000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendDemo/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/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino new file mode 100644 index 000000000..0a7a014a7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/IRsendProntoDemo.ino @@ -0,0 +1,105 @@ +/* IRremoteESP8266: IRsendProntoDemo + * Copyright 2017 David Conran + * + * Demonstrates sending Pronto codes with IRsend. + * + * Version 1.0 June, 2017 + * + * An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2), unless you + * change the irsend() value 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 + +IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) + +// Panasonic Plasma TV Descrete code (Power On). +// Acquired from: +// https://irdb.globalcache.com/ +// e.g. +// 0000 006D 0000 0022 00ac 00ac 0016 0040 0016 0040 0016 0040 0016 0015 0016 +// 0015 0016 0015 0016 0015 0016 0015 0016 0040 0016 0040 0016 0040 0016 0015 +// 0016 0015 0016 0015 0016 0015 0016 0015 0016 0040 0016 0015 0016 0015 0016 +// 0040 0016 0040 0016 0015 0016 0015 0016 0040 0016 0015 0016 0040 0016 0040 +// 0016 0015 0016 0015 0016 0040 0016 0040 0016 0015 0016 071c +// +// Or the equiv. of sendSamsung(0xE0E09966); +uint16_t samsungProntoCode[72] = { + 0x0000, 0x006D, 0x0000, 0x0022, + 0x00ac, 0x00ac, 0x0016, 0x0040, 0x0016, 0x0040, 0x0016, 0x0040, + 0x0016, 0x0015, 0x0016, 0x0015, 0x0016, 0x0015, 0x0016, 0x0015, + 0x0016, 0x0015, 0x0016, 0x0040, 0x0016, 0x0040, 0x0016, 0x0040, + 0x0016, 0x0015, 0x0016, 0x0015, 0x0016, 0x0015, 0x0016, 0x0015, + 0x0016, 0x0015, 0x0016, 0x0040, 0x0016, 0x0015, 0x0016, 0x0015, + 0x0016, 0x0040, 0x0016, 0x0040, 0x0016, 0x0015, 0x0016, 0x0015, + 0x0016, 0x0040, 0x0016, 0x0015, 0x0016, 0x0040, 0x0016, 0x0040, + 0x0016, 0x0015, 0x0016, 0x0015, 0x0016, 0x0040, 0x0016, 0x0040, + 0x0016, 0x0015, 0x0016, 0x071c +}; + +// Panasonic Plasma TV Descrete code (Power On). +// Acquired from: +// ftp://ftp.panasonic.com/pub/panasonic/drivers/monitors/Discrete-remote-control-codesProntoCCFformat.pdf +// e.g. +// 0000 0071 0000 0032 0080 003F 0010 0010 0010 0030 0010 0010 0010 0010 0010 +// 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 +// 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 +// 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 +// 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 +// 0030 0010 0030 0010 0030 0010 0030 0010 0010 0010 0010 0010 0010 0010 0030 +// 0010 0030 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0A98 +// +// Or the equiv. of sendPanasonic64(0x400401007C7D); +uint16_t panasonicProntoCode[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}; + +void setup() { + irsend.begin(); + Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY); +} + +void loop() { + 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); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/IRsendProntoDemo/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/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino new file mode 100644 index 000000000..9c7068000 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino @@ -0,0 +1,56 @@ +/* + * IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend + * Version 0.1 June, 2015 + * 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). + * + * 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 + +#define PanasonicAddress 0x4004 // Panasonic address (Pre data) +#define PanasonicPower 0x100BCBD // Panasonic Power button + +#define JVCPower 0xC5E8 + +IRsend irsend(4); // An IR LED is controlled by GPIO pin 4 (D2) + +void setup() { + irsend.begin(); +} + +void loop() { + // This should turn your TV on and off + irsend.sendPanasonic(PanasonicAddress, PanasonicPower); + + 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); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/JVCPanasonicSendDemo/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/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino new file mode 100644 index 000000000..7cced0c88 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/LGACSend/LGACSend.ino @@ -0,0 +1,259 @@ +// Copyright 2015 chaeplin +// Copyright 2017 xpokor22 +// This is based on: +// https://github.com/z3t0/Arduino-IRremote/blob/master/examples/LGACSendDemo/LGACSendDemo.ino + +#include +#include + + +IRsend irsend(14); // An IR LED is controlled by GPIO pin 14 (D5) + +// 0 : TOWER +// 1 : WALL +const unsigned int kAc_Type = 1; + +// 0 : cooling +// 1 : heating +unsigned int ac_heat = 1; + +// 0 : off +// 1 : on +unsigned int ac_power_on = 0; + +// 0 : off +// 1 : on --> power on +unsigned int ac_air_clean_state = 0; + +// temperature : 18 ~ 30 +unsigned int ac_temperature = 24; + +// 0 : low +// 1 : mid +// 2 : high +// if kAc_Type = 1, 3 : change +unsigned int ac_flow = 0; + +const uint8_t kAc_Flow_Tower[3] = {0, 4, 6}; +const uint8_t kAc_Flow_Wall[4] = {0, 2, 4, 5}; + +uint32_t ac_code_to_sent; + +void Ac_Send_Code(uint32_t code) { + Serial.print("code to send : "); + Serial.print(code, BIN); + Serial.print(" : "); + Serial.println(code, HEX); + + irsend.sendLG(code, 28); +} + +void Ac_Activate(unsigned int temperature, unsigned int air_flow, + unsigned int heat) { + ac_heat = heat; + unsigned int ac_msbits1 = 8; + unsigned int ac_msbits2 = 8; + unsigned int ac_msbits3 = 0; + unsigned int ac_msbits4; + if (ac_heat == 1) + ac_msbits4 = 4; // heating + else + ac_msbits4 = 0; // cooling + unsigned int ac_msbits5 = (temperature < 15) ? 0 : temperature - 15; + unsigned int ac_msbits6; + + if (0 <= air_flow && air_flow <= 2) { + if (kAc_Type == 0) + ac_msbits6 = kAc_Flow_Tower[air_flow]; + else + ac_msbits6 = kAc_Flow_Wall[air_flow]; + } + + // calculating using other values + unsigned int ac_msbits7 = (ac_msbits3 + ac_msbits4 + ac_msbits5 + + ac_msbits6) & B00001111; + ac_code_to_sent = ac_msbits1 << 4; + ac_code_to_sent = (ac_code_to_sent + ac_msbits2) << 4; + ac_code_to_sent = (ac_code_to_sent + ac_msbits3) << 4; + ac_code_to_sent = (ac_code_to_sent + ac_msbits4) << 4; + ac_code_to_sent = (ac_code_to_sent + ac_msbits5) << 4; + ac_code_to_sent = (ac_code_to_sent + ac_msbits6) << 4; + ac_code_to_sent = (ac_code_to_sent + ac_msbits7); + + Ac_Send_Code(ac_code_to_sent); + + ac_power_on = 1; + ac_temperature = temperature; + ac_flow = air_flow; +} + +void Ac_Change_Air_Swing(int air_swing) { + if (kAc_Type == 0) { + if (air_swing == 1) + ac_code_to_sent = 0x881316B; + else + ac_code_to_sent = 0x881317C; + } else { + if (air_swing == 1) + ac_code_to_sent = 0x8813149; + else + ac_code_to_sent = 0x881315A; + } + Ac_Send_Code(ac_code_to_sent); +} + +void Ac_Power_Down() { + ac_code_to_sent = 0x88C0051; + + Ac_Send_Code(ac_code_to_sent); + + ac_power_on = 0; +} + +void Ac_Air_Clean(int air_clean) { + if (air_clean == '1') + ac_code_to_sent = 0x88C000C; + else + ac_code_to_sent = 0x88C0084; + + Ac_Send_Code(ac_code_to_sent); + + ac_air_clean_state = air_clean; +} + +void setup() { + Serial.begin(115200); + delay(1000); + irsend.begin(); +} + +void loop() { + char b; + Serial.println("# a : mode or temp b : air_flow, temp, swing, clean," + " cooling/heating"); + Serial.println("# 0 : off 0"); + Serial.println("# 1 : on 0"); + Serial.println("# 2 : air_swing 0 or 1"); + Serial.println("# 3 : air_clean 0 or 1"); + Serial.println("# 4 : air_flow 0 ~ 2 : flow"); + Serial.println("# + : temp + 1"); + Serial.println("# - : temp - 1"); + Serial.println("# c : cooling"); + Serial.println("# h : heating"); + Serial.println("# m : change cooling to air clean, air clean to cooling"); + + Serial.println("a="); // Prompt User for input + while (Serial.available() == 0) { // Wait for user input + } + char a = Serial.read(); // Read user input into a + switch (a) { + case '0': + case '1': + case '+': + case '-': + case 'c': + case 'h': + case 'm': + break; + default: + Serial.println("b="); // Prompt User for input + while (Serial.available() == 0) {} + char b = Serial.read(); + } + + /* + # a : mode or temp b : air_flow, temp, swing, clean, cooling/heating + # 18 ~ 30 : temp 0 ~ 2 : flow // on + # 0 : off 0 + # 1 : on 0 + # 2 : air_swing 0 or 1 + # 3 : air_clean 0 or 1 + # 4 : air_flow 0 ~ 3 : flow + # + : temp + 1 + # - : temp - 1 + # c : cooling + # h : heating + # m : change cooling to air clean, air clean to cooling + */ + Serial.print("a : "); + Serial.print(a); + Serial.print(" b : "); + Serial.println(b); + + switch (a) { + case '0': // off + Ac_Power_Down(); + break; + case '1': // on + Ac_Activate(ac_temperature, ac_flow, ac_heat); + break; + case '2': + if (b == '0') + Ac_Change_Air_Swing(0); + else + Ac_Change_Air_Swing(1); + break; + case '3': // 1 : clean on, power on + if (b == '0' | b == '1') + Ac_Air_Clean(b); + break; + case '4': + switch (b) { + case '1': + Ac_Activate(ac_temperature, 1, ac_heat); + break; + case '2': + Ac_Activate(ac_temperature, 2, ac_heat); + break; + case '3': + Ac_Activate(ac_temperature, 3, ac_heat); + break; + default: + Ac_Activate(ac_temperature, 0, ac_heat); + } + break; + case '+': + if (18 <= ac_temperature && ac_temperature <= 29) + Ac_Activate((ac_temperature + 1), ac_flow, ac_heat); + break; + case '-': + if (19 <= ac_temperature && ac_temperature <= 30) + Ac_Activate((ac_temperature - 1), ac_flow, ac_heat); + break; + case 'c': + ac_heat = 0; + Ac_Activate(ac_temperature, ac_flow, ac_heat); + break; + case 'h': + ac_heat = 1; + Ac_Activate(ac_temperature, ac_flow, ac_heat); + break; + case 'm': + /* + if ac is on, 1) turn off, 2) turn on Ac_Air_Clean(1) + if ac is off, 1) turn on, 2) turn off Ac_Air_Clean(0) + */ + if (ac_power_on == 1) { + Ac_Power_Down(); + delay(100); + Ac_Air_Clean(1); + } else { + if (ac_air_clean_state == 1) { + Ac_Air_Clean(0); + delay(100); + } + Ac_Activate(ac_temperature, ac_flow, ac_heat); + } + break; + } + + delay(100); + Serial.println("ac_temperature"); + Serial.println(ac_temperature); + Serial.println("ac_flow"); + Serial.println(ac_flow); + Serial.println("ac_heat"); + Serial.println(ac_heat); + Serial.println("ac_power_on"); + Serial.println(ac_power_on); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino new file mode 100644 index 000000000..a2e450ac5 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/TurnOnArgoAC.ino @@ -0,0 +1,52 @@ +/* Copyright 2017 crankyoldgit +* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* +* 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 + +IRArgoAC argoir(4); // An IR LED is controlled by GPIO pin 4 (D2) + +void setup() { + argoir.begin(); + Serial.begin(115200); +} + +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); + + // Now send the IR signal. + argoir.send(); + + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnArgoAC/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/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino new file mode 100644 index 000000000..eb5cda5e7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino @@ -0,0 +1,56 @@ +/* Copyright 2016 sillyfrog +* +* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* +* 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 + +IRDaikinESP dakinir(D2); // An IR LED is controlled by GPIO pin 4 (D2) + +void setup() { + dakinir.begin(); + Serial.begin(115200); +} + + +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); + + // Now send the IR signal. + dakinir.send(); + + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnDaikinAC/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/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino new file mode 100644 index 000000000..52e31b5d8 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino @@ -0,0 +1,44 @@ +// 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/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnFujitsuAC/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/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino new file mode 100644 index 000000000..393ba28ff --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino @@ -0,0 +1,80 @@ +/* Copyright 2016 David Conran +* +* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* +* 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 + +IRKelvinatorAC kelvir(D2); // An IR LED is controlled by GPIO pin 4 (D2) + +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()); + // Display the encoded IR sequence. + unsigned char* ir_code = kelvir.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < KELVINATOR_STATE_LENGTH; i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + kelvir.begin(); + Serial.begin(115200); + delay(200); + + // Set up what we want to send. See ir_Kelvinator.cpp for all the options. + // Most things default to off. + 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); +} + +void loop() { + // Now send the IR signal. + Serial.println("Sending IR command to A/C ..."); + kelvir.send(); + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnKelvinatorAC/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/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino new file mode 100644 index 000000000..1ea9b0d31 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino @@ -0,0 +1,71 @@ +/* Copyright 2017 David Conran +* +* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* +* 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 + +IRMitsubishiAC mitsubir(D2); // An IR LED is controlled by GPIO pin 4 (D2) + +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()); + // Display the encoded IR sequence. + unsigned char* ir_code = mitsubir.getRaw(); + Serial.print("IR Code: 0x"); + for (uint8_t i = 0; i < MITSUBISHI_AC_STATE_LENGTH; i++) + Serial.printf("%02X", ir_code[i]); + Serial.println(); +} + +void setup() { + mitsubir.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."); + mitsubir.on(); + mitsubir.setFan(1); + mitsubir.setMode(MITSUBISHI_AC_COOL); + mitsubir.setTemp(26); + mitsubir.setVane(MITSUBISHI_AC_VANE_AUTO); +} + +void loop() { + // Now send the IR signal. + Serial.println("Sending IR command to A/C ..."); + mitsubir.send(); + printState(); + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnMitsubishiAC/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.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino new file mode 100644 index 000000000..2476ff557 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino @@ -0,0 +1,52 @@ +/* Copyright 2017 stufisher +* An IR LED circuit *MUST* be connected to ESP8266 pin 4 (D2). +* +* 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 + +IRTrotecESP trotecir(D2); // An IR LED is controlled by GPIO pin 4 (D2) + +void setup() { + trotecir.begin(); + Serial.begin(115200); +} + +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); + + // Now send the IR signal. + trotecir.send(); + + delay(5000); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/examples/TurnOnTrotecAC/platformio.ini new file mode 100644 index 000000000..eeb8d1f2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/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.2.1.02/keywords.txt b/lib/IRremoteESP8266-2.2.1.02/keywords.txt new file mode 100644 index 000000000..ab1b3f70c --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/keywords.txt @@ -0,0 +1,128 @@ +######################################### +# 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/library.json b/lib/IRremoteESP8266-2.2.1.02/library.json new file mode 100644 index 000000000..b8141a2eb --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/library.json @@ -0,0 +1,44 @@ +{ + "name": "IRremoteESP8266", + "version": "2.2.1", + "keywords": "infrared, ir, remote, esp8266", + "description": "Send and receive infrared signals with multiple protocols (ESP8266)", + "repository": + { + "type": "git", + "url": "https://github.com/markszabo/IRremoteESP8266.git" + }, + "authors": [ + { + "name": "Ken Shirriff", + "email": "zetoslab@gmail.com" + }, + { + "name": "Mark Szabo", + "url": "http://nomartini-noparty.blogspot.com/", + "maintainer": true + }, + { + "name": "Sebastien Warin", + "url": "http://sebastien.warin.fr", + "maintainer": true + }, + { + "name": "David Conran", + "url": "https://plus.google.com/+davidconran", + "maintainer": true + }, + { + "name": "Roi Dayan", + "url": "https://github.com/roidayan/", + "maintainer": true + }, + { + "name": "Massimiliano Pinto", + "url": "https://github.com/pintomax/", + "maintainer": true + } + ], + "frameworks": "arduino", + "platforms": "espressif8266" +} diff --git a/lib/IRremoteESP8266-2.2.1.02/library.properties b/lib/IRremoteESP8266-2.2.1.02/library.properties new file mode 100644 index 000000000..ae6f93da7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/library.properties @@ -0,0 +1,9 @@ +name=IRremoteESP8266 +version=2.2.1 +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) +paragraph=This library enables you to send and receive infra-red signals on an ESP8266. +category=Device Control +url=https://github.com/markszabo/IRremoteESP8266 +architectures=esp8266 diff --git a/lib/IRremoteESP8266-2.2.1.02/platformio.ini b/lib/IRremoteESP8266-2.2.1.02/platformio.ini new file mode 100644 index 000000000..63c3781e1 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/platformio.ini @@ -0,0 +1,26 @@ +[platformio] +lib_extra_dirs = . +src_dir = examples/IRrecvDumpV2 + +[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} + +[env:d1_mini] +platform = espressif8266 +framework = arduino +board = d1_mini +build_flags = ${common.build_flags} +lib_deps = + ${common.lib_deps_builtin} + ${common.lib_deps_external} diff --git a/lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg new file mode 100644 index 000000000..fc30d70f8 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/CPPLINT.cfg @@ -0,0 +1 @@ +filter=-build/include,+build/include_alpha,+build/include_order,+build/include_what_you_use diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp b/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp new file mode 100644 index 000000000..d8e390633 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.cpp @@ -0,0 +1,632 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2015 Mark Szabo +// Copyright 2015 Sebastien Warin +// Copyright 2017 David Conran + +#include "IRrecv.h" +#include +#ifndef UNIT_TEST +extern "C" { + #include + #include +} +#include +#endif +#include +#include "IRremoteESP8266.h" + +#ifdef UNIT_TEST +#undef ICACHE_RAM_ATTR +#define ICACHE_RAM_ATTR +#endif +// Updated by Sebastien Warin (http://sebastien.warin.fr) for receiving IR code +// on ESP8266 +// Updated by markszabo (https://github.com/markszabo/IRremoteESP8266) for +// sending IR code on ESP8266 + +// Globals +#ifndef UNIT_TEST +static ETSTimer timer; +#endif +volatile irparams_t irparams; +irparams_t *irparams_save; // A copy of the interrupt state while decoding. + +#ifndef UNIT_TEST +static void ICACHE_RAM_ATTR read_timeout(void *arg __attribute__((unused))) { + os_intr_lock(); + if (irparams.rawlen) + irparams.rcvstate = STATE_STOP; + os_intr_unlock(); +} + +static void ICACHE_RAM_ATTR gpio_intr() { + uint32_t now = system_get_time(); + uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); + static uint32_t start = 0; + + os_timer_disarm(&timer); + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status); + + // Grab a local copy of rawlen to reduce instructions used in IRAM. + // This is an ugly premature optimisation code-wise, but we do everything we + // can to save IRAM. + // It seems referencing the value via the structure uses more instructions. + // Less instructions means faster and less IRAM used. + // N.B. It saves about 13 bytes of IRAM. + uint16_t rawlen = irparams.rawlen; + + if (rawlen >= irparams.bufsize) { + irparams.overflow = true; + irparams.rcvstate = STATE_STOP; + } + + if (irparams.rcvstate == STATE_STOP) + return; + + if (irparams.rcvstate == STATE_IDLE) { + irparams.rcvstate = STATE_MARK; + irparams.rawbuf[rawlen] = 1; + } else { + if (now < start) + irparams.rawbuf[rawlen] = (UINT32_MAX - start + now) / RAWTICK; + else + irparams.rawbuf[rawlen] = (now - start) / RAWTICK; + } + irparams.rawlen++; + + start = now; + #define ONCE 0 + os_timer_arm(&timer, irparams.timeout, ONCE); +} +#endif // UNIT_TEST + +// Start of IRrecv class ------------------- + +// 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) +// timeout: Nr. of milli-Seconds of no signal before we stop capturing data. +// (Default: TIMEOUT_MS) +// save_buffer: Use a second (save) buffer to decode from. (Def: false) +// Returns: +// A 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.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!"); +#ifndef UNIT_TEST + ESP.restart(); // Mem alloc failure. Reboot. +#endif + } + // If we have been asked to use a save buffer (for decoding), then create one. + if (save_buffer) { + irparams_save = new irparams_t; + 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!"); +#ifndef UNIT_TEST + ESP.restart(); // Mem alloc failure. Reboot. +#endif + } + } else { + irparams_save = NULL; + } +} + +// Class destructor +IRrecv::~IRrecv(void) { + delete [] irparams.rawbuf; + if (irparams_save != NULL) { + delete [] irparams_save->rawbuf; + delete irparams_save; + } +} + +// initialization +void IRrecv::enableIRIn() { + // initialize state machine variables + resume(); + +#ifndef UNIT_TEST + // Initialize timer + os_timer_disarm(&timer); + os_timer_setfn(&timer, reinterpret_cast(read_timeout), + NULL); + + // Attach Interrupt + attachInterrupt(irparams.recvpin, gpio_intr, CHANGE); +#endif +} + +void IRrecv::disableIRIn() { +#ifndef UNIT_TEST + os_timer_disarm(&timer); + detachInterrupt(irparams.recvpin); +#endif +} + +void IRrecv::resume() { + irparams.rcvstate = STATE_IDLE; + irparams.rawlen = 0; + irparams.overflow = false; +} + +// 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. +// +// 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) + + // 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. + // This isn't immediately obvious due to typecasting/different variable names. + uint16_t *dst_rawbuf_ptr; + 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]; + + // 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]; +} + +// Obtain the maximum number of entries possible in the capture buffer. +// i.e. It's size. +uint16_t IRrecv::getBufSize() { + return irparams.bufsize; +} + +// Decodes the received IR message. +// If the interrupt state is saved, we will immediately resume waiting +// for the next IR message to avoid missing messages. +// Note: There is a trade-off here. Saving the state means less time lost until +// we can receiving the next message vs. using more RAM. Choose appropriately. +// +// Args: +// results: A pointer to where the decoded IR message will be stored. +// save: A pointer to an irparams_t instance in which to save +// the interrupt's memory/state. NULL means don't save it. +// Returns: +// A boolean indicating if an IR message is ready or not. +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; +#endif + + // Clear the entry we are currently pointing to when we got the timeout. + // i.e. Stopped collecting IR data. + // It's junk as we never wrote an entry to it and can only confuse decoding. + // This is done here rather than logically the best place in read_timeout() + // as it saves a few bytes of ICACHE_RAM as that routine is bound to an + // interrupt. decode() is not stored in ICACHE_RAM. + // Another better option would be to zero the entire irparams.rawbuf[] on + // resume() but that is a much more expensive operation compare to this. + irparams.rawbuf[irparams.rawlen] = 0; + + 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) { + // We haven't been asked to copy it so use the existing memory. +#ifndef UNIT_TEST + results->rawbuf = irparams.rawbuf; + results->rawlen = irparams.rawlen; + results->overflow = irparams.overflow; +#endif + } else { + copyIrParams(&irparams, save); // Duplicate the interrupt's memory. + resume(); // It's now safe to rearm. The IR message won't be overridden. + resumed = true; + // Point the results at the saved copy. + results->rawbuf = save->rawbuf; + results->rawlen = save->rawlen; + results->overflow = save->overflow; + } + + // Reset any previously partially processed results. + results->decode_type = UNKNOWN; + results->bits = 0; + results->value = 0; + results->address = 0; + results->command = 0; + results->repeat = false; + +#if DECODE_AIWA_RC_T501 + DPRINTLN("Attempting Aiwa RC T501 decode"); + // 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; +#endif +#if DECODE_SANYO + DPRINTLN("Attempting Sanyo LC7461 decode"); + // Try decodeSanyoLC7461() before decodeNEC() because the protocols are + // 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; +#endif +#if DECODE_NEC + DPRINTLN("Attempting NEC decode"); + if (decodeNEC(results)) + return true; +#endif +#if DECODE_SONY + DPRINTLN("Attempting Sony decode"); + if (decodeSony(results)) + return true; +#endif +#if DECODE_MITSUBISHI + DPRINTLN("Attempting Mitsubishi decode"); + if (decodeMitsubishi(results)) + return true; +#endif +#if DECODE_RC5 + DPRINTLN("Attempting RC5 decode"); + if (decodeRC5(results)) + return true; +#endif +#if DECODE_RC6 + DPRINTLN("Attempting RC6 decode"); + if (decodeRC6(results)) + return true; +#endif +#if DECODE_RCMM + DPRINTLN("Attempting RC-MM decode"); + if (decodeRCMM(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)) + return true; +#endif +#if DECODE_PANASONIC + DPRINTLN("Attempting Panasonic decode"); + if (decodePanasonic(results)) + return true; +#endif +#if DECODE_LG + DPRINTLN("Attempting LG (28-bit) decode"); + if (decodeLG(results, LG_BITS, true)) + return true; + DPRINTLN("Attempting LG (32-bit) decode"); + // LG32 should be tried before Samsung + if (decodeLG(results, LG32_BITS, true)) + return true; +#endif +#if DECODE_JVC + DPRINTLN("Attempting JVC decode"); + if (decodeJVC(results)) + return true; +#endif +#if DECODE_SAMSUNG + DPRINTLN("Attempting SAMSUNG decode"); + if (decodeSAMSUNG(results)) + return true; +#endif +#if DECODE_WHYNTER + DPRINTLN("Attempting Whynter decode"); + if (decodeWhynter(results)) + return true; +#endif +#if DECODE_DISH + DPRINTLN("Attempting DISH decode"); + if (decodeDISH(results)) + return true; +#endif +#if DECODE_SHARP + DPRINTLN("Attempting Sharp decode"); + if (decodeSharp(results)) + return true; +#endif +#if DECODE_COOLIX + DPRINTLN("Attempting Coolix decode"); + if (decodeCOOLIX(results)) + return true; +#endif +#if DECODE_NIKAI + DPRINTLN("Attempting Nikai decode"); + if (decodeNikai(results)) + return true; +#endif +/* NOTE: Disabled due to poor quality. +#if DECODE_SANYO + // The Sanyo S866500B decoder is very poor quality & depricated. + // *IF* you are going to enable it, do it near last to avoid false positive + // matches. + DPRINTLN("Attempting Sanyo SA8650B decode"); + if (decodeSanyo(results)) + return true; +#endif +*/ +#if DECODE_NEC + // Some devices send NEC-like codes that don't follow the true NEC spec. + // This should detect those. e.g. Apple TV remote etc. + // 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)) { + results->decode_type = NEC_LIKE; + return true; + } +#endif + // 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; + } + // Throw away and start over + if (!resumed) // Check if we have already resumed. + resume(); + return false; +} + +// Calculate the lower bound of the nr. of ticks. +// +// Args: +// usecs: Nr. of uSeconds. +// tolerance: Percent as an integer. e.g. 10 is 10% +// Returns: +// Nr. of ticks. +uint32_t IRrecv::ticksLow(uint32_t usecs, uint8_t tolerance) { + // 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)); +} + +// Calculate the upper bound of the nr. of ticks. +// +// Args: +// usecs: Nr. of uSeconds. +// tolerance: Percent as an integer. e.g. 10 is 10% +// Returns: +// Nr. of ticks. +uint32_t IRrecv::ticksHigh(uint32_t usecs, uint8_t tolerance) { + return((uint32_t) (usecs * (1.0 + tolerance / 100.0)) + 1); +} + +// Check if we match a pulse(measured) with the desired within +// +/-tolerance percent. +// +// 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%. +// +// 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. + DPRINT("Matching: "); + DPRINT(ticksLow(desired, tolerance)); + DPRINT(" <= "); + DPRINT(measured); + DPRINT(" <= "); + DPRINTLN(ticksHigh(desired, tolerance)); + return (measured >= ticksLow(desired, tolerance) && + measured <= ticksHigh(desired, tolerance)); +} + + +// Check if we match a pulse(measured) of at least desired within +// +/-tolerance percent. +// +// 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%. +// +// 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. + DPRINT("Matching ATLEAST "); + DPRINT(measured); + DPRINT(" vs "); + DPRINT(desired); + DPRINT(". Matching: "); + DPRINT(measured); + DPRINT(" >= "); + DPRINT(ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), tolerance)); + DPRINT(" [min("); + DPRINT(ticksLow(desired, tolerance)); + DPRINT(", "); + DPRINT(ticksLow(MS_TO_USEC(irparams.timeout), tolerance)); + 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); +} + +// Check if we match a mark signal(measured) with the desired within +// +/-tolerance percent, after an expected is excess is added. +// +// 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%. +// excess: Nr. of useconds. +// +// 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) { + DPRINT("Matching MARK "); + DPRINT(measured * RAWTICK); + DPRINT(" vs "); + DPRINT(desired); + DPRINT(" + "); + DPRINT(excess); + DPRINT(". "); + return match(measured, desired + excess, tolerance); +} + +// Check if we match a space signal(measured) with the desired within +// +/-tolerance percent, after an expected is excess is removed. +// +// 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%. +// excess: Nr. of useconds. +// +// 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) { + DPRINT("Matching SPACE "); + DPRINT(measured * RAWTICK); + DPRINT(" vs "); + DPRINT(desired); + DPRINT(" - "); + DPRINT(excess); + DPRINT(". "); + return match(measured, desired - excess, tolerance); +} + +/* ----------------------------------------------------------------------- + * hashdecode - decode an arbitrary IR code. + * Instead of decoding using a standard encoding scheme + * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value. + * + * The algorithm: look at the sequence of MARK signals, and see if each one + * is shorter (0), the same length (1), or longer (2) than the previous. + * Do the same with the SPACE signals. Hash the resulting sequence of 0's, + * 1's, and 2's to a 32-bit value. This will give a unique value for each + * different code (probably), for most code systems. + * + * http://arcfn.com/2010/01/using-arbitrary-remotes-with-arduino.html + */ + +// Compare two tick values, returning 0 if newval is shorter, +// 1 if newval is equal, and 2 if newval is longer +// Use a tolerance of 20% +int16_t IRrecv::compare(uint16_t oldval, uint16_t newval) { + if (newval < oldval * 0.8) + return 0; + else if (oldval < newval * 0.8) + return 2; + else + return 1; +} + +/* 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; + // 'rawlen - 2' to avoid the look ahead from going out of bounds. + // Should probably be -3 to avoid comparing the trailing space entry, + // however it is left this way for compatibility with previously captured + // values. + for (uint16_t i = 1; i < results->rawlen - 2; i++) { + int16_t value = compare(results->rawbuf[i], results->rawbuf[i + 2]); + // Add value into the hash + hash = (hash * FNV_PRIME_32) ^ value; + } + results->value = hash & 0xFFFFFFFF; + results->bits = results->rawlen / 2; + results->address = 0; + results->command = 0; + results->decode_type = UNKNOWN; + return true; +} + +// Match & decode the typical data section of an IR message. +// The data value constructed as the Most Significant Bit first. +// +// Args: +// data_ptr: A pointer to where we are at in the capture buffer. +// nbits: Nr. of data bits we expect. +// onemark: Nr. of uSeconds in an expected mark signal for a '1' bit. +// onespace: Nr. of uSeconds in an expected space signal for a '1' bit. +// zeromark: Nr. of uSeconds in an expected mark signal for a '0' bit. +// zerospace: Nr. of uSeconds in an expected space signal for a '0' bit. +// 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 result; + result.success = false; + 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 + } + 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; + } + return result; +} + +// End of IRrecv class ------------------- diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h b/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h new file mode 100644 index 000000000..febe5e2d5 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRrecv.h @@ -0,0 +1,207 @@ +// 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 new file mode 100644 index 000000000..e2dc26904 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRremoteESP8266.h @@ -0,0 +1,337 @@ + /*************************************************** + * 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 new file mode 100644 index 000000000..300b1fa99 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRsend.cpp @@ -0,0 +1,327 @@ +// 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 new file mode 100644 index 000000000..87c1fdd9a --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRsend.h @@ -0,0 +1,209 @@ +// 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/IRtimer.cpp b/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp new file mode 100644 index 000000000..cc5cdfaff --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.cpp @@ -0,0 +1,33 @@ +// Copyright 2017 David Conran + +#include "IRtimer.h" +#ifndef UNIT_TEST +#include +#endif + +// This class performs a simple time in useconds since instantiated. +// Handles when the system timer wraps around (once). + +IRtimer::IRtimer() { + reset(); +} + +void IRtimer::reset() { +#ifndef UNIT_TEST + start = micros(); +#else + start = 0; +#endif +} + +uint32_t IRtimer::elapsed() { +#ifndef UNIT_TEST + uint32_t now = micros(); +#else + uint32_t now = 0; +#endif + if (start <= now) // Check if the system timer has wrapped. + return now - start; // No wrap. + else + return UINT32_MAX - start + now; // Has wrapped. +} diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h b/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h new file mode 100644 index 000000000..6cf7f7dc8 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRtimer.h @@ -0,0 +1,20 @@ +// Copyright 2017 David Conran + +#ifndef IRTIMER_H_ +#define IRTIMER_H_ + +#define __STDC_LIMIT_MACROS +#include + +// Classes +class IRtimer { + public: + IRtimer(); + void reset(); + uint32_t elapsed(); + + private: + uint32_t start; +}; + +#endif // IRTIMER_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp b/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp new file mode 100644 index 000000000..22b4bb3b7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRutils.cpp @@ -0,0 +1,82 @@ +// 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 new file mode 100644 index 000000000..eb3f1d8ee --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/IRutils.h @@ -0,0 +1,23 @@ +#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_Aiwa.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp new file mode 100644 index 000000000..99a97e187 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Aiwa.cpp @@ -0,0 +1,118 @@ +// Copyright 2017 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" + +// AAA IIIII W W AAA +// A A I W W A A +// AAAAA I W W W AAAAA +// A A I W W W A A +// A A IIIII WWW A A + +// Based off the RC-T501 RCU +// 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 +// 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 + +#if SEND_AIWA_RC_T501 +// Send a 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) +// repeat: The number of times the command is to be repeated. +// +// Status: BETA / Should work. +// +// Ref: +// http://lirc.sourceforge.net/remotes/aiwa/RC-T501 +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; + if (nbits > sizeof(new_data) * 8) + return; // We are overflowing. Abort, and don't send. + sendNEC(new_data, nbits, repeat); +} +#endif + +#if DECODE_AIWA_RC_T501 +// Decode the supplied Aiwa RC T501 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 AIWA_RC_T501_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 / Should work. +// +// Notes: +// Aiwa RC T501 appears to be a 42 bit variant of the NEC1 protocol. +// However, we historically (original Arduino IRremote project) treats it as +// a 15 bit (data) protocol. So, we expect nbits to typically be 15, and we +// will remove the prefix and postfix from the raw data, and use that as +// the result. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/nec.php +bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t nbits, + bool strict) { + // Compliance + if (strict && nbits != AIWA_RC_T501_BITS) + 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; + uint64_t new_data; + if (expected_nbits > sizeof(new_data) * 8) + return false; // We can't possibly match something that big. + // Decode it as a much bigger (non-standard) NEC message, so we have to turn + // off strict mode checking for NEC. + if (!decodeNEC(results, expected_nbits, false)) + return false; // The NEC decode had a problem, so we should too. + uint16_t actual_bits = results->bits; + 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) + 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; + + // Extract out our likely new value and put it back in the results. + actual_bits -= AIWA_RC_T501_PRE_BITS; + 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. + return false; + + // Compliance + if (strict && results->bits != expected_nbits) + return false; + + // Success + results->decode_type = AIWA_RC_T501; + results->bits = actual_bits; + results->address = 0; + results->command = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp new file mode 100644 index 000000000..0129c7231 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.cpp @@ -0,0 +1,264 @@ +/* +Node MCU/ESP8266 Sketch to emulate Argo Ulisse 13 DCI remote +Controls Argo Ulisse 13 DCI A/C +Copyright 2017 Schmolders +*/ + +#include "ir_Argo.h" +#include +#include "IRremoteESP8266.h" +#include "IRutils.h" + +// Constants +// using SPACE modulation. MARK is always const 400u +#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 + +#if SEND_ARGO +// Send a Argo A/C message. +// +// Args: +// data: An array of ARGO_COMMAND_LENGTH 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. + } +} + +IRArgoAC::IRArgoAC(uint16_t pin) : _irsend(pin) { + stateReset(); +} + +void IRArgoAC::begin() { + _irsend.begin(); +} + +void IRArgoAC::send() { + // Serial.println("Sending IR code"); // Only for Debug + checksum(); // Create valid checksum before sending + _irsend.sendArgo(argo); +} + +void IRArgoAC::checksum() { + uint8_t sum = 2; // Corresponds to byte 11 being constant 0b01 + uint8_t i; + + // Only add up bytes to 9. byte 10 is 0b01 constant anyway. + // Assume that argo array is MSB first (left) + for (i = 0; i < 10; i++) + sum += argo[i]; + + sum = sum % 256; // modulo 256 + // Append sum to end of array + // Set const part of checksum bit 10 + argo[10] = 0b00000010; + argo[10] += sum << 2; // Shift up 2 bits and append to byte 10 + argo[11] = sum >> 6; // Shift down 6 bits and add in two LSBs of bit 11 +} + +void IRArgoAC::stateReset() { + for (uint8_t i = 0; i < ARGO_COMMAND_LENGTH; i++) + argo[i] = 0x0; + + // Argo Message. Store MSB left. + // Default message: + argo[0] = 0b10101100; // LSB first (as sent) 0b00110101; //const preamble + argo[1] = 0b11110101; // LSB first: 0b10101111; //const preamble + // Keep payload 2-9 at zero + argo[10] = 0b00000010; // Const 01, checksum 6bit + argo[11] = 0b00000000; // Checksum 2bit + + this->off(); + this->setTemp(20); + this->setRoomTemp(25); + this->setCoolMode(ARGO_COOL_AUTO); + this->setFan(ARGO_FAN_AUTO); +} + +uint8_t* IRArgoAC::getRaw() { + checksum(); // Ensure correct bit array before returning + return argo; +} + +void IRArgoAC::on() { + // state = ON; + ac_state = 1; + // Bit 5 of byte 9 is on/off + // in MSB first + argo[9] = argo[9] | 0b00100000; // Set ON/OFF bit to 1 +} + +void IRArgoAC::off() { + // state = OFF; + ac_state = 0; + // in MSB first + // bit 5 of byte 9 to off + argo[9] = argo[9] & 0b11011111; // Set on/off bit to 0 +} + +void IRArgoAC::setPower(bool state) { + if (state) + on(); + else + off(); +} + +uint8_t IRArgoAC::getPower() { + return ac_state; +} + +void IRArgoAC::setMax(bool state) { + max_mode = state; + if (max_mode) + argo[9] |= 0b00001000; + else + argo[9] &= 0b11110111; +} + +bool IRArgoAC::getMax() { + return max_mode; +} + +// Set the temp in deg C +// Sending 0 equals +4 +void IRArgoAC::setTemp(uint8_t temp) { + if (temp < ARGO_MIN_TEMP) + temp = ARGO_MIN_TEMP; + else if (temp > ARGO_MAX_TEMP) + temp = ARGO_MAX_TEMP; + + // Store in attributes + set_temp = temp; + // offset 4 degrees. "If I want 12 degrees, I need to send 8" + temp -= 4; + // Settemp = Bit 6,7 of byte 2, and bit 0-2 of byte 3 + // mask out bits + // argo[13] & 0x00000100; // mask out ON/OFF Bit + argo[2] &= 0b00111111; + argo[3] &= 0b11111000; + + argo[2] += temp << 6; // append to bit 6,7 + argo[3] += temp >> 2; // remove lowest to bits and append in 0-2 +} + +uint8_t IRArgoAC::getTemp() { + return set_temp; +} + +// Set the speed of the fan +void IRArgoAC::setFan(uint8_t fan) { + // Set the fan speed bits, leave low 4 bits alone + fan_mode = fan; + // Mask out bits + argo[3] &= 0b11100111; + // Set fan mode at bit positions + argo[3] += fan << 3; +} + +uint8_t IRArgoAC::getFan() { + return fan_mode; +} + +void IRArgoAC::setFlap(uint8_t flap) { + flap_mode = flap; + // TODO(kaschmo): set correct bits for flap mode +} + +uint8_t IRArgoAC::getFlap() { + return flap_mode; +} + +uint8_t IRArgoAC::getMode() { + // return cooling 0, heating 1 + return ac_mode; +} + +void IRArgoAC::setCoolMode(uint8_t mode) { + ac_mode = 0; // Set ac mode to cooling + cool_mode = mode; + // Mask out bits, also leave bit 5 on 0 for cooling + argo[2] &= 0b11000111; + + // Set cool mode at bit positions + argo[2] += mode << 3; +} + +uint8_t IRArgoAC::getCoolMode() { + return cool_mode; +} + +void IRArgoAC::setHeatMode(uint8_t mode) { + ac_mode = 1; // Set ac mode to heating + heat_mode = mode; + // Mask out bits + argo[2] &= 0b11000111; + // Set heating bit + argo[2] |= 0b00100000; + // Set cool mode at bit positions + argo[2] += mode << 3; +} + +uint8_t IRArgoAC::getHeatMode() { + return heat_mode; +} + +void IRArgoAC::setNight(bool state) { + night_mode = state; + if (night_mode) + // Set bit at night position: bit 2 + argo[9] |= 0b00000100; + else + argo[9] &= 0b11111011; +} + +bool IRArgoAC::getNight() { + return night_mode; +} + +void IRArgoAC::setiFeel(bool state) { + ifeel_mode = state; + if (ifeel_mode) + // Set bit at iFeel position: bit 7 + argo[9] |= 0b10000000; + else + argo[9] &= 0b01111111; +} + +bool IRArgoAC::getiFeel() { + return ifeel_mode; +} + +void IRArgoAC::setTime() { + // TODO(kaschmo): use function call from checksum to set time first +} + +void IRArgoAC::setRoomTemp(uint8_t temp) { + temp -= 4; + // Mask out bits + argo[3] &= 0b00011111; + argo[4] &= 0b11111100; + + argo[3] += temp << 5; // Append to bit 5,6,7 + argo[4] += temp >> 3; // Remove lowest 3 bits and append in 0,1 +} +#endif // SEND_ARGO diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h new file mode 100644 index 000000000..a25199208 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Argo.h @@ -0,0 +1,124 @@ +/* Copyright 2017 Schmolders +// Adds support for Argo Ulisse 13 DCI Mobile Split ACs. +*/ +#ifndef IR_ARGO_H_ +#define IR_ARGO_H_ + +#include "IRremoteESP8266.h" +#include "IRsend.h" + +// ARGO Ulisse DCI + +/* + Protocol Description: + All in LSB first as it is sent. argo message array will be stored MSB first! + do LSB-MSB conversion in sendData + Byte 0: const 0 0 1 1 0 1 0 1 + Byte 1: const 1 0 1 0 1 1 1 1 + Byte 2: 0 0 0, 3bit Cool/Heat Mode, 2bit start SetTemp LSB first + Byte 3: 3bit End SetTemp, 2bit Fan Mode, 3bit RoomTemp LSB first + Byte 4: 2bit RoomTemp, 3bit Flap Mode, 3bit OnTimer + Byte 5: 8bit OnTimer + Byte 6: 8Bit OffTimer + Byte 7: 3bit OffTimer, 5bit Time + Byte 8: 6bit Time, 1bit Timer On/Off, 1bit Timer Program + Byte 9: 1bit Timer Program, 1bit Timer 1h, 1 bit Night Mode, 1bit Max Mode, 1bit Filter, 1bit on/off, 1bit const 0, 1bit iFeel + Byte 10: 2bit const 0 1, 6bit Checksum + Byte 11: 2bit Checksum +*/ + +// 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 + +#define ARGO_HEAT_ON 0U // 0b001 +#define ARGO_HEAT_AUTO 1U // 0b101 +#define ARGO_HEAT_BLINK 2U // 0b011 // ??no idea what mode that is + + +#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); + + void send(); + void begin(); + void on(); + void off(); + + void setPower(bool state); + uint8_t getPower(); + + void setTemp(uint8_t temp); + uint8_t getTemp(); + + void setFan(uint8_t fan); + uint8_t getFan(); + + void setFlap(uint8_t flap); + uint8_t getFlap(); + + void setCoolMode(uint8_t mode); + uint8_t getCoolMode(); + + void setHeatMode(uint8_t mode); + uint8_t getHeatMode(); + uint8_t getMode(); + + void setMax(bool state); + bool getMax(); + + void setNight(bool state); + bool getNight(); + + void setiFeel(bool state); + bool getiFeel(); + + void setTime(); + void setRoomTemp(uint8_t temp); + + uint8_t* getRaw(); + + private: + // # of bytes per command + uint8_t argo[ARGO_COMMAND_LENGTH]; // Defined in IRremoteESP8266.h + void stateReset(); + void checksum(); + IRsend _irsend; // instance of the IR send class + + // Attributes + uint8_t set_temp; + uint8_t fan_mode; + uint8_t flap_mode; + uint8_t ac_state; + uint8_t ac_mode; // heat 1, cool 0 + uint8_t heat_mode; + uint8_t cool_mode; + uint8_t night_mode; // on/off + uint8_t max_mode; // on/off + uint8_t ifeel_mode; // on/off +}; +#endif // SEND_ARGO + +#endif // IR_ARGO_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 new file mode 100644 index 000000000..f664d6ad7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Coolix.cpp @@ -0,0 +1,167 @@ +// 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 new file mode 100644 index 000000000..f57b67608 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.cpp @@ -0,0 +1,347 @@ +/* +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 new file mode 100644 index 000000000..7172a5e27 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Daikin.h @@ -0,0 +1,107 @@ +/* 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_Denon.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp new file mode 100644 index 000000000..538e5af10 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Denon.cpp @@ -0,0 +1,153 @@ +// Copyright 2016 Massimiliano Pinto +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// DDDD EEEEE N N OOO N N +// D D E NN N O O NN N +// D D EEE N N N O O N N N +// D D E N NN O O N NN +// DDDD EEEEE N N OOO N N + +// Original Denon support added by https://github.com/csBlueChip +// Ported over by Massimiliano Pinto + +// 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 + +#if SEND_DENON +// Send a Denon message +// +// Args: +// data: Contents of the message to be sent. +// nbits: Nr. of bits of data to be sent. Typically DENON_BITS. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: BETA / Should be working. +// +// Notes: +// Some Denon devices use a Kaseikyo/Panasonic 48-bit format +// Others use the Sharp protocol. +// Ref: +// 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? + sendPanasonic64(data, nbits, repeat); + else if (nbits == DENON_LEGACY_BITS) + // Support legacy (broken) calls of sendDenon(). + sendSharpRaw(data & (~0x2000ULL), nbits + 1, repeat); + else + sendSharpRaw(data, nbits, repeat); +} +#endif + +#if DECODE_DENON +// Decode a Denon message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Expected nr. of data bits. (Typically DENON_BITS) +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: BETA / Should work fine. +// +// Ref: +// https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp +bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { + // Compliance + if (strict) { + switch (nbits) { + case DENON_BITS: + case DENON_48_BITS: + case DENON_LEGACY_BITS: + break; + default: + return false; + } + } + + // Denon uses the Sharp & Panasonic(Kaseikyo) protocol for some + // devices, so check for those first. + // It is not exactly like Sharp's protocols, but close enough. + // e.g. The expansion bit is not set for Denon vs. set for Sharp. + // Ditto for Panasonic, it's the same except for a different + // manufacturer code. + + if (!decodeSharp(results, nbits, true, false) && + !decodePanasonic(results, nbits, true, DENON_MANUFACTURER)) { + // 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; + + uint64_t data = 0; + uint16_t offset = OFFSET_START; + + // Header + if (!matchMark(results->rawbuf[offset], DENON_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 / + 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; + + // 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); + 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)) + return false; + + // Success + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + } // Legacy decode. + + // Compliance + if (strict && nbits != results->bits) return false; + + // Success + results->decode_type = DENON; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp new file mode 100644 index 000000000..4555db92f --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Dish.cpp @@ -0,0 +1,144 @@ +// Copyright Todd Treece +// Copyright 2017 David Conran + +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// DDDD IIIII SSSS H H +// D D I S H H +// D D I SSS HHHHH +// D D I S H H +// DDDD IIIII SSSS H H + +// DISH support originally by Todd Treece +// http://unionbridge.org/design/ircommand + +// Constants +// 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) + +#if SEND_DISH +// Send an IR command to a DISH NETWORK device. +// +// Args: +// data: The contents of the command you want to send. +// nbits: The bit size of the command being sent. +// repeat: The number of times you want the command to be repeated. +// +// Status: BETA / Previously working. +// +// Note: +// Dishplayer is a different protocol. +// Typically a DISH device needs to get a command a total of at least 4 +// times to accept it. e.g. repeat=3 +// +// Here is the LIRC file I found that seems to match the remote codes from the +// oscilloscope: +// DISH NETWORK (echostar 301): +// http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx +// +// 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); + } +} +#endif + +#if DECODE_DISH +// Decode the supplied DISH NETWORK 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 DISH_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 and unconfirmed.) +// +// Note: +// Dishplayer is a different protocol. +// Typically a DISH device needs to get a command a total of at least 4 +// times to accept it. +// Ref: +// http://www.hifi-remote.com/wiki/index.php?title=Dish +// 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) + return false; // Not enough entries to be valid. + if (strict && nbits != DISH_BITS) + return false; // Not strictly compliant. + + uint64_t data = 0; + uint16_t offset = OFFSET_START; + + // Header + if (!match(results->rawbuf[offset], DISH_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 / DISH_HDR_MARK_TICKS; + if (!matchSpace(results->rawbuf[offset], DISH_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 / DISH_HDR_SPACE_TICKS; + + // 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); + 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)) + return false; + + // Compliance + if (strict) { + // The DISH protocol calls for a repeated message, so strictly speaking + // there should be a code following this. Only require it if we are set to + // strict matching. + if (!matchSpace(results->rawbuf[offset], DISH_RPT_SPACE_TICKS * s_tick)) + return false; + } + + // Success + results->decode_type = DISH; + results->bits = nbits; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp new file mode 100644 index 000000000..adf753c0c --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.cpp @@ -0,0 +1,221 @@ +// 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 new file mode 100644 index 000000000..451a5b203 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Fujitsu.h @@ -0,0 +1,80 @@ +// 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_GlobalCache.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp new file mode 100644 index 000000000..019413b96 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_GlobalCache.cpp @@ -0,0 +1,72 @@ +// Copyright 2016 Hisham Khalifa +// Copyright 2017 David Conran + +#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 +// G L O O BBBBB A A L C A A C HHHHHH EEEE +// G GG L O O B BB AAAAAA L C C AAAAAA C C H H E +// GGGGG LLLLLL OOOO BBBBB A A LLLLLL CCCC A A CCCC H H EEEEEE + +// Global Cache IR format sender originally added by Hisham Khalifa +// (http://www.hishamkhalifa.com) + +// 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 + +#if SEND_GLOBALCACHE +// Send a shortened GlobalCache (GC) IRdb/control tower formatted message. +// +// Args: +// buf: An array of uint16_t containing the shortened GlobalCache data. +// len: Nr. of entries in the buf[] array. +// +// Status: STABLE / Known working. +// +// Note: +// Global Cache format without the emitter ID or request ID. +// Starts at the frequency (Hertz), followed by nr. of times to emit (count), +// then the offset for repeats (where a repeat will start from), +// then the rest of entries are the actual IR message as units of periodic +// time. +// e.g. sendir,1:1,1,38000,1,1,9,70,9,30,9,... -> 38000,1,1,9,70,9,30,9,... +// 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. + enableIROut(hz); + uint32_t periodic_time = calcUSecPeriod(hz, false); + uint8_t emits = std::min(buf[GLOBALCACHE_RPT_INDEX], + (uint16_t) GLOBALCACHE_MAX_REPEAT); + // Repeat + for (uint8_t repeat = 0; repeat < emits; repeat++) { + // First time through, start at the beginning (GLOBALCACHE_START_INDEX), + // 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; + // 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); + // These codes start at an odd index (not even as with sendRaw). + if (offset & 1) // Odd bit. + mark(microseconds); + else // Even bit. + space(microseconds); + } + } + // It's possible that we've ended on a mark(), thus ensure the LED is off. + ledOff(); +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp new file mode 100644 index 000000000..d1bc760bf --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Gree.cpp @@ -0,0 +1,113 @@ +// 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_JVC.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp new file mode 100644 index 000000000..194e39250 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_JVC.cpp @@ -0,0 +1,165 @@ +// Copyright 2015 Kristian Lauszus +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// JJJJJ V V CCCC +// J V V C +// J V V C +// J J V V C +// J V CCCC + +// JVC originally added by Kristian Lauszus +// (Thanks to zenwheel and other people at the original blog post) + +// 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) + +#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) +// repeat: The number of times you want the command to be repeated. +// +// Status: STABLE. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/jvc.php +void IRsend::sendJVC(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 + // Only sent for the first message. + mark(JVC_HDR_MARK); + space(JVC_HDR_SPACE); + + // 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); + // 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())); + usecs.reset(); + } +} + +// Calculate the raw JVC data based on address and command. +// +// Args: +// address: An 8-bit address value. +// command: An 8-bit command value. +// Returns: +// A raw JVC message. +// +// Status: BETA / Should work fine. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/jvc.php +uint16_t IRsend::encodeJVC(uint8_t address, uint8_t command) { + return reverseBits((command << 8) | address, 16); +} +#endif + +#if DECODE_JVC +// Decode the supplied JVC message. +// +// 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. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE +// +// Note: +// 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) + return false; // Must be called with the correct nr. of bits. + if (results->rawlen < 2 * nbits + FOOTER - 1) + return false; // Can't possibly be a valid JVC message. + + uint64_t data = 0; + uint16_t offset = OFFSET_START; + 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)) { + isRepeat = false; + m_tick = results->rawbuf[offset++] * RAWTICK / JVC_HDR_MARK_TICKS; + 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; + } 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; + } + + // 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); + 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)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], JVC_MIN_GAP_TICKS * s_tick)) + return false; + + // Success + results->decode_type = JVC; + 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->command = reverseBits(data & 0xFF, 8); // The last 8 bits sent. + results->repeat = isRepeat; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp new file mode 100644 index 000000000..257a32e1a --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.cpp @@ -0,0 +1,329 @@ +// 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_Kelvinator.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h new file mode 100644 index 000000000..c15d85c6e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Kelvinator.h @@ -0,0 +1,152 @@ +// Kelvinator A/C +// +// Copyright 2016 David Conran + +#ifndef IR_KELVINATOR_H_ +#define IR_KELVINATOR_H_ + +#define __STDC_LIMIT_MACROS +#include +#include "IRremoteESP8266.h" +#include "IRsend.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 +#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 + +/* + Kelvinator AC map + + (header mark and space) + byte 0 = Basic Modes + b2-0 = Modes + Modes: + 000 = Auto (temp = 25C) + 001 = Cool + 010 = Dry (temp = 25C, but not shown) + 011 = Fan + 100 = Heat + b3 = Power Status (1 = On, 0 = Off) + b5-4 = Fan (Basic modes) + Fan: + 00 = Auto + 01 = Fan 1 + 10 = Fan 2 + 11 = Fan 3 or higher (See byte 14) + b6 = Vent swing (1 = On, 0 = Off) (See byte 4) + b7 = Sleep Modes 1 & 3 (1 = On, 0 = Off) + byte 1 = Temperature + b3-0: Degrees C. + 0000 (0) = 16C + 0001 (1) = 17C + 0010 (2) = 18C + ... + 1101 (13) = 29C + 1110 (14) = 30C + byte 2 = Extras + b3-0 = UNKNOWN, typically 0. + b4 = Turbo Fan (1 = On, 0 = Off) + b5 = Light (Display) (1 = On, 0 = Off) + b6 = Ion Filter (1 = On, 0 = Off) + b7 = X-Fan (Fan runs for a while after power off) (1 = On, 0 = Off) + byte 3 = Section Indicator + b3-0 = Unused (Typically 0) + b5-4 = Unknown (possibly timer related) (Typically 0b01) + b7-6 = End of command block (B01) + (B010 marker and a gap of 20ms) + byte 4 = Extended options + b0 = Swing Vent Vertical (1 = On, 0 = Off) + b4 = Swing Vent Horizontal (1 = On, 0 = Off) + byte 5-6 = Timer related. Typically 0 except when timer in use. + byte 7 = checksum + b3-0 = Unknown (Used in Timer mode) + b7-4 = checksum of the previous bytes (0-6) + (gap of 40ms) + (header mark and space) + byte 8 = Repeat of byte 0 + byte 9 = Repeat of byte 1 + byte 10 = Repeat of byte 2 + byte 11 = Section Indicator + b3-0 = Unused (Typically 0) + b5-4 = Unknown (possibly timer related) (Typically 0b11) + b7-6 = End of command block (B01) + (B010 marker and a gap of 20ms) + byte 12 = Extended options + b0 = Sleep mode 2 (1 = On, 0=Off) + b6-1 = Unknown (Used in Sleep Mode 3, Typically 0b000000) + b7 = Quiet Mode (1 = On, 0=Off) + byte 13 = Unknown (Sleep Mode 3 related, Typically 0x00) + byte 14 = Fan control + b3-0 = Unknown (Sleep Mode 3 related, Typically 0b0000) + b6-4 = Fan speed + 0b000 (0) = Automatic + 0b001 (1) = Fan 1 + 0b010 (2) = Fan 2 + 0b011 (3) = Fan 3 + 0b100 (4) = Fan 4 + 0b101 (5) = Fan 5 + byte 15 = checksum + b3-0 = Unknown (Typically 0b0000) + b7-4 = checksum of the previous bytes (8-14) +*/ + +#if SEND_KELVINATOR + +// Classes +class IRKelvinatorAC { + public: + explicit IRKelvinatorAC(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 setSwingVertical(bool state); + bool getSwingVertical(); + void setSwingHorizontal(bool state); + bool getSwingHorizontal(); + void setQuiet(bool state); + bool getQuiet(); + void setIonFilter(bool state); + bool getIonFilter(); + void setLight(bool state); + bool getLight(); + void setXFan(bool state); + bool getXFan(); + void setTurbo(bool state); + bool getTurbo(); + uint8_t* getRaw(); + + private: + // The state of the IR remote in IR code form. + uint8_t remote_state[KELVINATOR_STATE_LENGTH]; + void checksum(); + void fixup(); + IRsend _irsend; +}; +#endif + +#endif // IR_KELVINATOR_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp new file mode 100644 index 000000000..716ddd205 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.cpp @@ -0,0 +1,233 @@ +// 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_LG.h b/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h new file mode 100644 index 000000000..25d56bc26 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_LG.h @@ -0,0 +1,17 @@ +// Copyright 2017 David Conran + +#ifndef IR_LG_H_ +#define IR_LG_H_ + +// L GGGG +// L G +// L G GG +// L G G +// LLLLL GGG + +#define __STDC_LIMIT_MACROS +#include + +uint8_t calcLGChecksum(uint16_t data); + +#endif // IR_LG_H_ diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp new file mode 100644 index 000000000..df8b6e1ef --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.cpp @@ -0,0 +1,349 @@ +// 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 new file mode 100644 index 000000000..e9f5731aa --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Mitsubishi.h @@ -0,0 +1,65 @@ +// 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_NEC.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp new file mode 100644 index 000000000..a5febe1b8 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_NEC.cpp @@ -0,0 +1,210 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// N N EEEEE CCCC +// NN N E C +// N N N EEE C +// N NN E C +// N N EEEEE CCCC + +// NEC originally added from https://github.com/shirriff/Arduino-IRremote/ + +// 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) +// 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. +// repeat: The number of times the command is to be repeated. +// +// Status: STABLE / Known working. +// +// 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())); + + // 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())); + } +} + +// Calculate the raw NEC data based on address and command. +// Args: +// address: An address value. +// command: An 8-bit command value. +// Returns: +// A raw 32-bit NEC message. +// +// Status: BETA / Expected to work. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/nec.php +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? + address = reverseBits(address, 16); + return ((address << 16) + command); // Extended. + } else { + address = reverseBits(address, 8); + return (address << 24) + ((address ^ 0xFF) << 16) + command; // Normal. + } +} +#endif + +#if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || DECODE_SANYO) +// Decode the supplied NEC 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 NEC_BITS. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: STABLE / Known good. +// +// Notes: +// NEC protocol has three varients/forms. +// Normal: a 8 bit address & a 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. +// 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) + return false; // Can't possibly be a valid NEC message. + if (strict && nbits != NEC_BITS) + return false; // Not strictly an NEC message. + + uint64_t data = 0; + uint16_t offset = OFFSET_START; + + // Header + if (!matchMark(results->rawbuf[offset], NEC_HDR_MARK)) 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; + // 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; + results->decode_type = NEC; + results->bits = 0; + results->address = 0; + results->command = 0; + results->repeat = true; + return true; + } + + // Header (cont.) + if (!matchSpace(results->rawbuf[offset], NEC_HDR_SPACE)) 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; + // 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); + 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)) + return false; + + // Compliance + // Calculate command and optionally enforce integrity checking. + 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. + command = 0; // The command value isn't valid, so default to zero. + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = NEC; + // NEC command and address are technically in LSB first order so the + // final versions have to be reversed. + results->command = reverseBits(command, 8); + // Normal NEC protocol has an 8 bit address sent, followed by it inverted. + uint8_t address = (data & 0xFF000000) >> 24; + uint8_t address_inverted = (data & 0x00FF0000) >> 16; + if (address == (address_inverted ^ 0xFF)) + // Inverted, so it is normal NEC protocol. + results->address = reverseBits(address, 8); + else // Not inverted, so must be Extended NEC protocol, thus 16 bit address. + results->address = reverseBits((data >> 16) & UINT16_MAX, 16); + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp new file mode 100644 index 000000000..e1afda4c5 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Nikai.cpp @@ -0,0 +1,120 @@ +// 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 new file mode 100644 index 000000000..fb1f12234 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Panasonic.cpp @@ -0,0 +1,196 @@ +// 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_Pronto.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp new file mode 100644 index 000000000..ca76f0848 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Pronto.cpp @@ -0,0 +1,109 @@ +// Copyright 2017 David Conran + +#include +#include "IRsend.h" +#include "IRtimer.h" + +// PPPPPP tt +// PP PP rr rr oooo nn nnn tt oooo +// PPPPPP rrr r oo oo nnn nn tttt oo oo +// PP rr oo oo nn nn tt oo oo +// PP rr oooo nn nn tttt oooo + +// Constants +#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 + +#if SEND_PRONTO +// Send a Pronto Code formatted message. +// +// Args: +// data: An array of uint16_t containing the pronto codes. +// len: Nr. of entries in the data[] array. +// repeat: Nr. of times to repeat the message. +// +// Status: ALPHA / Not tested in the real world. +// +// Note: +// Pronto codes are typically represented in hexadecimal. +// You will need to convert the code to an array of integers, and calculate +// it's length. +// e.g. +// A Sony 20 bit DVD remote command. +// "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" +// +// converts to: +// +// uint16_t prontoCode[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, +// 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); +// +// 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; + + // We only know how to deal with 'raw' pronto codes types. Reject all others. + if (data[PRONTO_TYPE_OFFSET] != 0) return; + + // Pronto frequency is in Hz. + uint16_t hz = (uint16_t) (1000000U / (data[PRONTO_FREQ_OFFSET] * + PRONTO_FREQ_FACTOR)); + 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; + // 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; + + uint32_t periodic_time = calcUSecPeriod(hz, false); + + // Normal (1st sequence) case. + // Is there a first (normal) sequence to send? + if (seq_1_len > 0) { + // Check we have enough data to send the complete first sequence. + if (seq_1_len + seq_1_start > len) return; + // Send the contents of the 1st sequence. + for (uint16_t i = seq_1_start; i < seq_1_start + seq_1_len; i += 2) { + mark(data[i] * periodic_time); + space(data[i + 1] * periodic_time); + } + } else { + // There was no first sequence to send, it is implied that we have to send + // the 2nd/repeat sequence an additional time. i.e. At least once. + repeat++; + } + + // Repeat (2nd sequence) case. + // Is there a second (repeat) sequence to be sent? + if (seq_2_len > 0) { + // Check we have enough data to send the complete second sequence. + if (seq_2_len + seq_2_start > len) return; + + // Send the contents of the 2nd sequence. + for (uint16_t r = 0; r < repeat; r++) + for (uint16_t i = seq_2_start; i < seq_2_start + seq_2_len; i += 2) { + mark(data[i] * periodic_time); + space(data[i + 1] * periodic_time); + } + } +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp new file mode 100644 index 000000000..65aaf88d7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_RC5_RC6.cpp @@ -0,0 +1,514 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// RRRRRR CCCCC 555555 XX XX RRRRRR CCCCC 666 +// RR RR CC C 55 XX XX RR RR CC C 66 +// RRRRRR CC _____ 555555 XXXX RRRRRR CC _____ 666666 +// RR RR CC C 5555 XX XX RR RR CC C 66 66 +// RR RR CCCCC 555555 XX XX RR RR CCCCC 66666 + +// RC-5 & RC-6 support added from https://github.com/z3t0/Arduino-IRremote +// RC-5X support added by David Conran + +// Constants +// RC-5/RC-5X +// Ref: +// 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) +// 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) + +// Common (getRClevel()) +#define MARK 0U +#define SPACE 1U + + +#if SEND_RC5 +// Send a Philips RC-5/RC-5X packet. +// +// 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: RC-5 (stable), RC-5X (alpha) +// +// Note: +// Caller needs to take care of flipping the toggle bit. +// That bit differentiates between key press & key release. +// For RC-5 it is the MSB of the data. +// For RC-5X it is the 2nd MSB of the data. +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc5.php +// https://en.wikipedia.org/wiki/RC-5 +// https://en.wikipedia.org/wiki/Manchester_code +// 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. + 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? + // field bit is the inverted MSB of RC-5X data. + field_bit = ((data >> (nbits - 1)) ^ 1) & 1; + nbits--; + } + + IRtimer usecTimer = IRtimer(); + for (uint16_t i = 0; i <= repeat; i++) { + usecTimer.reset(); + + // Header + // First start bit (0x1). space, then mark. + if (skipSpace) + skipSpace = false; // First time through, we assume the leading space(). + else + space(RC5_T1); + mark(RC5_T1); + // Field/Second start bit. + if (field_bit) { // Send a 1. Normal for RC-5. + space(RC5_T1); + mark(RC5_T1); + } else { // Send a 0. Special case for RC-5X. Means 7th command bit is 1. + mark(RC5_T1); + space(RC5_T1); + } + + // 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); + } + // Footer + space(std::max(RC5_MIN_GAP, RC5_MIN_COMMAND_LENGTH - usecTimer.elapsed())); + } +} + +// Encode a Philips RC-5 data message. +// +// Args: +// address: The 5-bit address value for the message. +// command: The 6-bit command value for the message. +// key_released: Boolean flag indicating if the remote key has been released. +// +// Returns: +// A data message suitable for use in sendRC5(). +// +// Status: Beta / Should be working. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc5.php +// 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) | + (command & 0x3F); +} + +// Encode a Philips RC-5X data message. +// +// Args: +// address: The 5-bit address value for the message. +// command: The 7-bit command value for the message. +// key_released: Boolean flag indicating if the remote key has been released. +// +// Returns: +// A data message suitable for use in sendRC5(). +// +// Status: Beta / Should be working. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc5.php +// https://en.wikipedia.org/wiki/RC-5 +uint16_t IRsend::encodeRC5X(uint8_t address, uint8_t command, + bool key_released) { + // 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); +} + +// Flip the toggle bit of a Philips RC-5/RC-5X data message. +// Used to indicate a change of remote button's state. +// +// Args: +// data: The existing RC-5/RC-5X message. +// +// Returns: +// A data message suitable for use in sendRC5() with the toggle bit flipped. +// +// Status: STABLE. +// +// 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; +} +#endif // SEND_RC5 + +#if SEND_RC6 +// Flip the toggle bit of a Philips RC-6 data message. +// Used to indicate a change of remote button's state. +// For RC-6 (20-bits), it is the 17th least significant bit. +// for RC-6 (36-bits/Xbox-360), it is the 16th least significant bit. +// +// Args: +// data: The existing RC-6 message. +// nbits: Nr. of bits in the RC-6 protocol. +// +// Returns: +// A data message suitable for use in sendRC6() with the toggle bit flipped. +// +// Status: BETA / Should work fine. +// +// Ref: +// 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; +} + +// Encode a Philips RC-6 data message. +// +// Args: +// address: The address (aka. control) value for the message. +// Includes the field/mode/toggle bits. +// command: The 8-bit command value for the message. (aka. information) +// mode: Which protocol to use. Defined by nr. of bits in the protocol. +// +// Returns: +// A data message suitable for use in sendRC6(). +// +// Status: Beta / Should be working. +// +// Ref: +// 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) { + switch (mode) { + case RC6_MODE0_BITS: + return ((address & 0xFFF) << 8) | (command & 0xFF); + case RC6_36_BITS: + return ((uint64_t) (address & 0xFFFFFFF) << 8) | (command & 0xFF); + default: + return 0; + } +} + +// Send a Philips RC-6 packet. +// Note: Caller needs to take care of flipping the toggle bit (The 4th Most +// Significant Bit). That bit differentiates between key press & key release. +// +// 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. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc6.php +// http://www.righto.com/2010/12/64-bit-rc6-codes-arduino-and-xbox.html +// 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; + // 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); + // Start bit. + mark(RC6_TICK); // mark, then space == 0x1. + space(RC6_TICK); + // 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 + else + bitTime = RC6_TICK; // Normal bit + if (data & mask) { // 1 + mark(bitTime); + space(bitTime); + } else { // 0 + space(bitTime); + mark(bitTime); + } + } + // Footer + space(RC6_RPT_LENGTH); + } +} +#endif // SEND_RC6 + +#if (DECODE_RC5 || DECODE_RC6) +// 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, +// successive calls to getRClevel will return MARK, MARK, SPACE. +// offset and used are updated to keep track of the current position. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// offset: Ptr to the currect offset to the rawbuf. +// used: Ptr to the current used counter. +// bitTime: Time interval of single bit in microseconds. +// 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. + 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; + // 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; + + // 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 + return -1; // The width is not what we expected. + + (*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)++; + } + + return val; +} +#endif // (DECODE_RC5 || DECODE_RC6) + +#if DECODE_RC5 +// Decode the supplied RC-5/RC5X message. +// +// 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: RC-5 (stable), RC-5X (alpha) +// +// Note: +// The 'toggle' bit is included as the 6th (MSB) address bit, the MSB of data, +// & in the count of bits decoded. +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc5.php +// https://en.wikipedia.org/wiki/RC-5 +// https://en.wikipedia.org/wiki/Manchester_code +// 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; + + // Compliance + if (strict && nbits != RC5_BITS && nbits != RC5X_BITS) + return false; // It's neither RC-5 or RC-5X. + + uint16_t offset = OFFSET_START; + 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; + // 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. + 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. + is_rc5x = true; + data = 1; + } else { + return false; // Not what we expected. + } + + // 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) + data = (data << 1) | 1; // 1 + else if (levelA == MARK && levelB == SPACE) + data <<= 1; // 0 + else + break; + } + // Footer (None) + + // Compliance + if (actual_bits < nbits) return false; // Less data than we expected. + if (strict && actual_bits != RC5_BITS && + actual_bits != RC5X_BITS) return false; + + // Success + results->value = data; + results->address = (data >> 6) & 0x1F; + results->command = data & 0x3F; + results->repeat = false; + if (is_rc5x) { + results->decode_type = RC5X; + results->command |= ((uint32_t) is_rc5x) << 6; + } else { + results->decode_type = RC5; + actual_bits--; // RC5 doesn't count the field bit as data. + } + results->bits = actual_bits; + return true; +} +#endif // DECODE_RC5 + +#if DECODE_RC6 +// Decode the supplied RC6 message. +// +// 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: Stable. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/rc6.php +// https://en.wikipedia.org/wiki/Manchester_code +// 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. + return false; // Smaller than absolute smallest possible RC6 message. + + if (strict) { // Compliance + // Unlike typical protocols, the ability to have mark+space, and space+mark + // as data bits means it is possible to only have nbits of entries for the + // data portion, rather than the typically required 2 * nbits. + // 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) + return false; // Don't have enough entries/samples to be valid. + switch (nbits) { + case RC6_MODE0_BITS: + case RC6_36_BITS: + break; + default: + return false; // Asking for the wrong number of bits. + } + } + + uint16_t offset = OFFSET_START; + + // Header + if (!matchMark(results->rawbuf[offset], RC6_HDR_MARK)) 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)) + 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; + + uint16_t actual_bits; + uint64_t data = 0; + + // Data (Warning: Here be dragons^Wpointers!!) + for (actual_bits = 0; offset < results->rawlen; actual_bits++) { + 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)) + 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)) + return false; + if (levelA == MARK && levelB == SPACE) // reversed compared to RC5 + data = (data << 1) | 1; // 1 + else if (levelA == SPACE && levelB == MARK) + data <<= 1; // 0 + else + break; + } + + // More compliance + if (strict && actual_bits != nbits) + return false; // Actual nr. of bits didn't match expected. + + // Success + results->decode_type = RC6; + results->bits = actual_bits; + results->value = data; + results->address = data >> 8; + results->command = data & 0xFF; + return true; +} +#endif // DECODE_RC6 diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp new file mode 100644 index 000000000..362702b66 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_RCMM.cpp @@ -0,0 +1,174 @@ +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// RRRRRR CCCCC MM MM MM MM +// RR RR CC C MMM MMM MMM MMM +// RRRRRR CC _____ MM MM MM MM MM MM +// RR RR CC C MM MM MM MM +// RR RR CCCCC MM MM MM MM + +// Send & decode support for RC-MM added by David Conran + +// Constants +// Ref: +// http://www.sbprojects.com/knowledge/ir/rcmm.php +#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 +// Use a tolerance of +/-10% when matching some data spaces. +#define RCMM_TOLERANCE 10U +#define RCMM_EXCESS 50U + +#if SEND_RCMM +// Send a Philips RC-MM packet. +// +// Args: +// data: The data we want to send. MSB first. +// nbits: The number of bits of data to send. (Typically 12, 24, or 32[Nokia]) +// repeat: The nr. of times the message should be sent. +// +// Status: BETA / Should be working. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/rcmm.php +void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { + // Set 36kHz IR carrier frequency & a 1/3 (33%) duty cycle. + enableIROut(36, 33); + IRtimer usecs = IRtimer(); + + for (uint16_t r = 0; r <= repeat; r++) { + usecs.reset(); + // Header + mark(RCMM_HDR_MARK); + space(RCMM_HDR_SPACE); + // 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); + // 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; + } + 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)); + } +} +#endif + +#if DECODE_RCMM +// Decode a Philips RC-MM packet (between 12 & 32 bits) 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: Nr. of bits to expect in the data portion. Typically RCMM_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 be working. +// +// Ref: +// 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; + + 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); + // 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 < 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; + // 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; + // 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; + + // 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)) + 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)) + data += 0; + else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_1_TICKS * s_tick, + TOLERANCE)) + data += 1; + else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_2_TICKS * s_tick, + RCMM_TOLERANCE)) + data += 2; + else if (match(results->rawbuf[offset], RCMM_BIT_SPACE_3_TICKS * s_tick, + RCMM_TOLERANCE)) + data += 3; + else + return false; + } + // Footer decode + if (!match(results->rawbuf[offset++], RCMM_BIT_MARK_TICKS * m_tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], RCMM_MIN_GAP_TICKS * s_tick)) + return false; + + // Compliance + if (strict && actualBits != nbits) + return false; + + // Success + results->value = data; + results->decode_type = RCMM; + results->bits = actualBits; + results->address = 0; + results->command = 0; + return true; +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp new file mode 100644 index 000000000..dbd94bcd4 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Samsung.cpp @@ -0,0 +1,175 @@ +// 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_Sanyo.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp new file mode 100644 index 000000000..cbb13a329 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sanyo.cpp @@ -0,0 +1,239 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2016 marcosamarinho +// Copyright 2017 David Conran + +#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 +// SSS AAAAA N N N Y O O +// S A A N NN Y O O +// SSSS A A N N Y OOO + +// Sanyo SA 8650B originally added from: +// https://github.com/shirriff/Arduino-IRremote/ +// Sanyo LC7461 support originally by marcosamarinho + +// Constants +// 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 +// usually see 713 - not using ticks as get number wrapround +#define SANYO_SA8650B_DOUBLE_SPACE_USECS 800U +#define SANYO_SA8650B_RPT_LENGTH 45000U +// 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) + +#if SEND_SANYO +// Construct a Sanyo LC7461 message. +// +// Args: +// address: The 13 bit value of the address(Custom) portion of the protocol. +// command: The 8 bit value of the command(Key) portion of the protocol. +// Returns: +// An uint64_t with the encoded raw 42 bit Sanyo LC7461 data value. +// +// Notes: +// This protocol uses the NEC protocol timings. However, data is +// formatted as : address(13 bits), !address, command(8 bits), !command. +// 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; + + uint64_t data = address; + address ^= SANYO_LC7461_ADDRESS_MASK; // Invert the 13 LSBs. + // Append the now inverted address. + data = (data << SANYO_LC7461_ADDRESS_BITS) | address; + // Append the command. + data = (data << SANYO_LC7461_COMMAND_BITS) | command; + command ^= SANYO_LC7461_COMMAND_MASK; // Invert the command. + // Append the now inverted command. + data = (data << SANYO_LC7461_COMMAND_BITS) | command; + + return data; +} + +// Send a Sanyo LC7461 message. +// +// Args: +// data: The contents of the command you want to send. +// nbits: The bit size of the command being sent. +// repeat: The number of times you want the command to be repeated. +// +// Status: BETA / Probably works. +// +// Notes: +// Based on @marcosamarinho's work. +// This protocol uses the NEC protocol timings. However, data is +// formatted as : address(13 bits), !address, command (8 bits), !command. +// According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon +// Information for this protocol is available at the Sanyo LC7461 datasheet. +// Repeats are performed similar to the NEC method of sending a special +// repeat message, rather than duplicating the entire message. +// Ref: +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Sanyo.cpp +// http://pdf.datasheetcatalog.com/datasheet/sanyo/LC7461.pdf +void IRsend::sendSanyoLC7461(uint64_t data, uint16_t nbits, uint16_t repeat) { + // This protocol appears to be another 42-bit variant of the NEC protcol. + sendNEC(data, nbits, repeat); +} +#endif // SEND_SANYO + +#if DECODE_SANYO +// Decode the supplied SANYO LC7461 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 / Probably works. +// +// Notes: +// Based on @marcosamarinho's work. +// This protocol uses the NEC protocol. However, data is +// formatted as : address(13 bits), !address, command (8 bits), !command. +// According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon +// Information for this protocol is available at the Sanyo LC7461 datasheet. +// Ref: +// http://slydiman.narod.ru/scr/kb/sanyo.htm +// https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Sanyo.cpp +// 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) + 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); + // Bits 9 to 16. + uint8_t command = (results->value >> SANYO_LC7461_COMMAND_BITS) & + SANYO_LC7461_COMMAND_MASK; + // Compliance + if (strict) { + 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; + // Bits 1-8. + uint8_t inverted_command = results->value & SANYO_LC7461_COMMAND_MASK; + if ((address ^ SANYO_LC7461_ADDRESS_MASK) != inverted_address) + return false; // Address integrity check failed. + if ((command ^ SANYO_LC7461_COMMAND_MASK) != inverted_command) + return false; // Command integrity check failed. + } + + // Success + results->decode_type = SANYO_LC7461; + results->address = address; + results->command = command; + return true; +} + +/* NOTE: Disabled due to poor quality. +// Decode the supplied Sanyo SA 8650B 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: Depricated. +// +// NOTE: This decoder looks like rubbish. Only keeping it for compatibility +// with the Arduino IRremote library. Seriously, don't trust it. +// If someone has a device that this is supposed to be for, please log an +// Issue on github with a rawData dump please. We should probably remove +// it. We think this is a Sanyo decoder - serial = SA 8650B +// 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) + return false; // Shorter than shortest possible. + if (strict && nbits != SANYO_SA8650B_BITS) + return false; // Doesn't match the spec. + + uint16_t offset = 0; + + // 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) { + results->bits = 0; + results->value = REPEAT; + results->decode_type = SANYO; + results->address = 0; + results->command = 0; + results->repeat = true; + return true; + } + + // Header + if (!matchMark(results->rawbuf[offset++], SANYO_SA8650B_HDR_MARK)) + return false; + // NOTE: These next two lines look very wrong. Treat as suspect. + if (!matchMark(results->rawbuf[offset++], SANYO_SA8650B_HDR_MARK)) + return false; + // Data + uint64_t data = 0; + while (offset + 1 < results->rawlen) { + if (!matchSpace(results->rawbuf[offset], SANYO_SA8650B_HDR_SPACE)) + break; + offset++; + if (matchMark(results->rawbuf[offset], SANYO_SA8650B_ONE_MARK)) + data = (data << 1) | 1; // 1 + else if (matchMark(results->rawbuf[offset], SANYO_SA8650B_ZERO_MARK)) + data <<= 1; // 0 + else + return false; + offset++; + } + + if (strict && SANYO_SA8650B_BITS > (offset - 1U) / 2U) + return false; + + // Success + results->bits = (offset - 1) / 2; + results->decode_type = SANYO; + results->value = data; + results->address = 0; + results->command = 0; + return true; +} +*/ +#endif // DECODE_SANYO diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp new file mode 100644 index 000000000..1a0bb3556 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sharp.cpp @@ -0,0 +1,278 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// SSSS H H AAA RRRR PPPP +// S H H A A R R P P +// SSS HHHHH AAAAA RRRR PPPP +// S H H A A R R P +// SSSS H H A A R R P + +// 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) + +// 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) + +#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. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: BETA / Previously working fine. +// +// Notes: +// This procedure handles the inversion of bits required per protocol. +// The protocol spec says to send the LSB first, but legacy code & usage +// has us sending the MSB first. Grrrr. Normal invocation of encodeSharp() +// handles this for you, assuming you are using the correct/standard values. +// e.g. sendSharpRaw(encodeSharp(address, command)); +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/sharp.htm +// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA +// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf +// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp +void IRsend::sendSharpRaw(uint64_t data, uint16_t nbits, uint16_t repeat) { + // 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); + + // 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; + } + } +} + +// Encode a (raw) Sharp message from it's components. +// +// Args: +// address: The value of the address to be sent. +// command: The value of the address to be sent. (8 bits) +// expansion: The value of the expansion bit to use. (0 or 1, typically 1) +// check: The value of the check bit to use. (0 or 1, typically 0) +// MSBfirst: Flag indicating MSB first or LSB first order. (Default: false) +// Returns: +// An uint32_t containing the raw Sharp message for sendSharpRaw(). +// +// Status: BETA / Should work okay. +// +// Notes: +// Assumes the standard Sharp bit sizes. +// Historically sendSharp() sends address & command in +// MSB first order. This is actually incorrect. It should be sent in LSB +// order. The behaviour of sendSharp() hasn't been changed to maintain +// backward compatibility. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/sharp.htm +// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA +// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf +uint32_t IRsend::encodeSharp(uint16_t address, uint16_t command, + uint16_t expansion, uint16_t check, + bool MSBfirst) { + // Mask any unexpected bits. + address &= ((1 << SHARP_ADDRESS_BITS) - 1); + command &= ((1 << SHARP_COMMAND_BITS) - 1); + expansion &= 1; + check &= 1; + + if (!MSBfirst) { // Correct bit order if needed. + address = reverseBits(address, SHARP_ADDRESS_BITS); + command = reverseBits(command, SHARP_COMMAND_BITS); + } + // Concatinate all the bits. + return (address << (SHARP_COMMAND_BITS + 2)) | (command << 2) | + (expansion << 1) | check; +} + +// Send a Sharp message +// +// Args: +// address: Address value to be sent. +// command: Command value to be sent. +// nbits: Nr. of bits of data to be sent. Typically SHARP_BITS. +// repeat: Nr. of additional times the message is to be sent. +// +// Status: DEPRICATED / Previously working fine. +// +// Notes: +// This procedure has a non-standard invocation style compared to similar +// sendProtocol() routines. This is due to legacy, compatibility, & historic +// reasons. Normally the calling syntax version is like sendSharpRaw(). +// This procedure transmits the address & command in MSB first order, which is +// incorrect. This behaviour is left as-is to maintain backward +// compatibility with legacy code. +// In short, you should use sendSharpRaw(), encodeSharp(), and the correct +// values of address & command instead of using this, & the wrong values. +// +// Ref: +// http://www.sbprojects.com/knowledge/ir/sharp.htm +// http://lirc.sourceforge.net/remotes/sharp/GA538WJSA +// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf +void IRsend::sendSharp(uint16_t address, uint16_t command, uint16_t nbits, + uint16_t repeat) { + sendSharpRaw(encodeSharp(address, command, 1, 0, true), nbits, repeat); +} +#endif // (SEND_SHARP || SEND_DENON) + +#if (DECODE_SHARP || DECODE_DENON) +// Decode the supplied Sharp message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// nbits: Nr. of data bits to expect. Typically SHARP_BITS. +// 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. +// +// Note: +// This procedure returns a value suitable for use in sendSharpRaw(). +// TODO(crankyoldgit): Need to ensure capture of the inverted message as it can +// be missed due to the interrupt timeout used to detect an end of message. +// Several compliance checks are disabled until that is resolved. +// Ref: +// http://www.sbprojects.com/knowledge/ir/sharp.php +// http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf +// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp +bool IRrecv::decodeSharp(decode_results *results, uint16_t nbits, bool strict, + bool expansion) { + if (results->rawlen < 2 * nbits + FOOTER - 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. + // 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; +#endif + } + + uint64_t data = 0; + uint16_t offset = OFFSET_START; + + // No header + // But try to auto-calibrate off the initial mark signal. + if (!matchMark(results->rawbuf[offset], SHARP_BIT_MARK, 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; + // 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)) + return false; + if (matchSpace(results->rawbuf[offset], SHARP_ONE_SPACE_TICKS * tick)) + data = (data << 1) | 1; // 1 + else if (matchSpace(results->rawbuf[offset], SHARP_ZERO_SPACE_TICKS * tick)) + data <<= 1; // 0 + else + return false; + } + + // Footer + if (!match(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], SHARP_GAP_TICKS * tick)) + return false; + + // Compliance + if (strict) { + // Check the state of the expansion bit is what we expect. + if ((data & 0b10) >> 1 != expansion) + return false; + // The check bit should be cleared in a normal message. + if (data & 0b1) + return false; + // DISABLED - See TODO +#ifdef UNIT_TEST + // Grab the second copy of the data (i.e. inverted) + // Header + // i.e. The inter-data/command repeat gap. + if (!matchSpace(results->rawbuf[offset++], SHARP_GAP_TICKS * 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)) + return false; + if (matchSpace(results->rawbuf[offset], SHARP_ONE_SPACE_TICKS * tick)) + second_data = (second_data << 1) | 1; // 1 + else if (matchSpace(results->rawbuf[offset], + SHARP_ZERO_SPACE_TICKS * tick)) + second_data <<= 1; // 0 + else + return false; + } + // Footer + if (!match(results->rawbuf[offset++], SHARP_BIT_MARK_TICKS * tick)) + return false; + if (offset < results->rawlen && + !matchAtLeast(results->rawbuf[offset], SHARP_GAP_TICKS * tick)) + return false; + + // Check that second_data has been inverted correctly. + if (data != (second_data ^ SHARP_TOGGLE_MASK)) + return false; +#endif // UNIT_TEST + } + + // Success + results->decode_type = SHARP; + results->bits = nbits; + results->value = data; + // Address & command are actually transmitted in LSB first order. + results->address = reverseBits(data, nbits) & SHARP_ADDRESS_MASK; + results->command = reverseBits((data >> 2) & SHARP_COMMAND_MASK, + SHARP_COMMAND_BITS); + return true; +} +#endif // (DECODE_SHARP || DECODE_DENON) diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp new file mode 100644 index 000000000..97e75067a --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sherwood.cpp @@ -0,0 +1,29 @@ +// Copyright 2017 David Conran + +#include +#include "IRsend.h" + +// SSSSS HH HH EEEEEEE RRRRRR WW WW OOOOO OOOOO DDDDD +// SS HH HH EE RR RR WW WW OO OO OO OO DD DD +// SSSSS HHHHHHH EEEEE RRRRRR WW W WW OO OO OO OO DD DD +// SS HH HH EE RR RR WW WWW WW OO OO OO OO DD DD +// SSSSS HH HH EEEEEEE RR RR WW WW OOOO0 OOOO0 DDDDDD + +#if SEND_SHERWOOD +// Send an IR command to a Sherwood device. +// +// Args: +// data: The contents of the command you want to send. +// nbits: The bit size of the command being sent. (SHERWOOD_BITS) +// 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)); +} +#endif diff --git a/lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp new file mode 100644 index 000000000..fd2652d1d --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Sony.cpp @@ -0,0 +1,197 @@ +// Copyright 2009 Ken Shirriff +// Copyright 2016 marcosamarinho +// Copyright 2017 David Conran + +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRtimer.h" +#include "IRutils.h" + +// SSSS OOO N N Y Y +// S O O NN N Y Y +// SSS O O N N N Y +// S O O N NN Y +// SSSS OOO N N Y + +// Sony originally added from https://github.com/shirriff/Arduino-IRremote/ +// Updates from marcosamarinho + +// 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) + +#if SEND_SONY +// Send a Sony/SIRC(Serial Infra-Red Control) 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. (Default: 2) +// +// Status: STABLE / Known working. +// +// Notes: +// sendSony() should typically be called with repeat=2 as Sony devices +// expect the message to be sent at least 3 times. +// +// 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. +} + +// Convert Sony/SIRC command, address, & extended bits into sendSony format. +// Args: +// nbits: Sony protocol bit size. +// command: Sony command bits. +// address: Sony address bits. +// extended: Sony extended bits. +// Returns: +// 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 result = 0; + switch (nbits) { + case 12: // 5 address bits. + result = address & 0x1F; + break; + case 15: // 8 address bits. + result = address & 0xFF; + break; + case 20: // 5 address bits, 8 extended bits. + result = address & 0x1F; + result |= (extended & 0xFF) << 5; + break; + default: + return 0; // This is not an expected Sony bit size/protocol. + } + result = (result << 7) | (command & 0x7F); // All sizes have 7 command bits. + return reverseBits(result, nbits); // sendSony uses reverse ordered bits. +} +#endif + +#if DECODE_SONY +// Decode the supplied Sony/SIRC message. +// +// 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 / Should be working. strict mode is ALPHA / Untested. +// +// Notes: +// SONY protocol, SIRC (Serial Infra-Red Control) can be 12,15,20 bits long. +// 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) + return false; // Message is smaller than we expected. + + // Compliance + if (strict) { + switch (nbits) { // Check we've been called with a correct bit size. + case 12: + case 15: + case 20: + break; + default: + return false; // The request doesn't strictly match the protocol defn. + } + } + + uint64_t data = 0; + uint16_t offset = OFFSET_START; + 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; + // Calculate how long the common tick time is based on the header mark. + uint32_t tick = results->rawbuf[offset++] * RAWTICK / SONY_HDR_MARK_TICKS; + + // 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)) + break; // Found a repeat space. + timeSoFar += results->rawbuf[offset] * RAWTICK; + if (!matchSpace(results->rawbuf[offset++], SONY_SPACE_TICKS * tick)) + return false; + timeSoFar += results->rawbuf[offset] * RAWTICK; + if (matchMark(results->rawbuf[offset], SONY_ONE_MARK_TICKS * tick)) + data = (data << 1) | 1; + else if (matchMark(results->rawbuf[offset], SONY_ZERO_MARK_TICKS * tick)) + data <<= 1; + else + return false; + } + // No Footer for Sony. + + // Compliance + if (strict && actualBits != nbits) + return false; // We got the wrong number of bits. + + // Success + results->bits = actualBits; + results->value = data; + results->decode_type = SONY; + // Message comes in LSB first. Convert ot MSB first. + 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. + results->command = data & 0x7F; // Bits 0-6 + 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 + break; + default: // Shouldn't happen, but just in case. + results->address = 0; + results->command = 0; + } + 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 new file mode 100644 index 000000000..ef8e9efa6 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.cpp @@ -0,0 +1,151 @@ +// 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 new file mode 100644 index 000000000..01ac13c59 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Trotec.h @@ -0,0 +1,80 @@ +// 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 new file mode 100644 index 000000000..4efb2c570 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/src/ir_Whynter.cpp @@ -0,0 +1,144 @@ +// 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/IRrecv_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp new file mode 100644 index 000000000..4b22656f6 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/IRrecv_test.cpp @@ -0,0 +1,448 @@ +// Copyright 2017 David Conran + +#include "IRremoteESP8266.h" +#include "IRrecv.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for the IRrecv object. +TEST(TestIRrecv, DefaultBufferSize) { + IRrecv irrecv_default(1); + EXPECT_EQ(RAWBUF, irrecv_default.getBufSize()); +} + +TEST(TestIRrecv, LargeBufferSize) { + IRrecv irrecv_large(3, 1024); + EXPECT_EQ(1024, irrecv_large.getBufSize()); +} + +TEST(TestIRrecv, SmallBufferSize) { + IRrecv irrecv_small(4, 80); + EXPECT_EQ(80, irrecv_small.getBufSize()); +} + +TEST(TestIRrecv, MediumBufferSize) { + IRrecv irrecv_medium(4, 512); + EXPECT_EQ(512, irrecv_medium.getBufSize()); +} + +TEST(TestIRrecv, IRrecvDestructor) { + IRrecv *irrecv_ptr = new IRrecv(1); + EXPECT_EQ(RAWBUF, irrecv_ptr->getBufSize()); + + delete irrecv_ptr; + irrecv_ptr = new IRrecv(1, 1234); + EXPECT_EQ(1234, irrecv_ptr->getBufSize()); + delete irrecv_ptr; + + irrecv_ptr = new IRrecv(1, 123); + EXPECT_EQ(123, irrecv_ptr->getBufSize()); + delete irrecv_ptr; +} + +// Tests for copyIrParams() + +TEST(TestCopyIrParams, CopyEmpty) { + irparams_t src; + irparams_t dst; + uint16_t test_size = 1234; + src.bufsize = test_size; + src.rawlen = 0; + src.rawbuf = new uint16_t[test_size]; + src.overflow = false; + dst.bufsize = 4567; + dst.rawlen = 123; + dst.rawbuf = new uint16_t[test_size]; + dst.overflow = true; + // Confirm we are looking at different memory for the buffers. + ASSERT_NE(src.rawbuf, dst.rawbuf); + + IRrecv irrecv(4); + irrecv.copyIrParams(&src, &dst); + + ASSERT_EQ(src.bufsize, dst.bufsize); + ASSERT_EQ(src.rawlen, dst.rawlen); + ASSERT_NE(src.rawbuf, dst.rawbuf); // Pointers, not content. + ASSERT_EQ(src.overflow, dst.overflow); + // Contents of the buffers needs to match. + EXPECT_EQ(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t))); +} + +TEST(TestCopyIrParams, CopyNonEmpty) { + irparams_t src; + irparams_t dst; + uint16_t test_size = 1234; + src.bufsize = test_size; + src.rawlen = 67; + src.rawbuf = new uint16_t[test_size]; + src.rawbuf[0] = 0xF00D; + src.rawbuf[1] = 0xBEEF; + src.rawbuf[test_size - 1] = 0xDEAD; + src.overflow = true; + dst.bufsize = 0; + dst.rawlen = 0; + dst.rawbuf = new uint16_t[test_size]; + dst.overflow = false; + // Confirm we are looking at different memory for the buffers. + ASSERT_NE(src.rawbuf, dst.rawbuf); + // and that they differ before we test. + EXPECT_NE(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t))); + + IRrecv irrecv(4); + irrecv.copyIrParams(&src, &dst); + + ASSERT_EQ(src.bufsize, dst.bufsize); + EXPECT_EQ(test_size, dst.bufsize); + ASSERT_EQ(src.rawlen, dst.rawlen); + EXPECT_EQ(67, dst.rawlen); + ASSERT_EQ(src.overflow, dst.overflow); + EXPECT_TRUE(dst.overflow); + ASSERT_NE(src.rawbuf, dst.rawbuf); // Pointers, not content. + // Contents of the buffers needs to match. + EXPECT_EQ(0, memcmp(src.rawbuf, dst.rawbuf, src.bufsize * sizeof(uint16_t))); + // Check the canary values. + EXPECT_EQ(0xF00D, dst.rawbuf[0]); + EXPECT_EQ(0xBEEF, dst.rawbuf[1]); + EXPECT_EQ(0xDEAD, dst.rawbuf[test_size - 1]); +} + +// Tests for decode(). + +// Test decode of a NEC message. +TEST(TestDecode, DecodeNEC) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendNEC(0x807F40BF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(0x807F40BF, irsend.capture.value); +} + +// Test decode of a JVC message. +TEST(TestDecode, DecodeJVC) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendJVC(0xC2B8); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); +} + +// Test decode of a LG message. +TEST(TestDecode, DecodeLG) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendLG(0x4B4AE51); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(0x4B4AE51, irsend.capture.value); + + irsend.reset(); + irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(0xB4B4AE51, irsend.capture.value); +} + +// Test decode of a Panasonic message. +TEST(TestDecode, DecodePanasonic) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendPanasonic64(0x40040190ED7C); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, PANASONIC_BITS, true)); + EXPECT_EQ(PANASONIC, irsend.capture.decode_type); + EXPECT_EQ(PANASONIC_BITS, irsend.capture.bits); + EXPECT_EQ(0x40040190ED7C, irsend.capture.value); +} + +// Test decode of a Samsun message. +TEST(TestDecode, DecodeSamsung) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendSAMSUNG(0xE0E09966); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); + EXPECT_EQ(SAMSUNG_BITS, irsend.capture.bits); + EXPECT_EQ(0xE0E09966, irsend.capture.value); +} + +// Test decode of a Sherwood message. +TEST(TestDecode, DecodeSherwood) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendSherwood(0x807F40BF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + // Sherwood codes are really NEC codes. + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(0x807F40BF, irsend.capture.value); +} + +// Test decode of a Whynter message. +TEST(TestDecode, DecodeWhynter) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendWhynter(0x87654321); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(0x87654321, irsend.capture.value); +} + +// Test decode of Sony messages. +TEST(TestDecode, DecodeSony) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Synthesised Normal Sony 20-bit message. + irsend.reset(); + irsend.sendSony(irsend.encodeSony(SONY_20_BITS, 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(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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(SONY_15_BITS, 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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SONY, irsend.capture.decode_type); + EXPECT_EQ(SONY_12_BITS, irsend.capture.bits); + EXPECT_EQ(0xA90, irsend.capture.value); +} + +// Test decode of Sharp messages. +TEST(TestDecode, DecodeSharp) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendSharpRaw(0x454A); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(0x454A, irsend.capture.value); +} + +// Test decode of Sanyo messages. +TEST(TestDecode, DecodeSanyo) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendSanyoLC7461(0x2468DCB56A9); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); + EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(0x2468DCB56A9, irsend.capture.value); +} + +// Test decode of RC-MM messages. +TEST(TestDecode, DecodeRCMM) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Normal RCMM 24-bit message. + irsend.reset(); + irsend.sendRCMM(0xe0a600); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(RCMM_BITS, irsend.capture.bits); + EXPECT_EQ(0xe0a600, irsend.capture.value); + + // Normal RCMM 12-bit message. + irsend.reset(); + irsend.sendRCMM(0x600, 12); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(12, irsend.capture.bits); + EXPECT_EQ(0x600, irsend.capture.value); + + // Normal RCMM 32-bit message. + irsend.reset(); + irsend.sendRCMM(0x28e0a600, 32); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x28e0a600, irsend.capture.value); +} + +// Test decode of Mitsubishi messages. +TEST(TestDecode, DecodeMitsubishi) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendMitsubishi(0xC2B8); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); + EXPECT_EQ(MITSUBISHI_BITS, irsend.capture.bits); + EXPECT_EQ(0xC2B8, irsend.capture.value); +} + +// Test decode of RC-5/RC-5X messages. +TEST(TestDecode, DecodeRC5) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + // Normal RC-5 12-bit message. + irsend.reset(); + irsend.sendRC5(0x175); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(RC5_BITS, 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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RC5X, irsend.capture.decode_type); + EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(0x1881, irsend.capture.value); +} + +// Test decode of RC-6 messages. +TEST(TestDecode, DecodeRC6) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + // Normal RC-6 Mode 0 (20-bit) message. + irsend.reset(); + irsend.sendRC6(0x175); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + + // Normal RC-6 36-bit message. + irsend.reset(); + irsend.sendRC6(0xC800F742A, RC6_36_BITS); + 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(0xC800F742A, irsend.capture.value); +} + +// Test decode of Dish messages. +TEST(TestDecode, DecodeDish) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendDISH(0x9C00); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(DISH_BITS, irsend.capture.bits); + EXPECT_EQ(0x9C00, irsend.capture.value); +} + +// Test decode of Denon messages. +TEST(TestDecode, DecodeDenon) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + // Normal Denon 15-bit message. (Sharp) + irsend.reset(); + irsend.sendDenon(0x2278); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_BITS, irsend.capture.bits); + EXPECT_EQ(0x2278, irsend.capture.value); + // Legacy Denon 14-bit message. + irsend.reset(); + irsend.sendDenon(0x1278, DENON_LEGACY_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_BITS, irsend.capture.bits); + EXPECT_EQ(0x1278, irsend.capture.value); + // Normal Denon 48-bit message. (Panasonic/Kaseikyo) + irsend.reset(); + irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_48_BITS, irsend.capture.bits); + EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value); +} + +// Test decode of Coolix messages. +TEST(TestDecode, DecodeCoolix) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendCOOLIX(0x123456); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(0x123456, irsend.capture.value); +} + +// Test decode of Aiwa messages. +TEST(TestDecode, DecodeAiwa) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + irsend.reset(); + irsend.sendAiwaRCT501(0x7F); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(0x7F, irsend.capture.value); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp new file mode 100644 index 000000000..3b18ae582 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.cpp @@ -0,0 +1,139 @@ +// 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 new file mode 100644 index 000000000..94de487af --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/IRsend_test.h @@ -0,0 +1,106 @@ +// 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 new file mode 100644 index 000000000..3b4c4145a --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/IRutils_test.cpp @@ -0,0 +1,91 @@ +// 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/Makefile b/lib/IRremoteESP8266-2.2.1.02/test/Makefile new file mode 100644 index 000000000..7ffd00053 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/Makefile @@ -0,0 +1,348 @@ +# SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project, except GTEST_HEADERS, which you can use in your own targets +# but shouldn't modify. + +# Points to the root of Google Test, relative to where this file is. +# Remember to tweak this if you move this file. +GTEST_DIR = ../lib/googletest/googletest + +# Where to find user code. +USER_DIR = ../src + +# Flags passed to the preprocessor. +# Set Google Test's header directory as a system directory, such that +# the compiler doesn't generate warnings in Google Test headers. +CPPFLAGS += -isystem $(GTEST_DIR)/include -DUNIT_TEST + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra -pthread + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. +TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \ + ir_Sherwood_test ir_Sony_test ir_Samsung_test ir_Kelvinator_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 + +# All Google Test headers. Usually you shouldn't change this +# definition. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# House-keeping build targets. + +all : $(TESTS) + +clean : + rm -f $(TESTS) gtest.a gtest_main.a *.o + +# Build and run all the tests. +run : all + failed=""; \ + for unittest in $(TESTS); do \ + ./$${unittest} || failed="$${failed} $${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 + +install-googletest : + git clone https://github.com/google/googletest.git ../lib/googletest + +# Builds gtest.a and gtest_main.a. + +# Usually you shouldn't tweak such internal variables, indicated by a +# trailing _. +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 +# 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 +# Common test dependencies +COMMON_TEST_DEPS = $(COMMON_DEPS) IRsend_test.h + +# For simplicity and to avoid depending on Google Test's +# implementation details, the dependencies specified below are +# conservative and not optimized. This is fine as Google Test +# compiles fast and for ordinary users its source rarely changes. +gtest-all.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest-all.cc + +gtest_main.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest_main.cc + +gtest.a : gtest-all.o + $(AR) $(ARFLAGS) $@ $^ + +gtest_main.a : gtest-all.o gtest_main.o + $(AR) $(ARFLAGS) $@ $^ + +# Builds a 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 + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp + +IRutils_test.o : IRutils_test.cpp $(USER_DIR)/IRutils.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRutils_test.cpp + +IRutils_test : IRutils.o IRutils_test.o gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRtimer.cpp + +IRsend.o : $(USER_DIR)/IRsend.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRremoteESP8266.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRsend.cpp + +IRsend_test.o : IRsend_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRsend_test.cpp + +IRsend_test : IRsend_test.o $(COMMON_OBJ) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP8266.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRrecv.cpp + +IRrecv_test.o : IRrecv_test.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRrecv.h IRsend_test.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c IRrecv_test.cpp + +IRrecv_test : IRrecv_test.o $(COMMON_OBJ) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp + +ir_NEC_test.o : ir_NEC_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_NEC_test.cpp + +ir_NEC_test : $(COMMON_OBJ) ir_NEC_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_GlobalCache.o : $(USER_DIR)/ir_GlobalCache.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GlobalCache.cpp + +ir_GlobalCache_test.o : ir_GlobalCache_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_GlobalCache_test.cpp + +ir_GlobalCache_test : $(COMMON_OBJ) ir_GlobalCache_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Sherwood.o : $(USER_DIR)/ir_Sherwood.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sherwood.cpp + +ir_Sherwood_test.o : ir_Sherwood_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sherwood_test.cpp + +ir_Sherwood_test : $(COMMON_OBJ) ir_Sherwood_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Sony.o : $(USER_DIR)/ir_Sony.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sony.cpp + +ir_Sony_test.o : ir_Sony_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sony_test.cpp + +ir_Sony_test : $(COMMON_OBJ) ir_Sony_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp + +ir_Samsung_test.o : ir_Samsung_test.cpp $(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 + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Kelvinator.cpp + +ir_Kelvinator_test.o : ir_Kelvinator_test.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Kelvinator_test.cpp + +ir_Kelvinator_test : $(COMMON_OBJ) ir_Kelvinator_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_JVC.o : $(USER_DIR)/ir_JVC.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_JVC.cpp + +ir_JVC_test.o : ir_JVC_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_JVC_test.cpp + +ir_JVC_test : $(COMMON_OBJ) ir_JVC_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_RCMM.o : $(USER_DIR)/ir_RCMM.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RCMM.cpp + +ir_RCMM_test.o : ir_RCMM_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_RCMM_test.cpp + +ir_RCMM_test : $(COMMON_OBJ) ir_RCMM_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_LG.o : $(USER_DIR)/ir_LG.h $(USER_DIR)/ir_LG.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_LG.cpp + +ir_LG_test.o : ir_LG_test.cpp $(USER_DIR)/ir_LG.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_LG_test.cpp + +ir_LG_test : $(COMMON_OBJ) ir_LG_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Mitsubishi.o : $(USER_DIR)/ir_Mitsubishi.h $(USER_DIR)/ir_Mitsubishi.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Mitsubishi.cpp + +ir_Mitsubishi_test.o : ir_Mitsubishi_test.cpp $(USER_DIR)/ir_Mitsubishi.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Mitsubishi_test.cpp + +ir_Mitsubishi_test : $(COMMON_OBJ) ir_Mitsubishi_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Fujitsu.o : $(USER_DIR)/ir_Fujitsu.h $(USER_DIR)/ir_Fujitsu.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Fujitsu.cpp + +ir_Fujitsu_test.o : ir_Fujitsu_test.cpp $(USER_DIR)/ir_Fujitsu.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Fujitsu_test.cpp + +ir_Fujitsu_test : $(COMMON_OBJ) ir_Fujitsu_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp + +ir_Sharp_test.o : ir_Sharp_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sharp_test.cpp + +ir_Sharp_test : $(COMMON_OBJ) ir_Sharp_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_RC5_RC6.o : $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RC5_RC6.cpp + +ir_RC5_RC6_test.o : ir_RC5_RC6_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_RC5_RC6_test.cpp + +ir_RC5_RC6_test : $(COMMON_OBJ) ir_RC5_RC6_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Panasonic.o : $(USER_DIR)/ir_Panasonic.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Panasonic.cpp + +ir_Panasonic_test.o : ir_Panasonic_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Panasonic_test.cpp + +ir_Panasonic_test : $(COMMON_OBJ) ir_Panasonic_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Dish.o : $(USER_DIR)/ir_Dish.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Dish.cpp + +ir_Dish_test.o : ir_Dish_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Dish_test.cpp + +ir_Dish_test : $(COMMON_OBJ) ir_Dish_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Whynter.o : $(USER_DIR)/ir_Whynter.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whynter.cpp + +ir_Whynter_test.o : ir_Whynter_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Whynter_test.cpp + +ir_Whynter_test : $(COMMON_OBJ) ir_Whynter_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -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) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Coolix_test.cpp + +ir_Coolix_test : $(COMMON_OBJ) ir_Coolix_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Aiwa.o : $(USER_DIR)/ir_Aiwa.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Aiwa.cpp + +ir_Aiwa_test.o : ir_Aiwa_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Aiwa_test.cpp + +ir_Aiwa_test : $(COMMON_OBJ) ir_Aiwa_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Denon.o : $(USER_DIR)/ir_Denon.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Denon.cpp + +ir_Denon_test.o : ir_Denon_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Denon_test.cpp + +ir_Denon_test : $(COMMON_OBJ) ir_Denon_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Sanyo.o : $(USER_DIR)/ir_Sanyo.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sanyo.cpp + +ir_Sanyo_test.o : ir_Sanyo_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Sanyo_test.cpp + +ir_Sanyo_test : $(COMMON_OBJ) ir_Sanyo_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Daikin.o : $(USER_DIR)/ir_Daikin.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Daikin.cpp + +ir_Daikin_test.o : ir_Daikin_test.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Daikin_test.cpp + +ir_Daikin_test : $(COMMON_OBJ) ir_Daikin_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Gree.cpp + +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 + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pronto.cpp + +ir_Pronto_test.o : ir_Pronto_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Pronto_test.cpp + +ir_Pronto_test : $(COMMON_OBJ) ir_Pronto_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Nikai.o : $(USER_DIR)/ir_Nikai.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Nikai.cpp + +ir_Nikai_test.o : ir_Nikai_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_Nikai_test.cpp + +ir_Nikai_test : $(COMMON_OBJ) ir_Nikai_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.2.1.02/test/ir_Aiwa_test.cpp new file mode 100644 index 000000000..a0bb12f86 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Aiwa_test.cpp @@ -0,0 +1,338 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendAiwaRCT501(). + +// Test sending typical data only. +TEST(TestSendAiwa, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendAiwaRCT501(0x7F); // Aiwa Power Toggle. + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s108080" + "m8960s2240m560s108080", irsend.outputStr()); +} + +// Test sending oversized data. +TEST(TestSendAiwa, SendOversizedData) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendAiwaRCT501(0x7F, 38); // 38 bits is over the maximum. Should fail. + EXPECT_EQ("", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendAiwa, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 0); // No repeats. + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s108080", irsend.outputStr()); + irsend.reset(); + irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s108080" + "m8960s2240m560s108080", irsend.outputStr()); + irsend.reset(); + irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 2); // 2 repeats. + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s108080" + "m8960s2240m560s108080" + "m8960s2240m560s108080", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendAiwa, SendUsualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendAiwaRCT501(0x12, 8); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s1680m560s108080" + "m8960s2240m560s108080", irsend.outputStr()); + + irsend.reset(); + irsend.sendAiwaRCT501(0x1234567890, 37); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560m560s1680" + "m560s560m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680" + "m560s108080" + "m8960s2240m560s108080", irsend.outputStr()); +} + +// Tests for decodeAiwaRCT501(). + +// Decode normal Aiwa messages. +TEST(TestDecodeAiwa, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Aiwa 15-bit(42bit) message. + irsend.reset(); + irsend.sendAiwaRCT501(0x7F); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + true)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(0x7F, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Aiwa 15-bit(42bit) message. + irsend.reset(); + irsend.sendAiwaRCT501(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + true)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(AIWA_RC_T501_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); + + // Normal Aiwa 15-bit(42bit) message. + irsend.reset(); + irsend.sendAiwaRCT501(0x7FFF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + true)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(0x7FFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Aiwa messages. +TEST(TestDecodeAiwa, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Aiwa 15-bit(42bit) message with 2 repeats. + irsend.reset(); + irsend.sendAiwaRCT501(0x7F, AIWA_RC_T501_BITS, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + true)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(AIWA_RC_T501_BITS, irsend.capture.bits); + EXPECT_EQ(0x7F, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode unsupported Aiwa messages. +TEST(TestDecodeAiwa, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Confirm using sendNEC(data, 42, 1) can make a legal Aiwa message. + irsend.sendNEC(0x1D8113F00FF, 42, AIWA_RC_T501_MIN_REPEAT); + irsend.makeDecodeResult(); + // MUST pass with strict on. + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + 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.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + true)); + // Should fail if strict off too. + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + 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.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + true)); + // Should fail if strict off too. + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + 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.makeDecodeResult(); + // Should fail with strict on. + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + true)); + // Should fail if strict off too. + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + false)); +} + +// Decode unsupported Aiwa messages. +TEST(TestDecodeAiwa, DecodeWithNonStrictSizes) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + 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)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 8, false)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x0, irsend.capture.value); + + irsend.reset(); + 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)); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, 32, true)); + + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 32, false)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeAiwa, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Aiwa 37(64)-bit message. + irsend.sendAiwaRCT501(0x1FFFFFFFFF, 37); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 37, false)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(37, irsend.capture.bits); + EXPECT_EQ(0x1FFFFFFFFF, irsend.capture.value); + + // 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.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 37, false)); + EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); + EXPECT_EQ(37, irsend.capture.bits); + EXPECT_EQ(0x1FFFFFFFFF, irsend.capture.value); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeAiwa, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + 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}; + 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(0x7F, irsend.capture.value); + EXPECT_EQ(0x0, 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); +} + +// Fail to decode a non-Aiwa example via GlobalCache +TEST(TestDecodeAiwa, FailToDecodeNonAiwaExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + 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}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, AIWA_RC_T501_BITS, + false)); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp new file mode 100644 index 000000000..14eb8d661 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Coolix_test.cpp @@ -0,0 +1,290 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendCOOLIX(). + +// Test sending typical data only. +TEST(TestSendCoolix, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendCOOLIX(0x0); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5040", irsend.outputStr()); + + irsend.reset(); + irsend.sendCOOLIX(0xAA55AA); + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5040", irsend.outputStr()); + + irsend.reset(); + irsend.sendCOOLIX(0xFFFFFF); + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s5040", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendCoolix, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendCOOLIX(0xAA55AA, COOLIX_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5040" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5040", irsend.outputStr()); + irsend.sendCOOLIX(0xAA55AA, COOLIX_BITS, 2); // 2 repeats. + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5040" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5040" + "m4480s4480" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680" + "m560s5040", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendCoolix, SendUsualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendCOOLIX(0x0, 8); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s5040", irsend.outputStr()); + + irsend.reset(); + irsend.sendCOOLIX(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680m560s560" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560m560s1680" + "m560s560m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s1680m560s560m560s560m560s1680m560s560m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560m560s1680" + "m560s560m560s1680m560s1680m560s1680m560s1680m560s560m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s560m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s1680" + "m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m560s560m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s560" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s560m560s560m560s560m560s1680m560s560m560s560m560s560m560s560" + "m560s5040", irsend.outputStr()); + + // Bit sizes must be a multiple of 8. + irsend.reset(); + irsend.sendCOOLIX(0x0, 17); + EXPECT_EQ("" , irsend.outputStr()); +} + +// Tests for decodeCOOLIX(). + +// Decode normal Coolix messages. +TEST(TestDecodeCoolix, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Coolix 24-bit message. + irsend.reset(); + irsend.sendCOOLIX(0x123456); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(0x123456, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Coolix 24-bit message. + irsend.reset(); + irsend.sendCOOLIX(0x0); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(COOLIX_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); + + // Normal Coolix 24-bit message. + irsend.reset(); + irsend.sendCOOLIX(0xFFFFFF); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(0xFFFFFF, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Coolix messages. +TEST(TestDecodeCoolix, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Coolix 16-bit message with 2 repeats. + irsend.reset(); + irsend.sendCOOLIX(0x123456, COOLIX_BITS, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, true)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(COOLIX_BITS, 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)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(COOLIX_BITS, 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)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(COOLIX_BITS, irsend.capture.bits); + EXPECT_EQ(0x123456, irsend.capture.value); +} + +// Decode unsupported Coolix messages. +TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + 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)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 8, false)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x12, irsend.capture.value); + + irsend.reset(); + 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)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 32, false)); + EXPECT_EQ(COOLIX, 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.sendCOOLIX(0x123456, COOLIX_BITS, 2); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, 9, false)); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeCoolix, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal size Coolix 64-bit message. + irsend.sendCOOLIX(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 64, false)); + EXPECT_EQ(COOLIX, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); +} + +// Fail to decode a non-Coolix example via GlobalCache +TEST(TestDecodeCoolix, FailToDecodeNonCoolixExample) { + 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.decodeCOOLIX(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, COOLIX_BITS, false)); +} 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 new file mode 100644 index 000000000..b516008c1 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Daikin_test.cpp @@ -0,0 +1,419 @@ +// 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_Denon_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp new file mode 100644 index 000000000..32de11b46 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Denon_test.cpp @@ -0,0 +1,272 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendDenon(). + +// Test sending typical data only. +TEST(TestSendDenon, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDenon(0x2278); // Denon AVR Power On. (Sharp) + EXPECT_EQ( + "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" + "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" + "m260s43602", irsend.outputStr()); + + irsend.reset(); + // Denon Eco Mode On. (Panasonic/Kaseikyo) + irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s1296m432s432" + "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" + "m432s129600", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendDenon, SendNormalWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDenon(0x2278, DENON_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" + "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" + "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" + "m260s43602", irsend.outputStr()); + irsend.sendDenon(0x2278, DENON_BITS, 2); // 2 repeats. + EXPECT_EQ( + "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" + "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" + "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s1820m260s780m260s780" + "m260s1820m260s1820m260s1820m260s1820m260s780m260s780m260s780" + "m260s43602" + "m260s780m260s1820m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s780m260s780m260s780m260s780m260s1820m260s1820m260s1820" + "m260s43602", irsend.outputStr()); +} + +TEST(TestSendDenon, Send48BitWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s1296m432s432" + "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" + "m432s129600" + "m3456s1728" + "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s1296m432s432" + "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" + "m432s129600", irsend.outputStr()); + irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS, 2); // 2 repeats. + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s1296m432s432" + "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" + "m432s129600" + "m3456s1728" + "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s1296m432s432" + "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" + "m432s129600" + "m3456s1728" + "m432s432m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s432" + "m432s432m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s1296m432s432" + "m432s1296m432s432m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s432m432s1296m432s1296m432s432m432s1296m432s1296m432s432m432s432" + "m432s1296m432s1296m432s1296m432s432m432s432m432s432m432s1296m432s1296" + "m432s129600", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendDenon, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDenon(0x12, 8); + EXPECT_EQ( + "m260s780m260s780m260s780m260s1820m260s780m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s1820m260s1820m260s780m260s1820m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); + + irsend.reset(); + irsend.sendDenon(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m3456s1728" + "m432s432m432s432m432s432m432s1296m432s432m432s432m432s1296m432s432" + "m432s432m432s432m432s1296m432s1296m432s432m432s1296m432s432m432s432" + "m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296m432s432" + "m432s432m432s1296m432s1296m432s1296m432s1296m432s432m432s432m432s432" + "m432s1296m432s432m432s432m432s1296m432s432m432s432m432s432m432s432" + "m432s1296m432s432m432s1296m432s432m432s1296m432s432m432s1296m432s1296" + "m432s1296m432s1296m432s432m432s432m432s1296m432s1296m432s432m432s1296" + "m432s1296m432s1296m432s1296m432s432m432s1296m432s1296m432s1296m432s1296" + "m432s129600", irsend.outputStr()); +} + +// Tests for decodeDenon(). + +// Decode normal Denon messages. +TEST(TestDecodeDenon, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Denon 15-bit message. (Sharp) + irsend.reset(); + irsend.sendDenon(0x2278); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_BITS, true)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_BITS, irsend.capture.bits); + EXPECT_EQ(0x2278, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); + EXPECT_EQ(0x79, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Legacy Denon 14-bit message. + irsend.reset(); + irsend.sendDenon(0x1278, DENON_LEGACY_BITS); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_LEGACY_BITS, true)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_LEGACY_BITS, irsend.capture.bits); + EXPECT_EQ(0x1278, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Denon 48-bit message. (Panasonic/Kaseikyo) + irsend.reset(); + irsend.sendDenon(0x2A4C028D6CE3, DENON_48_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_48_BITS, true)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_48_BITS, irsend.capture.bits); + EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value); + EXPECT_EQ(0x2A4C, irsend.capture.address); + EXPECT_EQ(0x028D6CE3, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeDenon, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + 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}; + irsend.sendGC(gc_test_power, 67); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_BITS, true)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_BITS, irsend.capture.bits); + EXPECT_EQ(0x2278, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); + EXPECT_EQ(0x79, irsend.capture.command); + 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}; + irsend.reset(); + irsend.sendGC(gc_test_eco, 103); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, DENON_48_BITS, true)); + EXPECT_EQ(DENON, irsend.capture.decode_type); + EXPECT_EQ(DENON_48_BITS, irsend.capture.bits); + EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value); + EXPECT_EQ(0x2A4C, irsend.capture.address); + EXPECT_EQ(0x028D6CE3, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-Denon example via GlobalCache +TEST(TestDecodeDenon, FailToDecodeNonDenonExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + 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}; + 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, 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.2.1.02/test/ir_Dish_test.cpp new file mode 100644 index 000000000..afd76e8fd --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Dish_test.cpp @@ -0,0 +1,321 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendDISH(). + +// Test sending typical data only. +TEST(TestSendDish, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDISH(0x0); + EXPECT_EQ( + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", irsend.outputStr()); + + irsend.reset(); + irsend.sendDISH(0x9C00); // Power on. + EXPECT_EQ( + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", irsend.outputStr()); + + irsend.reset(); + irsend.sendDISH(0xFFFF); + EXPECT_EQ( + "m400s6100" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s6100" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s6100" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s6100" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700m400s1700" + "m400s6100", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendDish, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDISH(0x9C00, DISH_BITS, 0); // 0 repeats. + EXPECT_EQ( + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", irsend.outputStr()); + + irsend.reset(); + irsend.sendDISH(0x9C00, DISH_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", irsend.outputStr()); + + irsend.sendDISH(0x9C00, DISH_BITS, 2); // 2 repeats. + EXPECT_EQ( + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s1700m400s2800m400s2800m400s1700m400s1700m400s1700m400s2800m400s2800" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendDish, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDISH(0x0, 8); + EXPECT_EQ( + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100" + "m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800m400s2800" + "m400s6100", irsend.outputStr()); + + irsend.reset(); + irsend.sendDISH(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m400s6100" + "m400s2800m400s2800m400s2800m400s1700m400s2800m400s2800m400s1700m400s2800" + "m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700m400s2800m400s2800" + "m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700m400s2800" + "m400s2800m400s1700m400s1700m400s1700m400s1700m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s2800m400s1700m400s2800m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700" + "m400s1700m400s1700m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700" + "m400s1700m400s1700m400s1700m400s2800m400s1700m400s1700m400s1700m400s1700" + "m400s6100" + "m400s2800m400s2800m400s2800m400s1700m400s2800m400s2800m400s1700m400s2800" + "m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700m400s2800m400s2800" + "m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700m400s2800" + "m400s2800m400s1700m400s1700m400s1700m400s1700m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s2800m400s1700m400s2800m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700" + "m400s1700m400s1700m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700" + "m400s1700m400s1700m400s1700m400s2800m400s1700m400s1700m400s1700m400s1700" + "m400s6100" + "m400s2800m400s2800m400s2800m400s1700m400s2800m400s2800m400s1700m400s2800" + "m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700m400s2800m400s2800" + "m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700m400s2800" + "m400s2800m400s1700m400s1700m400s1700m400s1700m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s2800m400s1700m400s2800m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700" + "m400s1700m400s1700m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700" + "m400s1700m400s1700m400s1700m400s2800m400s1700m400s1700m400s1700m400s1700" + "m400s6100" + "m400s2800m400s2800m400s2800m400s1700m400s2800m400s2800m400s1700m400s2800" + "m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700m400s2800m400s2800" + "m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700m400s2800" + "m400s2800m400s1700m400s1700m400s1700m400s1700m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s2800m400s1700m400s2800m400s2800m400s2800m400s2800" + "m400s1700m400s2800m400s1700m400s2800m400s1700m400s2800m400s1700m400s1700" + "m400s1700m400s1700m400s2800m400s2800m400s1700m400s1700m400s2800m400s1700" + "m400s1700m400s1700m400s1700m400s2800m400s1700m400s1700m400s1700m400s1700" + "m400s6100", irsend.outputStr()); +} + +// Tests for decodeDISH(). + +// Decode normal Dish messages. +TEST(TestDecodeDish, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Dish 16-bit message. + irsend.reset(); + irsend.sendDISH(0x9C00); + 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(0x9C00, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode Dish messages with unsupported size/lengths. +TEST(TestDecodeDish, DecodeWithNonStrictSize) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendDISH(0x12, 8); // Illegal size Dish message. (smaller) + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, 8, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, 8, false)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x12, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + irsend.sendDISH(0x12345678, 32); // Illegal size Dish message. (larger) + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, true)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, 32, false)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeDish, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Dish 64-bit message. + irsend.sendDISH(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, 64, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, 64, false)); + EXPECT_EQ(DISH, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeDish, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + 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(); + + 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)); + 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); +*/ + // 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}; + irsend.reset(); + irsend.sendGC(gc_test_hopper, 73); + 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(0x9C00, 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(0x9C00, 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-Dish example via GlobalCache +TEST(TestDecodeDish, FailToDecodeNonDishExample) { + 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.decodeDISH(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, DISH_BITS, false)); +} 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 new file mode 100644 index 000000000..f1b6c04f6 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Fujitsu_test.cpp @@ -0,0 +1,207 @@ +// 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 new file mode 100644 index 000000000..c2e9762a2 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_GlobalCache_test.cpp @@ -0,0 +1,68 @@ +// 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 new file mode 100644 index 000000000..80a3dec1d --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Gree_test.cpp @@ -0,0 +1,192 @@ +// 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_JVC_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp new file mode 100644 index 000000000..0826b2268 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_JVC_test.cpp @@ -0,0 +1,299 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendJVC(). + +// Test sending typical data only. +TEST(TestSendJVC, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendJVC(0xC2B8); // JVC VCR Power On. + EXPECT_EQ( + "m8400s4200" + "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" + "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" + "m525s60000", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendJVC, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendJVC(0xC2B8, JVC_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m8400s4200" + "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" + "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" + "m525s60000" + "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" + "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" + "m525s60000", irsend.outputStr()); + irsend.sendJVC(0xC2B8, JVC_BITS, 2); // 2 repeats. + EXPECT_EQ( + "m8400s4200" + "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" + "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" + "m525s60000" + "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" + "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" + "m525s60000" + "m525s1725m525s1725m525s525m525s525m525s525m525s525m525s1725m525s525" + "m525s1725m525s525m525s1725m525s1725m525s1725m525s525m525s525m525s525" + "m525s60000", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendJVC, SendUsualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendJVC(0x0, 8); + EXPECT_EQ( + "m8400s4200" + "m525s525m525s525m525s525m525s525m525s525m525s525m525s525m525s525" + "m525s60000", irsend.outputStr()); + + irsend.reset(); + irsend.sendJVC(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m8400s4200" + "m525s525m525s525m525s525m525s1725m525s525m525s525m525s1725m525s525" + "m525s525m525s525m525s1725m525s1725m525s525m525s1725m525s525m525s525" + "m525s525m525s1725m525s525m525s1725m525s525m525s1725m525s1725m525s525" + "m525s525m525s1725m525s1725m525s1725m525s1725m525s525m525s525m525s525" + "m525s1725m525s525m525s525m525s1725m525s525m525s525m525s525m525s525" + "m525s1725m525s525m525s1725m525s525m525s1725m525s525m525s1725m525s1725" + "m525s1725m525s1725m525s525m525s525m525s1725m525s1725m525s525m525s1725" + "m525s1725m525s1725m525s1725m525s525m525s1725m525s1725m525s1725m525s1725" + "m525s60000", irsend.outputStr()); +} + +// Tests for encodeJVC(). + +TEST(TestEncodeJVC, NormalEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x0, irsend.encodeJVC(0, 0)); + EXPECT_EQ(0x8080, irsend.encodeJVC(1, 1)); + EXPECT_EQ(0x8040, irsend.encodeJVC(1, 2)); + EXPECT_EQ(0xC2B8, irsend.encodeJVC(0x43, 0x1D)); + EXPECT_EQ(0x55AA, irsend.encodeJVC(0xAA, 0x55)); + EXPECT_EQ(0xFFFF, irsend.encodeJVC(0xFF, 0xFF)); +} + +// Tests for decodeJVC(). + +// Decode normal JVC messages. +TEST(TestDecodeJVC, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal JVC 16-bit message. + irsend.reset(); + irsend.sendJVC(0xC2B8); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(JVC_BITS, 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); + + // Synthesised Normal JVC 16-bit message. + irsend.reset(); + irsend.sendJVC(irsend.encodeJVC(0x07, 0x99)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(0xE099, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal JVC 16-bit message. + irsend.reset(); + irsend.sendJVC(irsend.encodeJVC(0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(JVC_BITS, irsend.capture.bits); + EXPECT_EQ(0x8080, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated JVC messages. +TEST(TestDecodeJVC, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal JVC 16-bit message with 2 repeats. + irsend.reset(); + irsend.sendJVC(0xC2B8, JVC_BITS, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, true)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(JVC_BITS, 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)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(JVC_BITS, 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)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(JVC_BITS, 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}; + 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(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x43, irsend.capture.address); + EXPECT_EQ(0x1D, irsend.capture.command); + EXPECT_TRUE(irsend.capture.repeat); +} + +// Decode unsupported JVC messages. +TEST(TestDecodeJVC, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + 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)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 8, false)); + EXPECT_EQ(JVC, 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); + + irsend.reset(); + 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)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 32, false)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + EXPECT_EQ(0x12346A, irsend.capture.address); + EXPECT_EQ(0x1E, irsend.capture.command); + + // Illegal over length (36-bit) message. + irsend.reset(); + irsend.sendJVC(irsend.encodeJVC(2, 3), 36); + irsend.makeDecodeResult(); + + // Shouldn't pass if strict off and the wrong expected bits. + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, false)); + + // Re-decode with correct bit size. + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, 36, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 36, false)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(36, irsend.capture.bits); + EXPECT_EQ(0x40C0, irsend.capture.value); + EXPECT_EQ(0x2, irsend.capture.address); + EXPECT_EQ(0x3, irsend.capture.command); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeJVC, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size JVC 64-bit message. + irsend.sendJVC(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 64, false)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0xFFFFFFFF, irsend.capture.address); + EXPECT_EQ(0xFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeJVC, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + 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}; + 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(0xC2B8, irsend.capture.value); + EXPECT_EQ(0x43, irsend.capture.address); + EXPECT_EQ(0x1D, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-JVC example via GlobalCache +TEST(TestDecodeJVC, FailToDecodeNonJVCExample) { + 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.decodeJVC(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, JVC_BITS, false)); +} 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 new file mode 100644 index 000000000..c409c20ba --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Kelvinator_test.cpp @@ -0,0 +1,432 @@ +// 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_LG_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp new file mode 100644 index 000000000..fbdaf7126 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_LG_test.cpp @@ -0,0 +1,358 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "ir_LG.h" +#include "gtest/gtest.h" + +// Tests for calcLGChecksum() +TEST(TestCalcLGChecksum, General) { + EXPECT_EQ(0x0, calcLGChecksum(0x0)); + EXPECT_EQ(0x1, calcLGChecksum(0x1)); + EXPECT_EQ(0xF, calcLGChecksum(0xF)); + EXPECT_EQ(0x4, calcLGChecksum(0x1111)); + EXPECT_EQ(0x8, calcLGChecksum(0x2222)); + EXPECT_EQ(0x0, calcLGChecksum(0x4444)); + EXPECT_EQ(0xA, calcLGChecksum(0x1234)); + EXPECT_EQ(0xA, calcLGChecksum(0x4321)); + EXPECT_EQ(0xE, calcLGChecksum(0xABCD)); + EXPECT_EQ(0x1, calcLGChecksum(0x4AE5)); + EXPECT_EQ(0xC, calcLGChecksum(0xFFFF)); +} + +// Tests for sendLG(). + +// Test sending typical data only. +TEST(TestSendLG, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLG(0x4B4AE51); + EXPECT_EQ( + "m8000s4000" + "m550s550m550s1600m550s550m550s550" + "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" + "m550s1600m550s550m550s1600m550s550m550s1600m550s1600m550s1600m550s550" + "m550s550m550s1600m550s550m550s1600m550s550m550s550m550s550m550s1600" + "m550s108050", irsend.outputStr()); + + irsend.reset(); + irsend.sendLG(0xB4B4AE51, LG32_BITS); + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560m560s1680" + "m560s108080" + "m8950s2250m550s108050", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendLG, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLG(0x4B4AE51, LG_BITS, 1); + EXPECT_EQ( + "m8000s4000" + "m550s550m550s1600m550s550m550s550" + "m550s1600m550s550m550s1600m550s1600m550s550m550s1600m550s550m550s550" + "m550s1600m550s550m550s1600m550s550m550s1600m550s1600m550s1600m550s550" + "m550s550m550s1600m550s550m550s1600m550s550m550s550m550s550m550s1600" + "m550s108050" + "m8000s2250m550s108050", irsend.outputStr()); + + irsend.reset(); + irsend.sendLG(0xB4B4AE51, LG32_BITS, 1); + EXPECT_EQ( + "m4480s4480" + "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s1680m560s1680m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680m560s560" + "m560s560m560s1680m560s560m560s1680m560s560m560s560m560s560m560s1680" + "m560s108080" + "m8950s2250m550s108050" + "m8950s2250m550s108050", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendLG, SendUsualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendLG(0x0, 31); + EXPECT_EQ( + "m8000s4000" + "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" + "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" + "m550s550m550s550m550s550m550s550m550s550m550s550m550s550m550s550" + "m550s550m550s550m550s550m550s550m550s550m550s550m550s550" + "m550s108050", irsend.outputStr()); + + irsend.reset(); + irsend.sendLG(0x0, 64); + EXPECT_EQ( + "m4480s4480" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s108080" + "m8950s2250m550s108050", irsend.outputStr()); +} + +// Tests for encodeLG(). + +TEST(TestEncodeLG, NormalEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x0, irsend.encodeLG(0, 0)); + EXPECT_EQ(0x100011, irsend.encodeLG(1, 1)); + EXPECT_EQ(0x100022, irsend.encodeLG(1, 2)); + EXPECT_EQ(0x43001DE, irsend.encodeLG(0x43, 0x1D)); + EXPECT_EQ(0xB4B4AE51, irsend.encodeLG(0xB4B, 0x4AE5)); + EXPECT_EQ(0xAA0055A, irsend.encodeLG(0xAA, 0x55)); + EXPECT_EQ(0xFFFFFFFC, irsend.encodeLG(0xFFFF, 0xFFFF)); +} + +// Tests for decodeLG(). + +// Decode normal LG messages. +TEST(TestDecodeLG, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal LG 28-bit message. + irsend.reset(); + irsend.sendLG(0x4B4AE51, LG_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(0x4B4AE51, irsend.capture.value); + EXPECT_EQ(0x4B, irsend.capture.address); + EXPECT_EQ(0x4AE5, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal LG 32-bit message. + irsend.reset(); + irsend.sendLG(0xB4B4AE51, LG32_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(0xB4B4AE51, irsend.capture.value); + EXPECT_EQ(0xB4B, irsend.capture.address); + EXPECT_EQ(0x4AE5, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal LG 28-bit message. + irsend.reset(); + irsend.sendLG(irsend.encodeLG(0x07, 0x99)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(0x700992, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal LG 32-bit message. + irsend.reset(); + irsend.sendLG(irsend.encodeLG(0x800, 0x8000), LG32_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(0x80080008, irsend.capture.value); + EXPECT_EQ(0x800, irsend.capture.address); + EXPECT_EQ(0x8000, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated LG messages. +TEST(TestDecodeLG, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal LG 28-bit message with 2 repeats. + irsend.reset(); + irsend.sendLG(irsend.encodeLG(0x07, 0x99), LG_BITS, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG_BITS, irsend.capture.bits); + EXPECT_EQ(0x700992, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal LG 32-bit message with 2 repeats. + irsend.reset(); + irsend.sendLG(irsend.encodeLG(0x07, 0x99), LG32_BITS, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(0x700992, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode unsupported LG message values. +TEST(TestDecodeLG, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Illegal values should be rejected when strict is on. + // Illegal LG 28-bit message value. + 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)); + + // Illegal LG 32-bit message value. + irsend.reset(); + irsend.sendLG(0x1111111, LG32_BITS); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, true)); + + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, false)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG32_BITS, 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.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); +} + +// Decode unsupported LG message sizes. +TEST(TestDecodeLG, DecodeWithNonStrictSizes) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Illegal sizes should be rejected when strict is on. + // Illegal LG 16-bit message size. + irsend.reset(); + 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)); + + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 16, false)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(16, irsend.capture.bits); + EXPECT_EQ(0x992, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + + // Illegal LG 36-bit message size. + irsend.reset(); + 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_TRUE(irrecv.decodeLG(&irsend.capture, 36, false)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(36, irsend.capture.bits); + EXPECT_EQ(0x123456789, irsend.capture.value); + EXPECT_EQ(0x1234, irsend.capture.address); + EXPECT_EQ(0x5678, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeLG, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size LG 64-bit message. + irsend.sendLG(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, 64, true)); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 64, false)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0xFFFFFFFF, irsend.capture.address); + EXPECT_EQ(0xFFFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeLG, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + +// 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}; + irsend.sendGC(gc_test, 75); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, LG32_BITS, true)); + EXPECT_EQ(LG, irsend.capture.decode_type); + EXPECT_EQ(LG32_BITS, irsend.capture.bits); + EXPECT_EQ(0xB4B4AE51, irsend.capture.value); + EXPECT_EQ(0xB4B, irsend.capture.address); + EXPECT_EQ(0x4AE5, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-LG example via GlobalCache +TEST(TestDecodeLG, FailToDecodeNonLGExample) { + 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.decodeLG(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, LG_BITS, false)); +} 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 new file mode 100644 index 000000000..2f28657fb --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Mitsubishi_test.cpp @@ -0,0 +1,694 @@ +// 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_NEC_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp new file mode 100644 index 000000000..781aa38d7 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_NEC_test.cpp @@ -0,0 +1,320 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendNEC(). + +// Test sending typical data only. +TEST(TestSendNEC, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendNEC(0); + EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s108080", irsend.outputStr()); + irsend.sendNEC(0xAA00FF55); + EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s560m560s1680m560s108080", + irsend.outputStr()); +} + +// Test sending different bit lengths. +TEST(TestSendNEC, SendSmallData) { + IRsendTest irsend(4); + irsend.begin(); + irsend.sendNEC(0xA, 4); // Send only 4 data bits. + EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s108080", + irsend.outputStr()); + irsend.sendNEC(0, 8); // Send only 8 data bits. + EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s108080", irsend.outputStr()); + irsend.sendNEC(0x1234567890ABCDEF, 64); // Send 64 data bits. + EXPECT_EQ("m8960s4480m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s1680m560s560m560s560m560s560m560s1680m560s1680m560s560" + "m560s1680m560s560m560s560m560s560m560s1680m560s560m560s1680" + "m560s560m560s1680m560s1680m560s560m560s560m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s1680m560s560" + "m560s560m560s1680m560s560m560s560m560s560m560s560m560s1680m560s560" + "m560s1680m560s560m560s1680m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s560m560s560m560s1680m560s1680m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s1680" + "m560s1680m560s108080", irsend.outputStr()); +} + +// Test sending with repeats. +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()); + irsend.sendNEC(0xAA, 8, 1); // Send a command with 1 repeat. + EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s108080" + "m8960s2240m560s108080", + irsend.outputStr()); + irsend.sendNEC(0xAA, 8, 3); // Send a command with 3 repeats. + EXPECT_EQ("m8960s4480m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s1680m560s560m560s108080" + "m8960s2240m560s108080" + "m8960s2240m560s108080" + "m8960s2240m560s108080", + irsend.outputStr()); +} + +// Tests for encodeNEC(). + +TEST(TestEncodeNEC, NormalNECEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x807F40BF, irsend.encodeNEC(1, 2)); + EXPECT_EQ(0x9A656897, irsend.encodeNEC(0x59, 0x16)); +} + +TEST(TestEncodeNEC, ExtendedNECEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x9A806897, irsend.encodeNEC(0x159, 0x16)); +} + +TEST(TestEncodeNEC, CommandTrimmedTo8Bits) { + IRsendTest irsend(4); + EXPECT_EQ(irsend.encodeNEC(0x1, 0x2), irsend.encodeNEC(0x1, 0xF02)); + EXPECT_EQ(irsend.encodeNEC(0xFFF0, 0x2), irsend.encodeNEC(0xFFF0, 0xF02)); +} + +// Tests for decodeNEC(). +// Decode normal NEC messages. +TEST(TestDecodeNEC, NormalNECDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Synthesised Normal NEC message. + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x1, 0x2)); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(0x807F40BF, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x2, irsend.capture.command); + + // Real-life Extended NEC code from an actual capture/decode. + irsend.reset(); + irsend.sendNEC(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); + + // Test strict decoding rejects a NEC-like message. + irsend.reset(); + irsend.sendNEC(0x0); + irsend.makeDecodeResult(); + EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture)); + + // Synthesised Normal NEC message with a repeat. + irsend.reset(); + irsend.sendNEC(irsend.encodeNEC(0x1, 0x2), 32, 1); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(0x807F40BF, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x2, irsend.capture.command); +} + +// NEC-like messages without strict mode. +TEST(TestDecodeNEC, NormalNECDecodeWithoutStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendNEC(0x0); + 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(0, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + irsend.reset(); + irsend.sendNEC(0x12345678); + 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(0x12345678, irsend.capture.value); + EXPECT_EQ(0x2C48, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); +} + +// Short NEC-like messages (without strict naturally) +TEST(TestDecodeNEC, ShortNECDecodeWithoutStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendNEC(0x0, 16); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 16, false)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(16, irsend.capture.bits); + EXPECT_EQ(0, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + // Expecting less than what was sent is not valid. + irsend.reset(); + irsend.sendNEC(0x0, 32); + irsend.makeDecodeResult(); + EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, 16, false)); + + // Send 16 bits of data, but fail because we are expecting 17. + irsend.reset(); + irsend.sendNEC(0x0, 16); + irsend.makeDecodeResult(); + EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, 17, false)); +} + +// Longer NEC-like messages (without strict naturally) +TEST(TestDecodeNEC, LongerNECDecodeWithoutStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + irsend.sendNEC(0x1234567890ABCDEF, 64); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 64, false)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0x1234567890ABCDEF, irsend.capture.value); + EXPECT_EQ(0xD509, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); + + // Send 63 bits of data, but fail because we are expecting 64. + irsend.reset(); + irsend.sendNEC(0x0, 63); + irsend.makeDecodeResult(); + EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, 64, false)); +} + +// Incorrect decoding reported in Issue #243 +// Incorrect handling of decodes when 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(TestDecodeNEC, NoTrailingGap_Issue243) { + 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); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(0x6DD2, irsend.capture.address); + EXPECT_EQ(0x2, irsend.capture.command); + + irsend.reset(); + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(NEC_BITS, 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. + 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(0x4BB640BF, irsend.capture.value); +} + +// Inconsistent decoding for unknown in Issue #264 +// Reported issues decoding an Apple Remote. Apple doesn't appear to respect +// or use the command structure/checks in the NEC protocol. +TEST(TestDecodeNEC, NonStrictNECDecode_Issue264) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + 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}; + + 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_EQ(0x77E1A040, irsend.capture.value); + + // Do it all again, but with a normal decode. + irsend.reset(); + irsend.sendRaw(rawData, 67, 38); + 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(0x77E1A040, irsend.capture.value); +} + +TEST(TestDecodeNEC, AutoReceiveCalibration) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // 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}; + + irsend.sendRaw(rawData, 67, 38); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, NEC_BITS, false)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(NEC_BITS, irsend.capture.bits); + EXPECT_EQ(0x77E1A040, irsend.capture.value); +} 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 new file mode 100644 index 000000000..0eea2bc40 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Nikai_test.cpp @@ -0,0 +1,210 @@ +// 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 new file mode 100644 index 000000000..3f27b90bf --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Panasonic_test.cpp @@ -0,0 +1,457 @@ +// 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_Pronto_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp new file mode 100644 index 000000000..7fbe39554 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Pronto_test.cpp @@ -0,0 +1,358 @@ +// Copyright 2017 David Conran +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendPronto(). + +TEST(TestSendPronto, CodeTooShort) { + IRsendTest irsend(4); + irsend.begin(); + irsend.reset(); + + // Less entries than the smallest possible (practical) Pronto code. + uint16_t pronto_test[5] = {0x0000, 0x0067, 0x0034, 0x0000, 0x0000}; + irsend.sendPronto(pronto_test, 5); + EXPECT_EQ("", irsend.outputStr()); // Should do nothing. +} + +TEST(TestSendPronto, NormalSequenceTooLong) { + IRsendTest irsend(4); + irsend.begin(); + irsend.reset(); + + // The First 'Normal' sequence is declared to be longer than the data we have. + uint16_t pronto_test[6] = {0x0000, 0x0067, 0x0010, 0x0000, 0x0000, 0x0000}; + irsend.sendPronto(pronto_test, 6); + EXPECT_EQ("", irsend.outputStr()); // Should do nothing. +} + +TEST(TestSendPronto, RepeatSequenceTooLong) { + IRsendTest irsend(4); + irsend.begin(); + irsend.reset(); + + // The 2nd 'Repeat' sequence is declared to be longer than the data we have. + uint16_t pronto_test[6] = {0x0000, 0x0067, 0x0000, 0x0010, 0x0000, 0x0000}; + irsend.sendPronto(pronto_test, 6); + EXPECT_EQ("", irsend.outputStr()); // Should do nothing. +} + +TEST(TestSendPronto, BothSequencesTooLong) { + IRsendTest irsend(4); + irsend.begin(); + irsend.reset(); + + // All sequences are declared to be longer than the data we have. + uint16_t pronto_test[6] = {0x0000, 0x0067, 0x0010, 0x0010, 0x0000, 0x0000}; + irsend.sendPronto(pronto_test, 6); + EXPECT_EQ("", irsend.outputStr()); // Should do nothing. +} + +TEST(TestSendPronto, MoreDataThanNeededInNormal) { + IRsendTest irsend(4); + irsend.begin(); + irsend.reset(); + + // We should handle when we are given more data than needed. (normal seq.) + uint16_t pronto_test[8] = {0x0000, 0x0067, 0x0001, 0x0000, + 0x0001, 0x0002, 0x0003, 0x0004}; + irsend.sendPronto(pronto_test, 8); + EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. +} + +TEST(TestSendPronto, MoreDataThanNeededInRepeat) { + IRsendTest irsend(4); + irsend.begin(); + irsend.reset(); + + // We should handle when we are given more data than needed. (repeat seq.) + uint16_t pronto_test[8] = {0x0000, 0x0067, 0x0000, 0x0001, + 0x0001, 0x0002, 0x0003, 0x0004}; + irsend.sendPronto(pronto_test, 8); + EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. +} + +TEST(TestSendPronto, MoreDataThanNeededInBoth) { + IRsendTest irsend(4); + irsend.begin(); + 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}; + irsend.sendPronto(pronto_test, 10); + EXPECT_EQ("m25s50", irsend.outputStr()); // Only send the data required. + irsend.sendPronto(pronto_test, 10, 1); + EXPECT_EQ("m25s50m75s100", irsend.outputStr()); // Only the data required. +} + +TEST(TestSendPronto, ShortestValidCodeThatSendsNothing) { + IRsendTest irsend(4); + irsend.begin(); + irsend.reset(); + + uint16_t pronto_test[6] = {0x0000, 0x0067, 0x0000, 0x0000, 0x0001, 0x0002}; + irsend.sendPronto(pronto_test, 6); + EXPECT_EQ("", irsend.outputStr()); // Nothing Happens. + irsend.sendPronto(pronto_test, 6, 1); + EXPECT_EQ("", irsend.outputStr()); // Twice as much Nothing Happens. ;-) +} + +// Test sending a Pronto code that only has a normal (first) sequence. +// i.e. No Pronto repeat sequence. +TEST(TestSendPronto, NonRepeatingCode) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // A random Pronto code I found on the Internet that has no repeat sequence. + // 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}; + + // Send the Pronto code without any repeats set. + irsend.reset(); + irsend.sendPronto(pronto_test, 108); + irsend.makeDecodeResult(); + EXPECT_EQ( + "m2400s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m600s600m600s27650" + "m2400s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m600s600m600s27650" + "m2400s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "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); + + // 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_EQ( + "m2400s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m600s600m600s27650" + "m2400s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "m600s600m600s600m600s600m600s27650" + "m2400s600" + "m600s600m600s600m600s600m600s600m600s600m600s600m600s600m1200s600" + "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); +} + +// Test sending a Pronto code that only has a repeat sequence (Sony). +TEST(TestSendPronto, RepeatSequenceOnlyForSony) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // 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, + 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_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); + + // Send the Pronto code with 2 repeats. + irsend.reset(); + irsend.sendPronto(pronto_test, 46, SONY_MIN_REPEAT); + irsend.makeDecodeResult(); + EXPECT_EQ( + "m2400s600" + "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" + "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s25350" + "m2400s600" + "m600s600m1200s600m1200s600m1200s600m600s600m1200s600m600s600m600s600" + "m1200s600m600s600m1200s600m1200s600m1200s600m600s600m600s600m1200s600" + "m600s600m600s600m1200s600m600s25350" + "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); +} + +// Test sending a Pronto code that only has a repeat sequence (Panasonic). +TEST(TestSendPronto, RepeatSequenceOnlyForPanasonic) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // 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}; + + // Send the Pronto code without any repeats set. + irsend.reset(); + irsend.sendPronto(pronto_test, 104); + irsend.makeDecodeResult(); + EXPECT_EQ( + "m3456s1701" + "m432s432m432s1296m432s432m432s432m432s432m432s432m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s1296m432s432m432s432" + "m432s432m432s432m432s432m432s432m432s432m432s432m432s432m432s1296" + "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); +} + + +// Test sending a Pronto code that has a normal & arepeat sequence (NEC). +TEST(TestSendPronto, NormalPlusRepeatSequence) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // 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, + 0x0156, 0x0055, 0x0015, 0x0E4E}; + + // Send the Pronto code without any repeats set. + irsend.reset(); + irsend.sendPronto(pronto_test, 76); + irsend.makeDecodeResult(); + 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); + + // Send it again with a single repeat. + irsend.reset(); + irsend.sendPronto(pronto_test, 76, 1); + irsend.makeDecodeResult(); + EXPECT_EQ( + "m8892s4446" + "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" + "m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664" + "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); + + // Send it again with a two repeats. + irsend.reset(); + irsend.sendPronto(pronto_test, 76, 2); + irsend.makeDecodeResult(); + EXPECT_EQ( + "m8892s4446" + "m546s546m546s546m546s546m546s1664m546s1664m546s546m546s546m546s546" + "m546s1664m546s1664m546s1664m546s546m546s546m546s1664m546s1664m546s1664" + "m546s546m546s546m546s546m546s1664m546s546m546s546m546s546m546s546" + "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); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp new file mode 100644 index 000000000..ef508e40e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_RC5_RC6_test.cpp @@ -0,0 +1,873 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// RRRRRR CCCCC 555555 RRRRRR CCCCC 555555 XX XX +// RR RR CC C 55 RR RR CC C 55 XX XX +// RRRRRR CC _____ 555555 RRRRRR CC _____ 555555 XXXX +// RR RR CC C 5555 RR RR CC C 5555 XX XX +// RR RR CCCCC 555555 RR RR CCCCC 555555 XX XX + +// Tests for encodeRC5(). +TEST(TestEncodeRC5, NormalEncoding) { + IRsendTest irsend(4); + + EXPECT_EQ(0x0, irsend.encodeRC5(0, 0)); + EXPECT_EQ(0x800, irsend.encodeRC5(0, 0, true)); + EXPECT_EQ(0x41, irsend.encodeRC5(1, 1)); + EXPECT_EQ(0x42, irsend.encodeRC5(1, 2)); + EXPECT_EQ(0x7FF, irsend.encodeRC5(0x1F, 0x3F)); + EXPECT_EQ(0xFFF, irsend.encodeRC5(0x1F, 0x3F, true)); + EXPECT_EQ(0x7FF, irsend.encodeRC5(0xFF, 0xFF)); + EXPECT_EQ(0xFFF, irsend.encodeRC5(0xFF, 0xFF, true)); + + EXPECT_EQ(0x175, irsend.encodeRC5(0x05, 0x35)); +} + +// Tests for encodeRC5X(). +TEST(TestEncodeRC5X, NormalEncoding) { + IRsendTest irsend(4); + + EXPECT_EQ(0x0, irsend.encodeRC5X(0, 0)); + EXPECT_EQ(0x800, irsend.encodeRC5X(0, 0, true)); + EXPECT_EQ(0x41, irsend.encodeRC5X(1, 1)); + EXPECT_EQ(0x42, irsend.encodeRC5X(1, 2)); + EXPECT_EQ(0x3FF, irsend.encodeRC5X(0x0F, 0x3F)); + EXPECT_EQ(0x3FF, irsend.encodeRC5X(0x0F, 0x3F, false)); + EXPECT_EQ(0xBFF, irsend.encodeRC5X(0x0F, 0x3F, true)); + EXPECT_EQ(0x17FF, irsend.encodeRC5X(0x1F, 0x7F)); + EXPECT_EQ(0x1FFF, irsend.encodeRC5X(0x1F, 0x7F, true)); + EXPECT_EQ(0x17FF, irsend.encodeRC5X(0xFF, 0xFF)); + EXPECT_EQ(0x1FFF, irsend.encodeRC5X(0xFF, 0xFF, true)); + + EXPECT_EQ(0x175, irsend.encodeRC5X(0x05, 0x35)); + + // Values of command <= 6-bits. i.e (<= 63 (0x3F)) should be the same + // as encodeRC5. + EXPECT_EQ(irsend.encodeRC5X(0, 0), irsend.encodeRC5(0, 0)); + EXPECT_EQ(irsend.encodeRC5X(0, 0, true), irsend.encodeRC5(0, 0, true)); + EXPECT_EQ(irsend.encodeRC5X(0x5, 0x35, false), + irsend.encodeRC5(0x5, 0x35, false)); + EXPECT_EQ(irsend.encodeRC5X(0x5, 0x35, true), + irsend.encodeRC5(0x5, 0x35, true)); + EXPECT_EQ(irsend.encodeRC5X(0x1F, 0x3F, true), + irsend.encodeRC5(0x1F, 0x3F, true)); + EXPECT_NE(irsend.encodeRC5X(0x1F, 0x7F, true), + irsend.encodeRC5(0x1F, 0x7F, true)); +} + +// Tests for toggleRC5(). +TEST(TestToggleRC5, GeneralUse) { + IRsendTest irsend(4); + + EXPECT_EQ(0x800, irsend.toggleRC5(0x0)); + EXPECT_EQ(0x0, irsend.toggleRC5(0x800)); + EXPECT_EQ(0x0, irsend.toggleRC5(irsend.toggleRC5(0x0))); + EXPECT_EQ(irsend.encodeRC5(0x5, 0x35, false), + irsend.toggleRC5(irsend.encodeRC5(0x5, 0x35, true))); +} + +// Tests for sendRC5(). + +// Test sending typical RC-5 & RC-5X data only. +TEST(TestSendRC5, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRC5(0x0, RC5_BITS); + EXPECT_EQ( + "m889s889m1778s889m889s889m889s889m889s889m889s889m889" + "s889m889s889m889s889m889s889m889s889m889s889m889s114667", + irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x1AAA, RC5_BITS); + EXPECT_EQ( + "m889s889m889s889m1778s1778m1778s1778m1778s1778" + "m1778s1778m1778s1778m1778s114667", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x175, RC5_BITS); + EXPECT_EQ( + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x3FFF, RC5_BITS); + EXPECT_EQ( + "m889s889m889s889m889s889m889s889m889s889m889s889m889s889" + "m889s889m889s889m889s889m889s889m889s889m889s889m889s113778", + irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x0, RC5X_BITS); + EXPECT_EQ( + "m889s889m1778s889m889s889m889s889m889s889m889s889m889" + "s889m889s889m889s889m889s889m889s889m889s889m889s114667", + irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x1AAA, RC5X_BITS); + EXPECT_EQ( + "m1778s1778m1778s1778m1778s1778m1778" + "s1778m1778s1778m1778s1778m1778s114667", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x175, RC5X_BITS); + EXPECT_EQ( + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x3FFF, RC5X_BITS); + EXPECT_EQ( + "m1778s1778m889s889m889s889m889s889m889s889m889s889m889" + "s889m889s889m889s889m889s889m889s889m889s889m889s113778", + irsend.outputStr()); +} + +// Test sending RC-5 & RC-5X with different repeats. +TEST(TestSendRC5, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRC5(0x175, RC5_BITS, 1); + EXPECT_EQ( + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x175, RC5_BITS, 2); + EXPECT_EQ( + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x175, RC5X_BITS, 1); + EXPECT_EQ( + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m889s889m1778s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC5(0x1175, RC5X_BITS, 2); + EXPECT_EQ( + "m1778s889m889s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m1778s889m889s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s114667" + "m1778s889m889s889m889s889m889s1778m1778s1778" + "m889s889m889s889m1778s1778m1778s1778m889s113778", irsend.outputStr()); +} +// Tests for decodeRC5(). + +// Decode normal RC-5/RC5X messages. +TEST(TestDecodeRC5, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RC-5 12-bit message. + irsend.reset(); + irsend.sendRC5(0x175); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + EXPECT_EQ(0x05, irsend.capture.address); + EXPECT_EQ(0x35, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal RC-5 12-bit message decoded as RC5-X. + irsend.reset(); + irsend.sendRC5(0x175); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + EXPECT_EQ(0x05, irsend.capture.address); + EXPECT_EQ(0x35, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // 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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + EXPECT_EQ(0x05, irsend.capture.address); + EXPECT_EQ(0x35, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal RC-5 12-bit message. + irsend.reset(); + irsend.sendRC5(irsend.encodeRC5(0x00, 0x0B, true)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(RC5_BITS, irsend.capture.bits); + EXPECT_EQ(0x80B, irsend.capture.value); + EXPECT_EQ(0x00, irsend.capture.address); + EXPECT_EQ(0x0B, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal RC-5X 13-bit message. + irsend.reset(); + irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), RC5X_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + EXPECT_EQ(RC5X, irsend.capture.decode_type); + EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(0x1881, irsend.capture.value); + EXPECT_EQ(0x02, irsend.capture.address); + EXPECT_EQ(0x41, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // 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.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); +} + +// Decode normal repeated RC5 messages. +TEST(TestDecodeRC5, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RC-5 12-bit (even) message with one repeat. + irsend.reset(); + irsend.sendRC5(0x174, RC5_BITS, 1); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(RC5_BITS, 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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, true)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(RC5_BITS, 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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, RC5X_BITS, true)); + EXPECT_EQ(RC5X, irsend.capture.decode_type); + EXPECT_EQ(RC5X_BITS, irsend.capture.bits); + EXPECT_EQ(0x1881, irsend.capture.value); + EXPECT_EQ(0x02, irsend.capture.address); + EXPECT_EQ(0x41, irsend.capture.command); +} + +// Decode unsupported RC5 messages. +TEST(TestDecodeRC5, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + 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)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 8, false)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0xFA, irsend.capture.value); + EXPECT_EQ(0x3, irsend.capture.address); + EXPECT_EQ(0x3A, irsend.capture.command); + + irsend.reset(); + 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)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 32, false)); + EXPECT_EQ(RC5, irsend.capture.decode_type); + EXPECT_EQ(31, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + + irsend.reset(); + 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)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 32, false)); + EXPECT_EQ(RC5X, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x87654321, irsend.capture.value); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeRC5, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal size RC-5 64-bit message. + irsend.sendRC5(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 64, false)); + EXPECT_EQ(RC5X, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); +} + +// Fail to decode a non-RC-5 example via GlobalCache +TEST(TestDecodeRC5, FailToDecodeNonRC5Example) { + IRsendTest irsend(4); + IRrecv irrecv(4); + 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}; + irsend.sendGC(gc_test, 39); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, RC5_BITS, false)); +} + +// RRRRRR CCCCC 666 +// RR RR CC C 66 +// RRRRRR CC _____ 666666 +// RR RR CC C 66 66 +// RR RR CCCCC 66666 + +// 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)); +} + +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)); +} + +// Tests for toggleRC6(). + +// Normal use (RC-6 Mode 0) +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(0x0, irsend.toggleRC6(0x10000)); + EXPECT_EQ(0x0, irsend.toggleRC6(irsend.toggleRC6(0x0))); +} + +// RC-6 36-bit use (Xbox 360) +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)); +} + +// Tests for sendRC6(). + +// Test sending typical RC-6 Mode-0 data only. +TEST(TestSendRC6, SendMode0DataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRC6(0x0); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444s888m888s444m444s444m444s444" + "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" + "m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s83028", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0x1FFFF); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m1332s888m444s444m444s444m444s444" + "m444s444m444s444m444s444m444s444m444s444m444s444m444s444" + "m444s444m444s444m444s444m444s444m444s444m444" + "s83472", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0x15555); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m1332s1332m888s888m888s888" + "m888s888m888s888m888s888m888s888m888s888m888" + "s83472", irsend.outputStr()); +} + +// Test sending typical RC-6 36-bit data only. +TEST(TestSendRC6, Send36BitDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRC6(0x0, RC6_36_BITS); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s83028", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0xFFFFFFFFF, RC6_36_BITS); + EXPECT_EQ( + "m2664s888" + "m444s444m444s444m444s444m444s444" + "m888s888" + "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444" + "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444" + "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444" + "m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s83472", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0xAAAAAAAAAA, RC6_36_BITS); + EXPECT_EQ( + "m2664s888m444s444m444s888m888" + "s1332m1332" + "s888m888s888m888s888m888s888m888s888m888s888m888s888m888s888m888s888m888" + "s888m888s888m888s888m888s888m888s888m888s888m888s888m444s83028", + irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0xC800F740C, RC6_36_BITS); // Xbox 360 OnOff code + EXPECT_EQ( + "m2664s888" + "m444s444m444s444m444s888m444" + "s888m1332" + "s888m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m888s444m444s444m444s444m444s888m888s444m444" + "s444m444s888m888s888m444s444m444s444m444s444m444s444m444s444m888" + "s444m444s888m444s444m444s83028", irsend.outputStr()); + irsend.reset(); + irsend.sendRC6(irsend.toggleRC6(0xC800F740C, RC6_36_BITS), + RC6_36_BITS); // Xbox 360 OnOff code (toggled) + EXPECT_EQ( + "m2664s888" + "m444s444m444s444m444s888m444" + "s888m1332" + "s888m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m888s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s888m888s888m444s444m444s444m444s444m444s444m444" + "s444m888s444m444s888m444s444m444s83028", irsend.outputStr()); +} + +// Test sending RC-6 Mode 0 with different repeats. +TEST(TestSendRC6, SendMode0WithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRC6(0x175, RC6_MODE0_BITS, 0); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0x175, RC6_MODE0_BITS, 1); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472" + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0x175, RC6_MODE0_BITS, 2); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472" + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472" + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); +} + +// Test sending RC-6 36-bit with different repeats. +TEST(TestSendRC6, Send36BitWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRC6(0x175, RC6_36_BITS, 0); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0x175, RC6_36_BITS, 1); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472" + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); + + irsend.reset(); + irsend.sendRC6(0x175, RC6_36_BITS, 2); + EXPECT_EQ( + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472" + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472" + "m2664s888" + "m444s888m444s444m444s444m444" + "s888m888" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m444s444m444" + "s444m444s444m444s444m444s444m444s444m444s444m444s444m888s888m888" + "s444m444s444m444s888m888s888m888s83472", irsend.outputStr()); +} + +// Tests for decodeRC6(). + +// Decode normal RC-6 Mode 0 messages. +TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RC-6 Mode 0 (20-bit) message. + irsend.reset(); + irsend.sendRC6(0x175); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + EXPECT_EQ(0x01, irsend.capture.address); + EXPECT_EQ(0x75, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Synthesised RC-6 Mode 0 (20-bit) message. + irsend.reset(); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_MODE0_BITS)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(0x56789, irsend.capture.value); + EXPECT_EQ(0x567, irsend.capture.address); + EXPECT_EQ(0x89, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Same again, but encoded manually. + irsend.reset(); + irsend.sendRC6(0x123456789, RC6_MODE0_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(0x56789, irsend.capture.value); + EXPECT_EQ(0x567, irsend.capture.address); + EXPECT_EQ(0x89, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal RC-6 36-bit messages. +TEST(TestDecodeRC6, Normal36BitDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RC-6 36-bit message. + irsend.reset(); + irsend.sendRC6(0x175, RC6_36_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + EXPECT_EQ(0x01, irsend.capture.address); + EXPECT_EQ(0x75, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Synthesised RC-6 36-bit message. + irsend.reset(); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS), RC6_36_BITS); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(0x123456789, irsend.capture.value); + EXPECT_EQ(0x1234567, irsend.capture.address); + EXPECT_EQ(0x89, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated RC6 Mode 0 messages. +TEST(TestDecodeRC6, NormalMode0DecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RC-6 Mode 0 (20-bit) even message with one repeat. + irsend.reset(); + irsend.sendRC6(0x174, RC6_MODE0_BITS, 1); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_MODE0_BITS, 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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_MODE0_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_MODE0_BITS, irsend.capture.bits); + EXPECT_EQ(0x175, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x75, irsend.capture.command); +} + +// Decode normal repeated RC6 36-bit messages. +TEST(TestDecodeRC6, Normal36BitDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RC-6 36-bit odd message with one repeat. + irsend.reset(); + irsend.sendRC6(0x175, RC6_36_BITS, 1); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_36_BITS, 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.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS, true)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(0x174, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x74, irsend.capture.command); +} + +// Decode RC-6 messages without strict. +TEST(TestDecodeRC6, NormalDecodeWithoutStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RC-6 Mode 0 (20-bit) message. + irsend.reset(); + irsend.sendRC6(0x175, RC6_MODE0_BITS); + 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(0x175, irsend.capture.value); + EXPECT_EQ(0x01, irsend.capture.address); + EXPECT_EQ(0x75, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal RC-6 Mode 0 (20-bit) message. + irsend.reset(); + irsend.sendRC6(0x174, RC6_MODE0_BITS); + 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(0x174, irsend.capture.value); + EXPECT_EQ(0x01, irsend.capture.address); + EXPECT_EQ(0x74, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal RC-6 36-bit message. + irsend.reset(); + irsend.sendRC6(0x174, RC6_36_BITS); + 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(0x174, irsend.capture.value); + EXPECT_EQ(0x01, irsend.capture.address); + EXPECT_EQ(0x74, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal Synthesised RC-6 36-bit message. + irsend.reset(); + irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, RC6_36_BITS), RC6_36_BITS); + 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(0x123456789, irsend.capture.value); + EXPECT_EQ(0x1234567, irsend.capture.address); + EXPECT_EQ(0x89, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeRC6, Decode36BitGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + 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}; + irsend.sendGC(gc_test, 65); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, RC6_36_BITS)); + EXPECT_EQ(RC6, irsend.capture.decode_type); + EXPECT_EQ(RC6_36_BITS, irsend.capture.bits); + EXPECT_EQ(0xC800F742A, irsend.capture.value); + EXPECT_EQ(0xC800F74, irsend.capture.address); + EXPECT_EQ(0x2A, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-RC-6 example via GlobalCache +TEST(TestDecodeRC5, FailToDecodeNonRC6Example) { + IRsendTest irsend(4); + IRrecv irrecv(4); + 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}; + 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)); + + 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)); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp new file mode 100644 index 000000000..2115dcb2e --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_RCMM_test.cpp @@ -0,0 +1,239 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendRCMM(). + +// Test sending typical data only. +TEST(TestSendRCMM, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRCMM(0xe0a600); + EXPECT_EQ("m416s277" + "m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s27778", irsend.outputStr()); + irsend.reset(); + irsend.sendRCMM(0x28e0a600UL, 32); + EXPECT_EQ("m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s27778", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendRCMM, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + 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()); +} + +// Test sending an atypical data size. +TEST(TestSendRCMM, SendUsualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendRCMM(0xE0, 8); + EXPECT_EQ("m416s277" + "m166s777m166s611m166s277m166s277" + "m166s27778", irsend.outputStr()); + irsend.reset(); + irsend.sendRCMM(0x28e0a60000UL, 40); + EXPECT_EQ("m416s277" + "m166s277m166s611m166s611m166s277m166s777m166s611m166s277m166s277" + "m166s611m166s611m166s444m166s611m166s277m166s277m166s277m166s277" + "m166s277m166s277m166s277m166s277m166s27778", irsend.outputStr()); +} + +// Tests for decodeRCMM(). + +// Decode normal RCMM messages. +TEST(TestDecodeRCMM, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal RCMM 24-bit message. + irsend.reset(); + irsend.sendRCMM(0xe0a600); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, RCMM_BITS, true)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(RCMM_BITS, irsend.capture.bits); + EXPECT_EQ(0xe0a600, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal RCMM 12-bit message. + irsend.reset(); + irsend.sendRCMM(0x600, 12); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 12, true)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(12, irsend.capture.bits); + EXPECT_EQ(0x600, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Normal RCMM 32-bit message. + irsend.reset(); + irsend.sendRCMM(0x28e0a600, 32); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 32, true)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x28e0a600, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decodes should fail for illegal bit sizes when in strict mode. +TEST(TestDecodeRCMM, IllegalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Illegal RCMM 8-bit message. + irsend.reset(); + irsend.sendRCMM(0x0, 8); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 8, true)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 12, true)); + + // Illegal RCMM 36-bit message. + irsend.reset(); + irsend.sendRCMM(0x0, 36); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 12, true)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 36, true)); +} + +// Decodes without strict mode. +TEST(TestDecodeRCMM, DecodeWithoutStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Illegal RCMM 8-bit message. + irsend.reset(); + irsend.sendRCMM(0x55, 8); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 8, false)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x55, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 12, false)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x55, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + // Illegal RCMM 36-bit message. + irsend.reset(); + irsend.sendRCMM(0x123456789, 36); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 12, false)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(36, irsend.capture.bits); + EXPECT_EQ(0x123456789, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 24, false)); + EXPECT_EQ(36, irsend.capture.bits); + EXPECT_EQ(0x123456789, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 36, false)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(36, irsend.capture.bits); + EXPECT_EQ(0x123456789, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeRCMM, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size RCMM 64-bit message. + irsend.sendRCMM(0xFEDCBA9876543210, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 64, false)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFEDCBA9876543210, irsend.capture.value); + EXPECT_EQ(0, irsend.capture.address); + EXPECT_EQ(0, irsend.capture.command); +} + +// Fail to decode a non-RCMM example via GlobalCache +TEST(TestDecodeRCMM, FailToDecodeNonRCMMExample) { + 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.decodeRCMM(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, RCMM_BITS, false)); +} + +// Issue 281 Debugging +TEST(TestDecodeRCMM, DebugIssue281) { + IRsendTest irsend(4); + IRrecv irrecv(4); + 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 + + irsend.reset(); + irsend.sendRaw(rawData, 36, 36); + irsend.makeDecodeResult(); + + ASSERT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(RCMM, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x26702610, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} 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 new file mode 100644 index 000000000..8c35ebebf --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Samsung_test.cpp @@ -0,0 +1,276 @@ +// 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_Sanyo_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp new file mode 100644 index 000000000..9442f3db5 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sanyo_test.cpp @@ -0,0 +1,242 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + + +// Tests for encodeSanyoLC7461(). + +TEST(TestEncodeSanyoLC7461, NormalEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x1FFF00FF, irsend.encodeSanyoLC7461(0, 0)); + EXPECT_EQ(0x3FFE01FE, irsend.encodeSanyoLC7461(1, 1)); + EXPECT_EQ(0x3FFE02FD, irsend.encodeSanyoLC7461(1, 2)); + EXPECT_EQ(0x3FFE000FF00, irsend.encodeSanyoLC7461(0x1FFF, 0xFF)); + EXPECT_EQ(0x2AAAAAA55AA, irsend.encodeSanyoLC7461(0x1555, 0x55)); + EXPECT_EQ(0x3FFE000FF00, irsend.encodeSanyoLC7461(0xFFFF, 0xFF)); + EXPECT_EQ(0x1D8113F00FF, irsend.encodeSanyoLC7461(0xEC0, 0x0)); +} + +// Tests for sendSanyoLC7461(). + +// Test sending typical data only. +TEST(TestEncodeSanyoLC7461, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSanyoLC7461(0x1D8113F00FF); + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s108080", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestEncodeSanyoLC7461, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSanyoLC7461(0x1D8113F00FF, SANYO_LC7461_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m8960s4480" + "m560s560m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s560m560s1680m560s560m560s560" + "m560s560m560s1680m560s560m560s560m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s560" + "m560s560m560s560m560s1680m560s1680m560s1680m560s1680m560s1680m560s1680" + "m560s1680m560s1680m560s108080" + "m8960s2240m560s108080", irsend.outputStr()); +} + +// Tests for decodeSanyoLC7461(). + +// Decode normal Sanyo LC7461 messages. +TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Sanyo LC7461 42-bit message. + irsend.reset(); + irsend.sendSanyoLC7461(0x1D8113F00FF); + 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); + + // Synthesised Normal Sanyo LC7461 42-bit message. + irsend.reset(); + irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1234, 0x56)); + 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(0x2468DCB56A9, irsend.capture.value); + EXPECT_EQ(0x1234, irsend.capture.address); + EXPECT_EQ(0x56, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal Sanyo LC7461 42-bit message. + irsend.reset(); + irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1, 0x1)); + 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(0x3FFE01FE, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Sanyo LC7461 messages. +TEST(TestDecodeSanyoLC7461, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Sanyo LC7461 16-bit message with 1 repeat. + irsend.reset(); + irsend.sendSanyoLC7461(0x3FFE01FE, SANYO_LC7461_BITS, 1); + 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(0x3FFE01FE, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode unsupported Sanyo LC7461 messages. +TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + 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)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, + false)); + EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); + EXPECT_EQ(SANYO_LC7461_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 value Sanyo LC7461 42-bit message. + irsend.sendSanyoLC7461(0x1234567890A); + irsend.makeDecodeResult(); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, + 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)); + // And should fail for a bad value. + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, + true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, + false)); + EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); + EXPECT_EQ(SANYO_LC7461_BITS, irsend.capture.bits); + EXPECT_EQ(0x1234567890A, irsend.capture.value); + EXPECT_EQ(0x91A, irsend.capture.address); + EXPECT_EQ(0x89, irsend.capture.command); + + // Shouldn't pass if strict off and looking for a smaller size. + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 34, false)); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeSanyoLC7461, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Sanyo LC7461 64-bit message. + irsend.sendSanyoLC7461(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, 64, false)); + EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0xFFFF, irsend.capture.address); + EXPECT_EQ(0xFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeSanyoLC7461, DecodeGlobalCacheExample) { +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(); + +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); + +// 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 +TEST(TestDecodeSanyoLC7461, FailToDecodeNonSanyoLC7461Example) { + 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.decodeSanyoLC7461(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, SANYO_LC7461_BITS, + false)); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp new file mode 100644 index 000000000..0329b4e27 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sharp_test.cpp @@ -0,0 +1,357 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for encodeSharp(). + +TEST(TestEncodeSharp, NormalEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x2, irsend.encodeSharp(0, 0)); + EXPECT_EQ(0x4202, irsend.encodeSharp(1, 1)); + EXPECT_EQ(0x4102, irsend.encodeSharp(1, 2)); + EXPECT_EQ(0x62E2, irsend.encodeSharp(0x43, 0x1D)); + EXPECT_EQ(0x2AAA, irsend.encodeSharp(0xAA, 0x55)); + EXPECT_EQ(0x7FFE, irsend.encodeSharp(0x1F, 0xFF)); + EXPECT_EQ(0x454A, irsend.encodeSharp(0x11, 0x4A)); +} + +TEST(TestEncodeSharp, AdvancedEncoding) { + IRsendTest irsend(4); + EXPECT_EQ(0x0, irsend.encodeSharp(0, 0, 0, 0)); + EXPECT_EQ(0x1, irsend.encodeSharp(0, 0, 0, 1)); + EXPECT_EQ(0x2, irsend.encodeSharp(0, 0, 1, 0)); + EXPECT_EQ(0x3, irsend.encodeSharp(0, 0, 1, 1)); + EXPECT_EQ(0x4200, irsend.encodeSharp(1, 1, 0, 0)); + EXPECT_EQ(0x4203, irsend.encodeSharp(1, 1, 1, 1)); + + EXPECT_EQ(0x4200, irsend.encodeSharp(1, 1, 0, 0, false)); + EXPECT_EQ(0x4201, irsend.encodeSharp(1, 1, 0, 1, false)); + EXPECT_EQ(0x4203, irsend.encodeSharp(1, 1, 1, 1, false)); + + EXPECT_EQ(0x0404, irsend.encodeSharp(1, 1, 0, 0, true)); + EXPECT_EQ(0x0405, irsend.encodeSharp(1, 1, 0, 1, true)); + EXPECT_EQ(0x0407, irsend.encodeSharp(1, 1, 1, 1, true)); + + EXPECT_EQ(0x454A, irsend.encodeSharp(0x11, 0x52, 1, 0, true)); +} + + +// Tests for sendSharp(). + +// Test sending typical data only. +TEST(TestSendSharp, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSharp(0x11, 0x52); + EXPECT_EQ( + "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" + "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendSharp, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSharp(0x11, 0x52, SHARP_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" + "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" + "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendSharp, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSharp(0x0, 0x0, 8); + EXPECT_EQ( + "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); + + irsend.reset(); + irsend.sendSharp(0x0, 0x0, 16); + EXPECT_EQ( + "m260s780m260s780m260s780m260s780m260s780m260s780m260s780m260s780" + "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" + "m260s43602" + "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); +} + +// Tests for sendSharpRaw(). + +// Test sending typical data only. +TEST(TestSendSharpRaw, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSharpRaw(0x454A); + EXPECT_EQ( + "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" + "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendSharpRaw, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSharpRaw(0x454A, SHARP_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" + "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s1820m260s780m260s780m260s1820m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s780m260s780m260s780m260s1820m260s1820m260s780m260s1820" + "m260s780m260s1820m260s1820m260s780m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendSharpRaw, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendSharpRaw(0x2, 8); + EXPECT_EQ( + "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" + "m260s43602" + "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); + + irsend.reset(); + irsend.sendSharpRaw(0x2, 16); + EXPECT_EQ( + "m260s780m260s780m260s780m260s780m260s780m260s780m260s780m260s780" + "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s780" + "m260s43602" + "m260s780m260s780m260s780m260s780m260s780m260s780m260s1820m260s1820" + "m260s1820m260s1820m260s1820m260s1820m260s1820m260s1820m260s780m260s1820" + "m260s43602", irsend.outputStr()); +} + +// Tests for decodeSharp(). + +// Decode normal Sharp messages. +TEST(TestDecodeSharp, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Sharp 15-bit message. + irsend.reset(); + irsend.sendSharpRaw(0x454A); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(0x454A, irsend.capture.value); + EXPECT_EQ(0x11, irsend.capture.address); + EXPECT_EQ(0x4A, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal Sharp 15-bit message. + irsend.reset(); + irsend.sendSharpRaw(irsend.encodeSharp(0x07, 0x99)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(0x7266, irsend.capture.value); + EXPECT_EQ(0x07, irsend.capture.address); + EXPECT_EQ(0x99, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); + + // Synthesised Normal Sharp 15-bit message. + irsend.reset(); + irsend.sendSharpRaw(irsend.encodeSharp(0x1, 0x1)); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(0x4202, irsend.capture.value); + EXPECT_EQ(0x1, irsend.capture.address); + EXPECT_EQ(0x1, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Sharp messages. +TEST(TestDecodeSharp, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Sharp 15-bit message with 1 repeat. + irsend.reset(); + irsend.sendSharpRaw(0x7266, SHARP_BITS, 1); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, SHARP_BITS, true)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(SHARP_BITS, 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)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(SHARP_BITS, irsend.capture.bits); + EXPECT_EQ(0x7266, irsend.capture.value); +} + +// Decode unsupported Sharp messages. +TEST(TestDecodeSharp, DecodeWithNonStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + 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)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 8, false)); + EXPECT_EQ(SHARP, 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); + + irsend.reset(); + 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)); + + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, 32, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 32, false)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(32, irsend.capture.bits); + EXPECT_EQ(0x12345678, irsend.capture.value); + EXPECT_EQ(0x8, irsend.capture.address); + EXPECT_EQ(0x79, irsend.capture.command); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeSharp, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal value & size Sharp 64-bit message. + irsend.sendSharpRaw(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 64, false)); + EXPECT_EQ(SHARP, irsend.capture.decode_type); + EXPECT_EQ(64, irsend.capture.bits); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); + EXPECT_EQ(0x1F, irsend.capture.address); + EXPECT_EQ(0xFF, irsend.capture.command); +} + +// Decode a 'real' example via GlobalCache +TEST(TestDecodeSharp, DecodeGlobalCacheExample) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + 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}; + 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(0x454A, irsend.capture.value); + EXPECT_EQ(0x11, irsend.capture.address); + EXPECT_EQ(0x4A, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Fail to decode a non-Sharp example via GlobalCache +TEST(TestDecodeSharp, FailToDecodeNonSharpExample) { + 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[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)); + + // 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}; + + irsend.sendGC(gc_half, 35); + irsend.makeDecodeResult(); + + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, SHARP_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 new file mode 100644 index 000000000..b5750b3b1 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sherwood_test.cpp @@ -0,0 +1,72 @@ +// 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 new file mode 100644 index 000000000..76d351441 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Sony_test.cpp @@ -0,0 +1,323 @@ +// 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/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp new file mode 100644 index 000000000..4978bb6f5 --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/test/ir_Whynter_test.cpp @@ -0,0 +1,247 @@ +// Copyright 2017 David Conran + +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendWhynter(). + +// Test sending typical data only. +TEST(TestSendWhynter, SendDataOnly) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendWhynter(0x0); + EXPECT_EQ( + "m750s750m2850s2850" + "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" + "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" + "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" + "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" + "m750s108000", irsend.outputStr()); + + irsend.reset(); + irsend.sendWhynter(0xFFFFFFFF); + EXPECT_EQ( + "m750s750m2850s2850" + "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" + "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" + "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" + "m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150m750s2150" + "m750s108000", irsend.outputStr()); + + irsend.reset(); + irsend.sendWhynter(0x87654321); + EXPECT_EQ( + "m750s750m2850s2850" + "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" + "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" + "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" + "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" + "m750s108000", irsend.outputStr()); +} + +// Test sending with different repeats. +TEST(TestSendWhynter, SendWithRepeats) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendWhynter(0x87654321, WHYNTER_BITS, 0); // 0 repeats. + EXPECT_EQ( + "m750s750m2850s2850" + "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" + "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" + "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" + "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" + "m750s108000", irsend.outputStr()); + + irsend.reset(); + irsend.sendWhynter(0x87654321, WHYNTER_BITS, 1); // 1 repeat. + EXPECT_EQ( + "m750s750m2850s2850" + "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" + "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" + "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" + "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" + "m750s108000" + "m750s750m2850s2850" + "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" + "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" + "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" + "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" + "m750s108000", irsend.outputStr()); + irsend.sendWhynter(0x87654321, WHYNTER_BITS, 2); // 2 repeats. + EXPECT_EQ( + "m750s750m2850s2850" + "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" + "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" + "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" + "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" + "m750s108000" + "m750s750m2850s2850" + "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" + "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" + "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" + "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" + "m750s108000" + "m750s750m2850s2850" + "m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150m750s2150" + "m750s750m750s2150m750s2150m750s750m750s750m750s2150m750s750m750s2150" + "m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150m750s2150" + "m750s750m750s750m750s2150m750s750m750s750m750s750m750s750m750s2150" + "m750s108000", irsend.outputStr()); +} + +// Test sending an atypical data size. +TEST(TestSendWhynter, SendUnusualSize) { + IRsendTest irsend(4); + irsend.begin(); + + irsend.reset(); + irsend.sendWhynter(0x0, 8); + EXPECT_EQ( + "m750s750m2850s2850" + "m750s750m750s750m750s750m750s750m750s750m750s750m750s750m750s750" + "m750s108000", irsend.outputStr()); + + irsend.reset(); + irsend.sendWhynter(0x1234567890ABCDEF, 64); + EXPECT_EQ( + "m750s750m2850s2850" + "m750s750m750s750m750s750m750s2150m750s750m750s750m750s2150m750s750" + "m750s750m750s750m750s2150m750s2150m750s750m750s2150m750s750m750s750" + "m750s750m750s2150m750s750m750s2150m750s750m750s2150m750s2150m750s750" + "m750s750m750s2150m750s2150m750s2150m750s2150m750s750m750s750m750s750" + "m750s2150m750s750m750s750m750s2150m750s750m750s750m750s750m750s750" + "m750s2150m750s750m750s2150m750s750m750s2150m750s750m750s2150m750s2150" + "m750s2150m750s2150m750s750m750s750m750s2150m750s2150m750s750m750s2150" + "m750s2150m750s2150m750s2150m750s750m750s2150m750s2150m750s2150m750s2150" + "m750s108000", irsend.outputStr()); +} + +// Tests for decodeWhynter(). + +// Decode normal Whynter messages. +TEST(TestDecodeWhynter, NormalDecodeWithStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Whynter 32-bit message. + irsend.reset(); + irsend.sendWhynter(0x87654321); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(0x87654321, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + EXPECT_FALSE(irsend.capture.repeat); +} + +// Decode normal repeated Whynter messages. +TEST(TestDecodeWhynter, NormalDecodeWithRepeatAndStrict) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + // Normal Whynter 32-bit message with 2 repeats. + irsend.reset(); + irsend.sendWhynter(0x87654321, WHYNTER_BITS, 2); + irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, true)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(WHYNTER_BITS, 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)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(WHYNTER_BITS, 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)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(WHYNTER_BITS, irsend.capture.bits); + EXPECT_EQ(0x87654321, irsend.capture.value); +} + +// Decode unsupported Whynter messages. +TEST(TestDecodeWhynter, DecodeWithNonStrictSizes) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + 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, 8, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 8, false)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(8, irsend.capture.bits); + EXPECT_EQ(0x12, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); + + irsend.reset(); + 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)); + + irsend.makeDecodeResult(); + // Should fail with strict when we ask for the wrong bit size. + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, 40, true)); + // Should pass if strict off. + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 40, false)); + EXPECT_EQ(WHYNTER, irsend.capture.decode_type); + EXPECT_EQ(40, irsend.capture.bits); + EXPECT_EQ(0x1234567890, irsend.capture.value); + EXPECT_EQ(0x0, irsend.capture.address); + EXPECT_EQ(0x0, irsend.capture.command); +} + +// Decode (non-standard) 64-bit messages. +TEST(TestDecodeWhynter, Decode64BitMessages) { + IRsendTest irsend(4); + IRrecv irrecv(4); + irsend.begin(); + + irsend.reset(); + // Illegal size Whynter 64-bit message. + irsend.sendWhynter(0xFFFFFFFFFFFFFFFF, 64); + irsend.makeDecodeResult(); + // Should work with a 'normal' match (not strict) + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 64, false)); + EXPECT_EQ(WHYNTER, 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); +} + +// Fail to decode a non-Whynter example via GlobalCache +TEST(TestDecodeWhynter, FailToDecodeNonWhynterExample) { + 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.decodeWhynter(&irsend.capture)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, WHYNTER_BITS, false)); +} diff --git a/lib/IRremoteESP8266-2.2.1.02/tools/Makefile b/lib/IRremoteESP8266-2.2.1.02/tools/Makefile new file mode 100644 index 000000000..84bf6569b --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/tools/Makefile @@ -0,0 +1,136 @@ +# SYNOPSIS: +# +# make [all] - makes everything. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project, except GTEST_HEADERS, which you can use in your own targets +# but shouldn't modify. + + +# Where to find user code. +USER_DIR = ../src + +# Where to find test code. +TEST_DIR = ../test + +# Flags passed to the preprocessor. +# Set Google Test's header directory as a system directory, such that +# the compiler doesn't generate warnings in Google Test headers. +CPPFLAGS += -DUNIT_TEST + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra -pthread + +all : gc_decode + +clean : + rm -f *.o gc_decode + + +# 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_GlobalCache.o ir_Nikai.o +# Common object files +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 \ + $(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h +# Common test dependencies +COMMON_TEST_DEPS = $(COMMON_DEPS) $(TEST_DIR)/IRsend_test.h + +gc_decode.o : gc_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -I$(TEST_DIR) -c gc_decode.cpp + +gc_decode : $(COMMON_OBJ) gc_decode.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + + +IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp + +IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRtimer.cpp + +IRsend.o : $(USER_DIR)/IRsend.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRremoteESP8266.h + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRsend.cpp + +IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP8266.h $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRrecv.cpp + + +ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp + +ir_GlobalCache.o : $(USER_DIR)/ir_GlobalCache.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GlobalCache.cpp + +ir_Sherwood.o : $(USER_DIR)/ir_Sherwood.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sherwood.cpp + +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) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp + +ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Kelvinator.cpp + +ir_JVC.o : $(USER_DIR)/ir_JVC.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_JVC.cpp + +ir_RCMM.o : $(USER_DIR)/ir_RCMM.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RCMM.cpp + +ir_LG.o : $(USER_DIR)/ir_LG.h $(USER_DIR)/ir_LG.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_LG.cpp + +ir_Mitsubishi.o : $(USER_DIR)/ir_Mitsubishi.h $(USER_DIR)/ir_Mitsubishi.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Mitsubishi.cpp + +ir_Fujitsu.o : $(USER_DIR)/ir_Fujitsu.h $(USER_DIR)/ir_Fujitsu.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Fujitsu.cpp + +ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp + +ir_RC5_RC6.o : $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RC5_RC6.cpp + +ir_Panasonic.o : $(USER_DIR)/ir_Panasonic.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Panasonic.cpp + +ir_Dish.o : $(USER_DIR)/ir_Dish.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Dish.cpp + +ir_Whynter.o : $(USER_DIR)/ir_Whynter.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whynter.cpp + +ir_Coolix.o : $(USER_DIR)/ir_Coolix.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Coolix.cpp + +ir_Aiwa.o : $(USER_DIR)/ir_Aiwa.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Aiwa.cpp + +ir_Denon.o : $(USER_DIR)/ir_Denon.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Denon.cpp + +ir_Sanyo.o : $(USER_DIR)/ir_Sanyo.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sanyo.cpp + +ir_Daikin.o : $(USER_DIR)/ir_Daikin.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Daikin.cpp + +ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Gree.cpp + +ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pronto.cpp + +ir_Nikai.o : $(USER_DIR)/ir_Nikai.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Nikai.cpp diff --git a/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp new file mode 100644 index 000000000..9c3d316ca --- /dev/null +++ b/lib/IRremoteESP8266-2.2.1.02/tools/gc_decode.cpp @@ -0,0 +1,106 @@ +// 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/NeoPixelBus-2.2.9/.gitattributes b/lib/NeoPixelBus-2.2.9/.gitattributes new file mode 100644 index 000000000..412eeda78 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/lib/NeoPixelBus-2.2.9/.gitignore b/lib/NeoPixelBus-2.2.9/.gitignore new file mode 100644 index 000000000..6dae74742 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/.gitignore @@ -0,0 +1,36 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Icon must ends with two \r. +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes diff --git a/lib/NeoPixelBus-2.2.9/COPYING b/lib/NeoPixelBus-2.2.9/COPYING new file mode 100644 index 000000000..10926e87f --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/lib/NeoPixelBus-2.2.9/ReadMe.md b/lib/NeoPixelBus-2.2.9/ReadMe.md new file mode 100644 index 000000000..580e72426 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/ReadMe.md @@ -0,0 +1,34 @@ +# NeoPixelBus + +[![Donate](http://img.shields.io/paypal/donate.png?color=yellow)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6AA97KE54UJR4) + +Arduino NeoPixel library + +A library to control one wire protocol RGB and RGBW leds like SK6812, WS2811, WS2812 and WS2813 that are commonly refered to as NeoPixels and two wire protocol RGB like APA102 commonly refered to as DotStars. +Supports most Arduino platforms. +This is the most funtional library for the Esp8266 as it provides solutions for all Esp8266 module types even when WiFi is used. + + +Please read this best practices link before connecting your NeoPixels, it will save you alot of time and effort. +[Adafruit NeoPixel Best Practices](https://learn.adafruit.com/adafruit-neopixel-uberguide/best-practices) + +For quick questions jump on Gitter and ask away. +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Makuna/NeoPixelBus?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +For bugs, make sure there isn't an active issue and then create one. + +## Documentation +[See Wiki](https://github.com/Makuna/NeoPixelBus/wiki) + +## Installing This Library (prefered, you just want to use it) +Open the Library Manager and search for "NeoPixelBus by Makuna" and install + +## Installing This Library From GitHub (advanced, you want to contribute) +Create a directory in your Arduino\Library folder named "NeoPixelBus" +Clone (Git) this project into that folder. +It should now show up in the import list when you restart Arduino IDE. + + + + + diff --git a/lib/NeoPixelBus-2.2.9/examples/DotStarTest/DotStarTest.ino b/lib/NeoPixelBus-2.2.9/examples/DotStarTest/DotStarTest.ino new file mode 100644 index 000000000..45201ab1e --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/DotStarTest/DotStarTest.ino @@ -0,0 +1,88 @@ +// DotStarTest +// This example will cycle between showing four pixels as Red, Green, Blue, White +// and then showing those pixels as Black. +// +// There is serial output of the current state so you can confirm and follow along +// + +#include + +const uint16_t PixelCount = 4; // this example assumes 4 pixels, making it smaller will cause a failure + +// make sure to set this to the correct pins +const uint8_t DotClockPin = 2; +const uint8_t DotDataPin = 3; + +#define colorSaturation 128 + +// for software bit bang +NeoPixelBus strip(PixelCount, DotClockPin, DotDataPin); + +// for hardware SPI (best performance but must use hardware pins) +//NeoPixelBus strip(PixelCount); + +// DotStars that support RGB color and a overall luminance/brightness value +// NeoPixelBus strip(PixelCount, DotClockPin, DotDataPin); +// DotStars that support RGBW color with a seperate white element +//NeoPixelBus strip(PixelCount, DotClockPin, DotDataPin); + +RgbColor red(colorSaturation, 0, 0); +RgbColor green(0, colorSaturation, 0); +RgbColor blue(0, 0, colorSaturation); +RgbColor white(colorSaturation); +RgbColor black(0); + +// for use with RGB DotStars when using the luminance/brightness global value +// note that its range is only 0 - 31 (31 is full bright) and +// also note that it is not useful for POV displays as it will cause more flicker +RgbwColor redL(colorSaturation, 0, 0, 31); // use white value to store luminance +RgbwColor greenL(0, colorSaturation, 0, 31); // use white value to store luminance +RgbwColor blueL(0, 0, colorSaturation, 31); // use white value to store luminance +RgbwColor whiteL(255, 255, 255, colorSaturation / 8); // luminance is only 0-31 + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + Serial.flush(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.ClearTo(black); + strip.Show(); + + Serial.println(); + Serial.println("Running..."); +} + + +void loop() +{ + delay(5000); + + Serial.println("Colors R, G, B, W..."); + + // set the colors, + strip.SetPixelColor(0, red); + strip.SetPixelColor(1, green); + strip.SetPixelColor(2, blue); + strip.SetPixelColor(3, white); + strip.Show(); + + + delay(5000); + + Serial.println("Off ..."); + + // turn off the pixels + strip.SetPixelColor(0, black); + strip.SetPixelColor(1, black); + strip.SetPixelColor(2, black); + strip.SetPixelColor(3, black); + strip.Show(); + +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/NeoPixelBrightness/NeoPixelBrightness.ino b/lib/NeoPixelBus-2.2.9/examples/NeoPixelBrightness/NeoPixelBrightness.ino new file mode 100644 index 000000000..01af6cb3a --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/NeoPixelBrightness/NeoPixelBrightness.ino @@ -0,0 +1,83 @@ +// NeoPixelBrightness +// This example will cycle brightness from high to low of +// three pixels colored Red, Green, Blue. +// This demonstrates the use of the NeoPixelBrightnessBus +// with integrated brightness support +// +// There is serial output of the current state so you can +// confirm and follow along +// + +#include // instead of NeoPixelBus.h + +const uint16_t PixelCount = 3; // this example assumes 3 pixels, making it smaller will cause a failure +const uint8_t PixelPin = 14; // make sure to set this to the correct pin, ignored for Esp8266 + +#define colorSaturation 255 // saturation of color constants +RgbColor red(colorSaturation, 0, 0); +RgbColor green(0, colorSaturation, 0); +RgbColor blue(0, 0, colorSaturation); + +// Make sure to provide the correct color order feature +// for your NeoPixels +NeoPixelBrightnessBus strip(PixelCount, PixelPin); + +// you loose the original color the lower the dim value used +// here due to quantization +const uint8_t c_MinBrightness = 8; +const uint8_t c_MaxBrightness = 255; + +int8_t direction; // current direction of dimming + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + Serial.flush(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.Show(); + + direction = -1; // default to dim first + + Serial.println(); + Serial.println("Running..."); + + // set our three original colors + strip.SetPixelColor(0, red); + strip.SetPixelColor(1, green); + strip.SetPixelColor(2, blue); + + strip.Show(); +} + + +void loop() +{ + uint8_t brightness = strip.GetBrightness(); + Serial.println(brightness); + + delay(100); + + // swap diection of dim when limits are reached + // + if (direction < 0 && brightness <= c_MinBrightness) + { + direction = 1; + } + else if (direction > 0 && brightness >= c_MaxBrightness) + { + direction = -1; + } + // apply dimming + brightness += direction; + strip.SetBrightness(brightness); + + // show the results + strip.Show(); +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/NeoPixelGamma/NeoPixelGamma.ino b/lib/NeoPixelBus-2.2.9/examples/NeoPixelGamma/NeoPixelGamma.ino new file mode 100644 index 000000000..3ed91524e --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/NeoPixelGamma/NeoPixelGamma.ino @@ -0,0 +1,95 @@ +// NeoPixelGamma +// This example will display a timed series of color gradiants with gamma correction +// and then without. +// If the last pixel is on, then the colors being shown are color corrected. +// It will show Red grandiant, Green grandiant, Blue grandiant, a White grandiant, and +// then repeat. +// +// This will demonstrate the use of the NeoGamma class +// +// + +#include +#include + +const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); + +// uncomment only one of these to compare memory use or speed +// +// NeoGamma colorGamma; +NeoGamma colorGamma; + +void DrawPixels(bool corrected, HslColor startColor, HslColor stopColor) +{ + for (uint16_t index = 0; index < strip.PixelCount() - 1; index++) + { + float progress = index / static_cast(strip.PixelCount() - 2); + RgbColor color = HslColor::LinearBlend(startColor, stopColor, progress); + if (corrected) + { + color = colorGamma.Correct(color); + } + strip.SetPixelColor(index, color); + } + + // use the last pixel to indicate if we are showing corrected colors or not + if (corrected) + { + strip.SetPixelColor(strip.PixelCount() - 1, RgbColor(64)); + } + else + { + strip.SetPixelColor(strip.PixelCount() - 1, RgbColor(0)); + } + + strip.Show(); +} + +void setup() +{ + strip.Begin(); + strip.Show(); +} + +void loop() +{ + HslColor startColor; + HslColor stopColor; + + // red color + startColor = HslColor(0.0f, 1.0f, 0.0f); + stopColor = HslColor(0.0f, 1.0f, 0.5f); + DrawPixels(true, startColor, stopColor); + delay(5000); + DrawPixels(false, startColor, stopColor); + delay(5000); + + // green color + startColor = HslColor(0.33f, 1.0f, 0.0f); + stopColor = HslColor(0.33f, 1.0f, 0.5f); + DrawPixels(true, startColor, stopColor); + delay(5000); + DrawPixels(false, startColor, stopColor); + delay(5000); + + // blue color + startColor = HslColor(0.66f, 1.0f, 0.0f); + stopColor = HslColor(0.66f, 1.0f, 0.5f); + DrawPixels(true, startColor, stopColor); + delay(5000); + DrawPixels(false, startColor, stopColor); + delay(5000); + + // white color + startColor = HslColor(0.0f, 0.0f, 0.0f); + stopColor = HslColor(0.0f, 0.0f, 0.5f); + DrawPixels(true, startColor, stopColor); + delay(5000); + DrawPixels(false, startColor, stopColor); + delay(5000); +} \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/examples/NeoPixelTest/NeoPixelTest.ino b/lib/NeoPixelBus-2.2.9/examples/NeoPixelTest/NeoPixelTest.ino new file mode 100644 index 000000000..6d323b884 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/NeoPixelTest/NeoPixelTest.ino @@ -0,0 +1,140 @@ +// NeoPixelTest +// This example will cycle between showing four pixels as Red, Green, Blue, White +// and then showing those pixels as Black. +// +// Included but commented out are examples of configuring a NeoPixelBus for +// different color order including an extra white channel, different data speeds, and +// for Esp8266 different methods to send the data. +// NOTE: You will need to make sure to pick the one for your platform +// +// +// There is serial output of the current state so you can confirm and follow along +// + +#include + +const uint16_t PixelCount = 4; // this example assumes 4 pixels, making it smaller will cause a failure +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +#define colorSaturation 128 + +// three element pixels, in different order and speeds +NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); + +// For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. +// There are other Esp8266 alternative methods that provide more pin options, but also have +// other side effects. +//NeoPixelBus strip(PixelCount); +// +// NeoEsp8266Uart800KbpsMethod uses GPI02 instead + +// You can also use one of these for Esp8266, +// each having their own restrictions +// +// These two are the same as above as the DMA method is the default +// NOTE: These will ignore the PIN and use GPI03 pin +//NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); + +// Uart method is good for the Esp-01 or other pin restricted modules +// NOTE: These will ignore the PIN and use GPI02 pin +//NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); + +// The bitbang method is really only good if you are not using WiFi features of the ESP +// It works with all but pin 16 +//NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); + +// four element pixels, RGBW +//NeoPixelBus strip(PixelCount, PixelPin); + +RgbColor red(colorSaturation, 0, 0); +RgbColor green(0, colorSaturation, 0); +RgbColor blue(0, 0, colorSaturation); +RgbColor white(colorSaturation); +RgbColor black(0); + +HslColor hslRed(red); +HslColor hslGreen(green); +HslColor hslBlue(blue); +HslColor hslWhite(white); +HslColor hslBlack(black); + + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + Serial.flush(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.Show(); + + + Serial.println(); + Serial.println("Running..."); +} + + +void loop() +{ + delay(5000); + + Serial.println("Colors R, G, B, W..."); + + // set the colors, + // if they don't match in order, you need to use NeoGrbFeature feature + strip.SetPixelColor(0, red); + strip.SetPixelColor(1, green); + strip.SetPixelColor(2, blue); + strip.SetPixelColor(3, white); + // the following line demonstrates rgbw color support + // if the NeoPixels are rgbw types the following line will compile + // if the NeoPixels are anything else, the following line will give an error + //strip.SetPixelColor(3, RgbwColor(colorSaturation)); + strip.Show(); + + + delay(5000); + + Serial.println("Off ..."); + + // turn off the pixels + strip.SetPixelColor(0, black); + strip.SetPixelColor(1, black); + strip.SetPixelColor(2, black); + strip.SetPixelColor(3, black); + strip.Show(); + + delay(5000); + + Serial.println("HSL Colors R, G, B, W..."); + + // set the colors, + // if they don't match in order, you may need to use NeoGrbFeature feature + strip.SetPixelColor(0, hslRed); + strip.SetPixelColor(1, hslGreen); + strip.SetPixelColor(2, hslBlue); + strip.SetPixelColor(3, hslWhite); + strip.Show(); + + + delay(5000); + + Serial.println("Off again..."); + + // turn off the pixels + strip.SetPixelColor(0, hslBlack); + strip.SetPixelColor(1, hslBlack); + strip.SetPixelColor(2, hslBlack); + strip.SetPixelColor(3, hslBlack); + strip.Show(); + +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino new file mode 100644 index 000000000..66b4d4aca --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelAnimation/NeoPixelAnimation.ino @@ -0,0 +1,225 @@ +// NeoPixelAnimation +// This example will randomly pick a new color for each pixel and animate +// the current color to the new color over a random small amount of time, using +// a randomly selected animation curve. +// It will repeat this process once all pixels have finished the animation +// +// This will demonstrate the use of the NeoPixelAnimator extended time feature. +// This feature allows for different time scales to be used, allowing slow extended +// animations to be created. +// +// This will demonstrate the use of the NeoEase animation ease methods; that provide +// simulated acceleration to the animations. +// +// It also includes platform specific code for Esp8266 that demonstrates easy +// animation state and function definition inline. This is not available on AVR +// Arduinos; but the AVR compatible code is also included for comparison. +// +// The example includes some serial output that you can follow along with as it +// does the animation. +// + +#include +#include + +const uint16_t PixelCount = 4; // make sure to set this to the number of pixels in your strip +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +NeoPixelBus strip(PixelCount, PixelPin); +// For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. +// There are other Esp8266 alternative methods that provide more pin options, but also have +// other side effects. +//NeoPixelBus strip(PixelCount); +// +// NeoEsp8266Uart800KbpsMethod uses GPI02 instead + + +// NeoPixel animation time management object +NeoPixelAnimator animations(PixelCount, NEO_CENTISECONDS); + +// create with enough animations to have one per pixel, depending on the animation +// effect, you may need more or less. +// +// since the normal animation time range is only about 65 seconds, by passing timescale value +// to the NeoPixelAnimator constructor we can increase the time range, but we also increase +// the time between the animation updates. +// NEO_CENTISECONDS will update the animations every 100th of a second rather than the default +// of a 1000th of a second, but the time range will now extend from about 65 seconds to about +// 10.9 minutes. But you must remember that the values passed to StartAnimations are now +// in centiseconds. +// +// Possible values from 1 to 32768, and there some helpful constants defined as... +// NEO_MILLISECONDS 1 // ~65 seconds max duration, ms updates +// NEO_CENTISECONDS 10 // ~10.9 minutes max duration, centisecond updates +// NEO_DECISECONDS 100 // ~1.8 hours max duration, decisecond updates +// NEO_SECONDS 1000 // ~18.2 hours max duration, second updates +// NEO_DECASECONDS 10000 // ~7.5 days, 10 second updates +// + +#ifdef ARDUINO_ARCH_AVR +// for AVR, you need to manage the state due to lack of STL/compiler support +// for Esp8266 you can define the function using a lambda and state is created for you +// see below for an example +struct MyAnimationState +{ + RgbColor StartingColor; // the color the animation starts at + RgbColor EndingColor; // the color the animation will end at + AnimEaseFunction Easeing; // the acceleration curve it will use +}; + +MyAnimationState animationState[PixelCount]; +// one entry per pixel to match the animation timing manager + +void AnimUpdate(const AnimationParam& param) +{ + // first apply an easing (curve) to the animation + // this simulates acceleration to the effect + float progress = animationState[param.index].Easeing(param.progress); + + // this gets called for each animation on every time step + // progress will start at 0.0 and end at 1.0 + // we use the blend function on the RgbColor to mix + // color based on the progress given to us in the animation + RgbColor updatedColor = RgbColor::LinearBlend( + animationState[param.index].StartingColor, + animationState[param.index].EndingColor, + progress); + // apply the color to the strip + strip.SetPixelColor(param.index, updatedColor); +} +#endif + +void SetRandomSeed() +{ + uint32_t seed; + + // random works best with a seed that can use 31 bits + // analogRead on a unconnected pin tends toward less than four bits + seed = analogRead(0); + delay(1); + + for (int shifts = 3; shifts < 31; shifts += 3) + { + seed ^= analogRead(0) << shifts; + delay(1); + } + + // Serial.println(seed); + randomSeed(seed); +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + strip.Begin(); + strip.Show(); + + SetRandomSeed(); + + // just pick some colors + for (uint16_t pixel = 0; pixel < PixelCount; pixel++) + { + RgbColor color = RgbColor(random(255), random(255), random(255)); + strip.SetPixelColor(pixel, color); + } + + Serial.println(); + Serial.println("Running..."); +} + + +void SetupAnimationSet() +{ + // setup some animations + for (uint16_t pixel = 0; pixel < PixelCount; pixel++) + { + const uint8_t peak = 128; + + // pick a random duration of the animation for this pixel + // since values are centiseconds, the range is 1 - 4 seconds + uint16_t time = random(100, 400); + + // each animation starts with the color that was present + RgbColor originalColor = strip.GetPixelColor(pixel); + // and ends with a random color + RgbColor targetColor = RgbColor(random(peak), random(peak), random(peak)); + // with the random ease function + AnimEaseFunction easing; + + switch (random(3)) + { + case 0: + easing = NeoEase::CubicIn; + break; + case 1: + easing = NeoEase::CubicOut; + break; + case 2: + easing = NeoEase::QuadraticInOut; + break; + } + +#ifdef ARDUINO_ARCH_AVR + // each animation starts with the color that was present + animationState[pixel].StartingColor = originalColor; + // and ends with a random color + animationState[pixel].EndingColor = targetColor; + // using the specific curve + animationState[pixel].Easeing = easing; + + // now use the animation state we just calculated and start the animation + // which will continue to run and call the update function until it completes + animations.StartAnimation(pixel, time, AnimUpdate); +#else + // we must supply a function that will define the animation, in this example + // we are using "lambda expression" to define the function inline, which gives + // us an easy way to "capture" the originalColor and targetColor for the call back. + // + // this function will get called back when ever the animation needs to change + // the state of the pixel, it will provide a animation progress value + // from 0.0 (start of animation) to 1.0 (end of animation) + // + // we use this progress value to define how we want to animate in this case + // we call RgbColor::LinearBlend which will return a color blended between + // the values given, by the amount passed, hich is also a float value from 0.0-1.0. + // then we set the color. + // + // There is no need for the MyAnimationState struct as the compiler takes care + // of those details for us + AnimUpdateCallback animUpdate = [=](const AnimationParam& param) + { + // progress will start at 0.0 and end at 1.0 + // we convert to the curve we want + float progress = easing(param.progress); + + // use the curve value to apply to the animation + RgbColor updatedColor = RgbColor::LinearBlend(originalColor, targetColor, progress); + strip.SetPixelColor(pixel, updatedColor); + }; + + // now use the animation properties we just calculated and start the animation + // which will continue to run and call the update function until it completes + animations.StartAnimation(pixel, time, animUpdate); +#endif + } +} + +void loop() +{ + if (animations.IsAnimating()) + { + // the normal loop just needs these two to run the active animations + animations.UpdateAnimations(); + strip.Show(); + } + else + { + Serial.println(); + Serial.println("Setup Next Set..."); + // example function that sets up some animations + SetupAnimationSet(); + } +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelCylon/NeoPixelCylon.ino b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelCylon/NeoPixelCylon.ino new file mode 100644 index 000000000..4eec443d4 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelCylon/NeoPixelCylon.ino @@ -0,0 +1,123 @@ +// NeoPixelCylon +// This example will move a Cylon Red Eye back and forth across the +// the full collection of pixels on the strip. +// +// This will demonstrate the use of the NeoEase animation ease methods; that provide +// simulated acceleration to the animations. +// +// + +#include +#include + +const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 +const RgbColor CylonEyeColor(HtmlColor(0x7f0000)); + +NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); + +NeoPixelAnimator animations(2); // only ever need 2 animations + +uint16_t lastPixel = 0; // track the eye position +int8_t moveDir = 1; // track the direction of movement + +// uncomment one of the lines below to see the effects of +// changing the ease function on the movement animation +AnimEaseFunction moveEase = +// NeoEase::Linear; +// NeoEase::QuadraticInOut; +// NeoEase::CubicInOut; + NeoEase::QuarticInOut; +// NeoEase::QuinticInOut; +// NeoEase::SinusoidalInOut; +// NeoEase::ExponentialInOut; +// NeoEase::CircularInOut; + +void FadeAll(uint8_t darkenBy) +{ + RgbColor color; + for (uint16_t indexPixel = 0; indexPixel < strip.PixelCount(); indexPixel++) + { + color = strip.GetPixelColor(indexPixel); + color.Darken(darkenBy); + strip.SetPixelColor(indexPixel, color); + } +} + +void FadeAnimUpdate(const AnimationParam& param) +{ + if (param.state == AnimationState_Completed) + { + FadeAll(10); + animations.RestartAnimation(param.index); + } +} + +void MoveAnimUpdate(const AnimationParam& param) +{ + // apply the movement animation curve + float progress = moveEase(param.progress); + + // use the curved progress to calculate the pixel to effect + uint16_t nextPixel; + if (moveDir > 0) + { + nextPixel = progress * PixelCount; + } + else + { + nextPixel = (1.0f - progress) * PixelCount; + } + + // if progress moves fast enough, we may move more than + // one pixel, so we update all between the calculated and + // the last + if (lastPixel != nextPixel) + { + for (uint16_t i = lastPixel + moveDir; i != nextPixel; i += moveDir) + { + strip.SetPixelColor(i, CylonEyeColor); + } + } + strip.SetPixelColor(nextPixel, CylonEyeColor); + + lastPixel = nextPixel; + + if (param.state == AnimationState_Completed) + { + // reverse direction of movement + moveDir *= -1; + + // done, time to restart this position tracking animation/timer + animations.RestartAnimation(param.index); + } +} + +void SetupAnimations() +{ + // fade all pixels providing a tail that is longer the faster + // the pixel moves. + animations.StartAnimation(0, 5, FadeAnimUpdate); + + // take several seconds to move eye fron one side to the other + animations.StartAnimation(1, 2000, MoveAnimUpdate); +} + +void setup() +{ + strip.Begin(); + strip.Show(); + + SetupAnimations(); +} + +void loop() +{ + // this is all that is needed to keep it running + // and avoiding using delay() is always a good thing for + // any timing related routines + animations.UpdateAnimations(); + strip.Show(); +} diff --git a/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino new file mode 100644 index 000000000..45e66ec38 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunFadeInOut/NeoPixelFunFadeInOut.ino @@ -0,0 +1,132 @@ +// NeoPixelFunFadeInOut +// This example will randomly pick a color and fade all pixels to that color, then +// it will fade them to black and restart over +// +// This example demonstrates the use of a single animation channel to animate all +// the pixels at once. +// +#include +#include + +const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 +const uint8_t AnimationChannels = 1; // we only need one as all the pixels are animated at once + +NeoPixelBus strip(PixelCount, PixelPin); +// For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. +// There are other Esp8266 alternative methods that provide more pin options, but also have +// other side effects. +//NeoPixelBus strip(PixelCount); +// +// NeoEsp8266Uart800KbpsMethod uses GPI02 instead + +NeoPixelAnimator animations(AnimationChannels); // NeoPixel animation management object + +uint16_t effectState = 0; // general purpose variable used to store effect state + + +// what is stored for state is specific to the need, in this case, the colors. +// basically what ever you need inside the animation update function +struct MyAnimationState +{ + RgbColor StartingColor; + RgbColor EndingColor; +}; + +// one entry per pixel to match the animation timing manager +MyAnimationState animationState[AnimationChannels]; + +void SetRandomSeed() +{ + uint32_t seed; + + // random works best with a seed that can use 31 bits + // analogRead on a unconnected pin tends toward less than four bits + seed = analogRead(0); + delay(1); + + for (int shifts = 3; shifts < 31; shifts += 3) + { + seed ^= analogRead(0) << shifts; + delay(1); + } + + randomSeed(seed); +} + +// simple blend function +void BlendAnimUpdate(const AnimationParam& param) +{ + // this gets called for each animation on every time step + // progress will start at 0.0 and end at 1.0 + // we use the blend function on the RgbColor to mix + // color based on the progress given to us in the animation + RgbColor updatedColor = RgbColor::LinearBlend( + animationState[param.index].StartingColor, + animationState[param.index].EndingColor, + param.progress); + + // apply the color to the strip + for (uint16_t pixel = 0; pixel < PixelCount; pixel++) + { + strip.SetPixelColor(pixel, updatedColor); + } +} + +void FadeInFadeOutRinseRepeat(float luminance) +{ + if (effectState == 0) + { + // Fade upto a random color + // we use HslColor object as it allows us to easily pick a hue + // with the same saturation and luminance so the colors picked + // will have similiar overall brightness + RgbColor target = HslColor(random(360) / 360.0f, 1.0f, luminance); + uint16_t time = random(800, 2000); + + animationState[0].StartingColor = strip.GetPixelColor(0); + animationState[0].EndingColor = target; + + animations.StartAnimation(0, time, BlendAnimUpdate); + } + else if (effectState == 1) + { + // fade to black + uint16_t time = random(600, 700); + + animationState[0].StartingColor = strip.GetPixelColor(0); + animationState[0].EndingColor = RgbColor(0); + + animations.StartAnimation(0, time, BlendAnimUpdate); + } + + // toggle to the next effect state + effectState = (effectState + 1) % 2; +} + +void setup() +{ + strip.Begin(); + strip.Show(); + + SetRandomSeed(); +} + +void loop() +{ + if (animations.IsAnimating()) + { + // the normal loop just needs these two to run the active animations + animations.UpdateAnimations(); + strip.Show(); + } + else + { + // no animation runnning, start some + // + FadeInFadeOutRinseRepeat(0.2f); // 0.0 = black, 0.25 is normal, 0.5 is bright + } +} + + + diff --git a/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino new file mode 100644 index 000000000..3dea4c0e6 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunLoop/NeoPixelFunLoop.ino @@ -0,0 +1,141 @@ +// NeoPixelFunLoop +// This example will move a trail of light around a series of pixels. +// A ring formation of pixels looks best. +// The trail will have a slowly fading tail. +// +// This will demonstrate the use of the NeoPixelAnimator. +// It shows the advanced use an animation to control the modification and +// starting of other animations. +// It also shows the normal use of animating colors. +// It also demonstrates the ability to share an animation channel rather than +// hard code them to pixels. +// + +#include +#include + + +const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip +const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 +const uint16_t AnimCount = PixelCount / 5 * 2 + 1; // we only need enough animations for the tail and one extra + +const uint16_t PixelFadeDuration = 300; // third of a second +// one second divide by the number of pixels = loop once a second +const uint16_t NextPixelMoveDuration = 1000 / PixelCount; // how fast we move through the pixels + +NeoGamma colorGamma; // for any fade animations, best to correct gamma + +NeoPixelBus strip(PixelCount, PixelPin); +// For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. +// There are other Esp8266 alternative methods that provide more pin options, but also have +// other side effects. +//NeoPixelBus strip(PixelCount); +// +// NeoEsp8266Uart800KbpsMethod uses GPI02 instead + +// what is stored for state is specific to the need, in this case, the colors and +// the pixel to animate; +// basically what ever you need inside the animation update function +struct MyAnimationState +{ + RgbColor StartingColor; + RgbColor EndingColor; + uint16_t IndexPixel; // which pixel this animation is effecting +}; + +NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object +MyAnimationState animationState[AnimCount]; +uint16_t frontPixel = 0; // the front of the loop +RgbColor frontColor; // the color at the front of the loop + +void SetRandomSeed() +{ + uint32_t seed; + + // random works best with a seed that can use 31 bits + // analogRead on a unconnected pin tends toward less than four bits + seed = analogRead(0); + delay(1); + + for (int shifts = 3; shifts < 31; shifts += 3) + { + seed ^= analogRead(0) << shifts; + delay(1); + } + + // Serial.println(seed); + randomSeed(seed); +} + +void FadeOutAnimUpdate(const AnimationParam& param) +{ + // this gets called for each animation on every time step + // progress will start at 0.0 and end at 1.0 + // we use the blend function on the RgbColor to mix + // color based on the progress given to us in the animation + RgbColor updatedColor = RgbColor::LinearBlend( + animationState[param.index].StartingColor, + animationState[param.index].EndingColor, + param.progress); + // apply the color to the strip + strip.SetPixelColor(animationState[param.index].IndexPixel, + colorGamma.Correct(updatedColor)); +} + +void LoopAnimUpdate(const AnimationParam& param) +{ + // wait for this animation to complete, + // we are using it as a timer of sorts + if (param.state == AnimationState_Completed) + { + // done, time to restart this position tracking animation/timer + animations.RestartAnimation(param.index); + + // pick the next pixel inline to start animating + // + frontPixel = (frontPixel + 1) % PixelCount; // increment and wrap + if (frontPixel == 0) + { + // we looped, lets pick a new front color + frontColor = HslColor(random(360) / 360.0f, 1.0f, 0.25f); + } + + uint16_t indexAnim; + // do we have an animation available to use to animate the next front pixel? + // if you see skipping, then either you are going to fast or need to increase + // the number of animation channels + if (animations.NextAvailableAnimation(&indexAnim, 1)) + { + animationState[indexAnim].StartingColor = frontColor; + animationState[indexAnim].EndingColor = RgbColor(0, 0, 0); + animationState[indexAnim].IndexPixel = frontPixel; + + animations.StartAnimation(indexAnim, PixelFadeDuration, FadeOutAnimUpdate); + } + } +} + +void setup() +{ + strip.Begin(); + strip.Show(); + + SetRandomSeed(); + + // we use the index 0 animation to time how often we move to the next + // pixel in the strip + animations.StartAnimation(0, NextPixelMoveDuration, LoopAnimUpdate); +} + + +void loop() +{ + // this is all that is needed to keep it running + // and avoiding using delay() is always a good thing for + // any timing related routines + animations.UpdateAnimations(); + strip.Show(); +} + + + diff --git a/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino new file mode 100644 index 000000000..17d6b6a48 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelFunRandomChange/NeoPixelFunRandomChange.ino @@ -0,0 +1,116 @@ +// NeoPixelFunRandomChange +// This example will randomly select a number pixels and then +// start an animation to blend them from their current color to +// randomly selected a color +// + +#include +#include + +const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +NeoPixelBus strip(PixelCount, PixelPin); +// For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. +// There are other Esp8266 alternative methods that provide more pin options, but also have +// other side effects. +//NeoPixelBus strip(PixelCount); +// +// NeoEsp8266Uart800KbpsMethod uses GPI02 instead + +NeoPixelAnimator animations(PixelCount); // NeoPixel animation management object + +// what is stored for state is specific to the need, in this case, the colors. +// Basically what ever you need inside the animation update function +struct MyAnimationState +{ + RgbColor StartingColor; + RgbColor EndingColor; +}; + +// one entry per pixel to match the animation timing manager +MyAnimationState animationState[PixelCount]; + +void SetRandomSeed() +{ + uint32_t seed; + + // random works best with a seed that can use 31 bits + // analogRead on a unconnected pin tends toward less than four bits + seed = analogRead(0); + delay(1); + + for (int shifts = 3; shifts < 31; shifts += 3) + { + seed ^= analogRead(0) << shifts; + delay(1); + } + + // Serial.println(seed); + randomSeed(seed); +} + +// simple blend function +void BlendAnimUpdate(const AnimationParam& param) +{ + // this gets called for each animation on every time step + // progress will start at 0.0 and end at 1.0 + // we use the blend function on the RgbColor to mix + // color based on the progress given to us in the animation + RgbColor updatedColor = RgbColor::LinearBlend( + animationState[param.index].StartingColor, + animationState[param.index].EndingColor, + param.progress); + // apply the color to the strip + strip.SetPixelColor(param.index, updatedColor); +} + +void PickRandom(float luminance) +{ + // pick random count of pixels to animate + uint16_t count = random(PixelCount); + while (count > 0) + { + // pick a random pixel + uint16_t pixel = random(PixelCount); + + // pick random time and random color + // we use HslColor object as it allows us to easily pick a color + // with the same saturation and luminance + uint16_t time = random(100, 400); + animationState[pixel].StartingColor = strip.GetPixelColor(pixel); + animationState[pixel].EndingColor = HslColor(random(360) / 360.0f, 1.0f, luminance); + + animations.StartAnimation(pixel, time, BlendAnimUpdate); + + count--; + } +} + +void setup() +{ + strip.Begin(); + strip.Show(); + + SetRandomSeed(); +} + + +void loop() +{ + if (animations.IsAnimating()) + { + // the normal loop just needs these two to run the active animations + animations.UpdateAnimations(); + strip.Show(); + } + else + { + // no animations runnning, start some + // + PickRandom(0.2f); // 0.0 = black, 0.25 is normal, 0.5 is bright + } +} + + + diff --git a/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino new file mode 100644 index 000000000..bdc9af70c --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/animations/NeoPixelRotateLoop/NeoPixelRotateLoop.ino @@ -0,0 +1,97 @@ +// NeoPixelFunLoop +// This example will move a trail of light around a series of pixels. +// A ring formation of pixels looks best. +// The trail will have a slowly fading tail. +// +// This will demonstrate the use of the RotateRight method. +// + +#include +#include + + +const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip +const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 +const uint16_t AnimCount = 1; // we only need one +const uint16_t TailLength = 6; // length of the tail, must be shorter than PixelCount +const float MaxLightness = 0.4f; // max lightness at the head of the tail (0.5f is full bright) + +NeoGamma colorGamma; // for any fade animations, best to correct gamma + +NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); + +NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object + +void SetRandomSeed() +{ + uint32_t seed; + + // random works best with a seed that can use 31 bits + // analogRead on a unconnected pin tends toward less than four bits + seed = analogRead(0); + delay(1); + + for (int shifts = 3; shifts < 31; shifts += 3) + { + seed ^= analogRead(0) << shifts; + delay(1); + } + + // Serial.println(seed); + randomSeed(seed); +} + +void LoopAnimUpdate(const AnimationParam& param) +{ + // wait for this animation to complete, + // we are using it as a timer of sorts + if (param.state == AnimationState_Completed) + { + // done, time to restart this position tracking animation/timer + animations.RestartAnimation(param.index); + + // rotate the complete strip one pixel to the right on every update + strip.RotateRight(1); + } +} + +void DrawTailPixels() +{ + // using Hsl as it makes it easy to pick from similiar saturated colors + float hue = random(360) / 360.0f; + for (uint16_t index = 0; index < strip.PixelCount() && index <= TailLength; index++) + { + float lightness = index * MaxLightness / TailLength; + RgbColor color = HslColor(hue, 1.0f, lightness); + + strip.SetPixelColor(index, colorGamma.Correct(color)); + } +} + +void setup() +{ + strip.Begin(); + strip.Show(); + + SetRandomSeed(); + + // Draw the tail that will be rotated through all the rest of the pixels + DrawTailPixels(); + + // we use the index 0 animation to time how often we rotate all the pixels + animations.StartAnimation(0, 66, LoopAnimUpdate); +} + + +void loop() +{ + // this is all that is needed to keep it running + // and avoiding using delay() is always a good thing for + // any timing related routines + animations.UpdateAnimations(); + strip.Show(); +} + + diff --git a/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino new file mode 100644 index 000000000..56071b2b1 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/NeoPixelBitmap.ino @@ -0,0 +1,98 @@ +// NeoPixelBuffer +// This example will animate pixels using a bitmap stored on a SD card +// +// +// This will demonstrate the use of the NeoBitmapFile object +// NOTE: The images provided in the example directory should be copied to +// the root of the SD card so the below code will find it. +// NOTE: This sample and the included images were built for a 144 pixel strip so +// running this with a smaller string may not look as interesting. Try providing +// your own 24 bit bitmap for better results. + +#include +#include +#include +#include + +const int chipSelect = D8; // make sure to set this to your SD carder reader CS + +//typedef NeoGrbFeature MyPixelColorFeature; +typedef NeoGrbwFeature MyPixelColorFeature; + +const uint16_t PixelCount = 144; // the sample images are meant for 144 pixels +const uint16_t PixelPin = 2; +const uint16_t AnimCount = 1; // we only need one + +NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); +NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object + +// our NeoBitmapFile will use the same color feature as NeoPixelBus and +// we want it to use the SD File object +NeoBitmapFile image; + +uint16_t animState; + +void LoopAnimUpdate(const AnimationParam& param) +{ + // wait for this animation to complete, + // we are using it as a timer of sorts + if (param.state == AnimationState_Completed) + { + // done, time to restart this position tracking animation/timer + animations.RestartAnimation(param.index); + + // draw the complete row at animState to the complete strip + image.Blt(strip, 0, 0, animState, image.Width()); + animState = (animState + 1) % image.Height(); // increment and wrap + } +} + +void setup() { + Serial.begin(115200); + while (!Serial); // wait for serial attach + + strip.Begin(); + strip.Show(); + + Serial.print("Initializing SD card..."); + + // see if the card is present and can be initialized: + if (!SD.begin(chipSelect)) + { + Serial.println("Card failed, or not present"); + // don't do anything more: + return; + } + Serial.println("card initialized."); + + // open the file + File bitmapFile = SD.open("strings.bmp"); + if (!bitmapFile) + { + Serial.println("File open fail, or not present"); + // don't do anything more: + return; + } + + // initialize the image with the file + if (!image.Begin(bitmapFile)) + { + Serial.println("File format fail, not a supported bitmap"); + // don't do anything more: + return; + } + + animState = 0; + // we use the index 0 animation to time how often we rotate all the pixels + animations.StartAnimation(0, 30, LoopAnimUpdate); +} + +void loop() { + // this is all that is needed to keep it running + // and avoiding using delay() is always a good thing for + // any timing related routines + animations.UpdateAnimations(); + strip.Show(); +} \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/Strings.bmp b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBitmap/Strings.bmp new file mode 100644 index 0000000000000000000000000000000000000000..0ee3be6f14647c2b65a307451aeb70aaa1260c2f GIT binary patch literal 62262 zcmeI5`*T*undkexNC+V?2!*?4A%QFd7FWxFxmo5S1Hl+$f-xpUHkZgU##n=~EX!|v z2^o(QCzH%fWimU-?#xuBc4l^KYHMq1lDXuE{g3t^*iZNKzWw$&r_b$ukHFMU*Fl{3 zyytZH>2E*xr~4iM_SpYbri}4-gnvJ+|0}6A=DPm#f0oHVdm;U#r$gQARJD>CNWZt8 zJNBx7*QuNR>h6%L4f~JTO={{1b$Puyy-FQep+=Xg{w}qwn!V*}Sq-jK6Hlo- zULFKEUR5gb*9$%*7a-iwNG~M*`0c4 z#v97&0R5qF8SgLVw$74T)u}dht38jYqkZb!8a4U2y0g&_qJVpQqq@35oms68_11Ch zso2geU##}@t4n*-?C~&6{VVKUsV6;*Mu)m%0Rpe8x?WXR8^_HKHRpUgS5fCmsz0IL zox65|*YvG-O3Z>{N|gyiAIfT5G4-`s%krukSgdv|)3|`nl?`foK+SE6LfLbFc*9ql zcHAGB_9ycK3Qa=VdiY(;aHMok|w^*~QB%>$Y}nJ-T%4jo$H@)u;bt z!|}h|c=&IJjEe;XfG=Xa><OInq1CGrKyAJ+oNi9w4-l(w+01h00{XASaI?ZmWyyaxk~L_ zu7;PC`kr-0`=ocY)4I&}-4%6GXtP7j7^)0EH2Kz>K=$Iv7sFq)`dOq{MV)W8g4pMf z@(33oKn>WjUZViBI{KtKJE|`1R9Bx>HxH=W&j;j=MZ`TpFaaD-?cb=Y>Ppr@y31)L>3%Ni|-GOKop1Hcf%6-Sno_CHrSJzcpvU7oqBYI}n?8g>e}m)2>51@SeD zf@7c1M7gXE388_VQeEz?&+dH|yl&rlZ&BAG_j=3c=%`GOvf7_e1GAa|ggPJ%*wNgH zbVOifU^lr}qX3#`p4RkrXh_oKG5sld*$kPf$Zw!_c}ULDsi8RJ1?nWT0u36-mqq= z79}vQ5Jk+tSjPe>133r^BdawEh#^St8&$BXL{~RbW;m&D=%~X>G=dn6w+6xlI5Vh` z-L*`?b^WEMs%{#{W*}*M%aWcYqALPi5mZ+0P_wk6RF5=)?YVbAGbjra1O=HuUyueM za>FB1%IN0}PIbk;VAjreVT5-pOn&qkz_M}>y2IRnHa(@YsxCz#Ly+B>c^@j9ntuDq zktf5?mCC9!z(vD11V0O}z!1a6Krxtkp^lXJ2cViq2O#&w?9icd9|>s!?tNL$VTq`t zAO&869kv6QhD*7sE<_=N%EajbYPW8`d+PM5!$%Iwp{8qU-_dY2@t;LYT(M~4t^IYR zpeB^DN4YS#+EnRKcZ;`H;D^`+LUAZ3o>CR15kBlHau{N$A3|uLW)F?m$%~$9VlE-V zdKcAR+Ik5Fh?20$+l82Czk!!Ag~YrvLOCG%3+pXDF=QN6hSlINQ1^8v3_g$$Y2*4> zy=FCj4>>?k<8|e>zZ&1w!QQ^{!P=QE)2M%sChKdy6^d>{U|sULm6~_9c!nbyr?e=O zSm-F3v1OTPjA;9@x5yWhGa9nhnH(%o)7**bu}!rtee;F+CR6&i5MOsGh2Q5KQJSegE^Z%N(5uz7{H9h6$0 z`p7r%2HdcWiD&dq%AOkF@Ob*T`E~v31YGj8R z7*>62&hF~`(HXVtab1msb&6MgLtSJ*@W*oaV;rHoV?UzM3PS)d!XhD;UF>7YU*Pf; zn!>#L?glNeqNY`H4YA)sVmjQJuK!>-509$Tm(=&?n!p+Omd(@-|ExCt<=w@X-cl#d zm&fjRZ2YB_?gm~%LnJDpZ|KU|KmFKm8Sn^dHO%p^w;Y3X|;2|>hc8O zQu-A4HPi%B0K~zV027Dk!~BKYWG;rRbkyD`6?>B;c;-5_Gmv}(=^LoENBG`m5wg&i z34*jpvA72@jZro#Jw00O-@Fa_s(kw&)r~LfWO(hKCd~E=o^4UC@CE>l9Su&7IPxdZ`M~iAKqM4c5L8B>&r`Lhy{xD+O1172gSaHxNLa)z9)bAn%Nnxv z1MY2E&jlP6-^K1e$Pai_AYkU&Qjxfczbi>sg}5$8(ilAoCt77|cx4AmdWt>3Y=UI@7|>>MZ( zxe81P)?~O7)0GbftP3s6=uC}c64D~QMc-)2=E9?5#tnDwg4nI3FoD--#Ke?#&17!8 zs4zo}wd@5^C9e;OwNM}~O=5dw1kz&=Ei@5*gmhw?wMc3WnHzb;nP`ASd!rS%e}%x7 zB$-E(#88;ce7;<7MTiTRNOxv3LE6ZR6B}x+Fi^F<<+*DeJs(42t<@3t6z@(hmOr$I z;z0(K@J3+{0EY-B@g_xY>@!mfrj&;T#dR@qo%lY)Meb#^VARmG(L9xAfVendhI`VY zY_=j~_Xk7j=Ua91UaNgaOjj;Wk;z#;dem0j+6nG!UY4K(4gr~>yto`(fyt25MOq!H zT+M?04tqq5y1>CM&|Sd}J|CgGveK-eqE0s}DfEm^(r5D1qD6$JNlH=LVFg$y8`&){ zl4<|^3epjU<1zhH+@Blq5lIl*pzbLp)!)rt4i$Z(9M z@3!2^IjPQZcuDX}bq?#S55PJwk*NX9C2{0}7qhO_BK~&czNl(v2m`{}y*vfkB&rlI z2oM2A7hezXk*WvVk)SQla*&Wrj-_AHp+n*V#VbPhYQvI;uWDnu!&yaMd~YJ(oZO=O zgQquIB>h#LxT?Xrcr%j@&r%&(FNvo#)rk>pvT=nmgR+e8+RzkJTB^ zbP7O3Z&AsF)~FdC+Z1iVIz)byPtR>fgPaSdVV%ikJ1Eoqd93!@F22^5#@4PG%)$ajr_69vc)IWG&XOaGO%_o@v zf*R{PhJ7{)E=@Xb)(|zjq)h;nNs!_dn9}^k#A~(4%n94eOP{H{`Mc8e|43KhQJf^H zmA`H9z()7c35nw29EjxIVHfbSiCTxv>;kMf5@k$zMCd z9kY(NVB)o!{sDC}XV7e$B-Ytgdi}>lmdnS!@V9HPqEX14f$H04&eSUF0{l@tY*pTr zNMcMu@e?)(SPNR13CIy?i=jhjbCj80@FK1e+W}}z@)a}7;%HSuV#roqFpXcCEKUDi z<@`UDI^wNk+J(RwKn^5Vs}`}_8A3(oW$*cYq%?sVLvv7cq^w@5K0T!;9wEF1qO4Gx zEKdQbX3NIZ17-l9P6sHl*30W0c?cn~v@;pzdZ{ z?iox=CJ6=z)4rf0D>%Z;->n?84!l@z6)c1pKAup&pH}aW7c8@a?RY-XG}@XN-K^X} zs5Mj$CkoF@!`F=(Ces@h!2q^burHXLm)@IL`9V!xyH{QQ5mOzl!&56tyZC3YFIr{7 zo@%vohjiSzqy<^=k7BO3vWL(7v;!8R0u#UzI%7FWbT_De3e7126)Yg5nw zg_)zd6{`)pZDu(ap@wQYccSaS&e^^bx7AH&RXgkm`zuYk&C*c)9ul9XYa^e|PknF8 zdq?`d)urRtfyW_g-0VWp%$b4^yRwcYDx=O?PnDApr9 z(_at=Sl*}JysMo~jyo42vS~%_+P?j?b^Jg_Nx-6Si2DU7lA2M%S}K1y^z3hj z*&Yfl`T-Sj%OePgIEVxnj9@q@epvCrSeSUrH}{R;enfHo@@$=N+0Mn3)2F_(lC7eSezI<1 zO)a4#tjkc?3%o#$>sW#@%AQO@mI}hFU)!zata!;F0Xa~R*zzJAtciPXRuZjwydE+p zr7)O3Bkoq!w_(M{gZuvL@R_e4fA@GP=N4yi4TrB2+5;?F41W>-89&VJiSi4-9(wFY z!^QJwBsDQ*cwLB&pr(BBk!9w+W^Hy5Qw!Ejlnv~}+7;mNZXtJ4wupiIeeh%T@h@;? zC{{fLi&oY8KUA~Co`)B|zIO6piJED`8`cayn){Qa5Z4{r*`Ag>{}bOgwlg!o{epl7 zBSQQkd1UDbX_a3Umuz;t`_T?!dfZU?x34;5%XBw<%7NI z^Cts31M-MDfSiiwb#ax2t`nN)?GR+4>+VMY0yyjT$ARpzB3ZD2%!=FFp{KtxbF)-? zO}l-txf%uH5-KLDPUyCfA{+JON_-MO49)~yu$q}vq}jJ-xf8bj#WwZtd)56Btux@e zM*DSMx$SpE@0C4*(xQh-JF;XR!Y#u^GMxr|^1ZWEn%bxHk*>TF?KvV0H$H?0@owr1 z*P8dUOg|iv*@=rLn1OVl&Y2lo;b3Udxe5$W{3JhoQoa4e0_nZHmhfaDP zGVZ3*%!?*D^ML0Da|xC!S#Z=$=%+b!aS!;eOB^?{%4bOb>q%$an?u zgrk8IW5Ur&#tW7d*EzroN!L~`kiYT7t73@FSwk%DW=t^2#cCSSY}x=`L2rhBTvqO& zy*KFB-B~fNey-Dmc*qfFb!TJ3-R3Jvr!mg|%o4{uNQw)*BAjR9His~hD5{|2{zYJc zRM2JQKDwaivTDz3h`H^G`x=F+S&p36cx?|Z9FPbF^kw)t#xj%NACYfX)I39+Nkdu0 znc3A-wodAAR*~UM^8C?wQ>;IjAuJI=Of&(vCqfFZ5me@7k{Q}9qjBWgByCDiTt3bRPW8A%l0L@)CUK`xzQ9Y`$nROY!P znYuXK9?gO>oMec>rX)m8`fjt})&ML#8?NvY7the{aLp1~ZhjG$$vmK)lRY zbg%51+__e7Dm#0;2Qoof#T}ioz|6&Q9Z+#IKAiQoWq4YcpLiimHXU1JTrsPpT^C-~ zx{~i}tV6#m;yVQ_>JnwcR*Ekg;zH>Sl)eVz3S4dJgH9@y+Ey&?aTn%Dgf7gkgKhAw zfaPKA!8=?1gwOXZ-HST_k=fg7<^JbnK#*muOJerMQkFaoUaw6xE5c3zFLJ5_r7eBK z)@1A~?QvpvJDdNB*2<)^iv{Q~VG(+cgtFM7ED;4@IjY2N01F+a@Ip{q6l{!5JVj>t zD)9z5&N9*x(B;HkX8KqGoz z0vvuPR`CbSeD|^T&SjGddYC0hT2iYQsb6)fU$FE(I`Q&$1RjEg1z3kS*48Y|kj4OB zt|!V*Uu0nGpX_Pr_Ym=CiQdjmTq*ATyf0hO{avC|XWn-O83%9FyaLZmu25a5!-OE= z?M%osThA=3q9u-pZt#2rFZ{i>;2nj&@bm_Y{0v7%|G$0I2rTVuVnB-7j@4FO+=*ln zn>Fl+s;q_Ak)$BrjtSYq+aa}4EdUF{zpJ8CR*YCr>i~GIA86hr`k`YiH@?D)EiT!R zXls1m{2y5~h&~L&4T*rSDWBK9Sy}QK(Qtx6p(B#nl~{+(B2IlTPc;yiI6rw)h%V!6 zV&fx)h0o&^XS_&$Xn54qWFmO2alqY#iL7JndR#H=ScQ*TGLY$i^dPa}r7MbXIjkOs8$QyQBHQ)k$RhUC zgGG2$MjKVcY-*bHzVJX+gaH=P*|jFEEMk#lpmveV87Q40#JUWIRcdjoO%jK*ODo7+A{>SV%pf z`SMl$mHt@-IFl>}Oyfe0ij)60n=$GsZBV=7422r%Q$J`JDR>DC4-8Z$;jnZKfwu@1 z7@N4H$TISmKBfVzuW^i<6|%g3+Xcq;^q98aEk-cC@iU4P*6jPgMSH=7L`IJt(MZW2 zN~ZqOE4AwOUsaZ1ycbybMNv#S?H1rzR6e(JeJ>t>`)Bk52kia0l)tP_zbIbxecV`K z&G=V=uM<-hG89}aD?ZZ+JNQ-q-i2wegd>Exc@e+40hQyH&tNMvrN435s;_AkqR*(Hw-S|Phbwnim)4IN+k7T$4qa&)035-U8H~aGLGh^%L*Y`kcD3JKL z!iJKqvMs!*g;amEMDjPV4i}<8IQ)c!q#^(o1cg2j(tH-8-DaKLRrP9BeOGHB{K^jz zTRUgYzoq+@le7`-m{gMLEb1R#8sq2ewLb(Pa?Rw}gbkd=9ysTl9rT{j$)L*Ayi0b{ zi0qTlyrJbY)N-p!fE3cdNM4kwTgG(4uj`BtJekxZtDMj=g1HG=O`{!a@MweWF zlvA}nHH(6EM&)3benU5=eNY5j-Czu%p<`!o_EIf9Vg4i(QuPpIX!tGfzJgzZWlHka$aM7T zI1Zf9jRp9M5iVek8Hh*4GD(=j=53{N83ri9I5HF1`#q7SlB&=B9m9x?lRVWC zVL--yEO~VgY|wqllF1=IRF?;*X@9&*E zRV9mwcWDATq}JZK-zGDc}^k->h6?KZ3LNrwE*cJ+sS>aVx!rdh7V5+TwRIKe!`DeY|dqtV0w z;X1*ENIWRE6}|HIDkNrpC@uCb*@GHSVA!x?#GX6e3?HBjFk@M-npzl~y)Wn)4kL=U z7yQ*Q?0CN!ZDtGeWXmqi#6m+2r7)wm?^3nP>en;s@BUbQ^jQ-io<)hmn}l3OaNGnIeaY8P6FRUafLmydAN|j&|n_m%&$i3_My=h|L~{kw_mBdw>5D= zV#P9WsKbg&fXiOU76Dvg0v0&9Wpgcnzb@IK#S0m_Iy?}((BabylmfZQ-(ZOvv z@O0Tg-u>UGPybTA@}{=zxWV3x=Le$8jvCG)!c1r&E{g+w!h$phv4hUQuzG2*E=@@G z$isZnUzs~#cZ@cW<=>E`UO&LGn3veAEO(_g#2lM5#4Ae>7kC-Qc-~EXk~B^-BvV$I zgV~P(I4s(+L}bl$oD{;6;*Vq$YyiBG#oOGM2O$6#FC%2!R~8o~vM!-1p-Ntw{SkQKxw z5W^l_Ktp%7_K_i#%`O10C^w_{nIW-a3mAcvctin?ZljiXV&Hv}N&%sf*f6?g??)%P zaW_5Cf(9te4OvroL4`iu*kTk(k)Rl4X_}xmgUP7IGp;Pv#NI>qSZr?h&XslO5i6jq zcCgrit{fcD0muHwSnn`q+#q>`X>2Dle1U2wPB0=n3sIP>vY7x1_LkgBgql4G3^<;@PdoP zN80}qCM-hJqE;;t9|0_sji7dg(UMZACye+ z!uhbEUP|VpEYjrlQ5|EHG5;_NUWF?g{>Fk=LCx}qnZc8j%RfF{LYdD{y0N$oj$~sV zA?43Nc~eqNO=t;4;aH9<2w#+Q@;6{j$PtE)11}J<%UnClvB8CP zIA90GX2%8lG1#r?i*b8c1wjeQ#U$>x)!NS3f3ii=Xz)R{!Qb4D1MRpj&8Tjyu{8l)D-nTMens3*qtEs{X&1V zzwB0Dp3h`s^2khM8Y3nar1X%41Fe~`PQ*qa1OQ9K>4CcgHVDT~#wglD_yd7U-U9ZR zE3X5_%P!NxA$gp63+rR*f*tZvlr+9wkeM8Pjqnu<7Hc^J1%`m)B&eZEMW4i zgdO1?NptwO^aeJcB;qcR-IekDw^Mip(c95dT5}&UQE?hG4)7eX-L@RiUZ+sy@ z%$B5ZJT^~&n&glS>U`lXoB$$)aYDAnTYO^`ix)SGR_}W%_cg>Z^NnLcxO(pH$O9~3 zB#zG}=MWL=g-LCawT%`guJ9F`UM4ZXgvQ~GVhZuMAjp#NnlL+kCG;oPSF&Xyf;jBu z&Q(k9n;{BFhB3dkUuz2_NF#}4lLU*4dqQNN4aWe{Zl067N%sL@vXB+Q7-f+-f89pv z=c00WzG&$ZTwSszVCf4}SiFk9jWNr5QWzRBL>HI;xTXH^ZvEF_0SIj+)nYfpE|V7-|NbxCY(^mrU$A z{&NTlcK6O({k=)9Xp~;FTh}ez&ZX3+<`A2jc4 z++Xzn{ayOSnXYXJvc~$0>;BG>GoOLJo)~yy_nzH{j~wRMzGM4i%bWXH`l}W14O&xX zp9!Rd&W7l5bv6J()?f{R&ZfRbN^P@A4UqA8U%|yKUem?u51r~$IS>6cap5TwQasAA zWZc-K*;^l^R-XhV{ZQAm(ISlq$l2uhS(J+ zKlX20fp@WJR1%Pcl)wlIV%1wc=eb#fCO+07vdx9N*N5PO+s!P3gT9VpY|6$3tg9k+ zFMCc#;A45?Ws@`Cw#czPl*k>ZwOH6ET<;)ccNz>=lZe;BLk9(>+jrhOb^4Uh*M*DU z0WYqDV+RWb;tI(YHI${M7-@JA)gZyCla28xVY!o@nZ@1XwR*v_a-?F`&2f-hxsKpCQz7D?I%`C z2wozv%*+^J9T}AH159kSK>NdvOZ#=<^?b@#*KEC8_I;`>)-&{^eJH5+~ytcWDR3 z z-(?((nwoewOT7?Y`vQJNWY$0b?q9zC*-t|{VYDJ{xc|pL`j>zG{l!bKMZdLIaP%Rq z@QM$eHsY9fBpIMuLCrJc!;Zd(jA~+^cxWf2Seq{0YI0*N0K68=F+j2T_PhcI-T)Gi zTBj-dn%G?0*iRuY78Xe^J?kKx0&{!+k7hpm;&b$Q=d$M%hWUffK1Ix--g~|_mn>NI z#1&Gl3B6|W)yU=&fcT4qf(Jrk8FTqE zyaTE)U?tgHQi*sDSzZ(=Lz{+>O6cmV*TiO&J+{*9p5f(#cE~j%E06Vtgvhlj`(&v$VY){Tzo&n`ed=kg`!Ulp zCc9>Ay?$G7r~158ebuCB@8hfplMNwR&F3pGo_rBF?##TuvTtSd`)9_U5$g;GNc3B| zV!;Y+7f;@BwR5gA@vfRbEIsybu@py)kR|a5P<={2q|O?w%ff z8dZ=UAh4jOm(RV-b&lr_#4ccq1B*&z18^jTc4AviSjLKs0?ag0xbbD>b#Ws{5c=3Y z$QtA$6hR~|BymE}kc90!&rwQ zHGq*U++*=8d}DKnEaTlJt+z zkaCe>N7j>9EC&#ik|c+K;(gGqhg>_-nIJ2kg^+#F#J!8Tj?2Yv`u)Q$^{o+V$CutdfabeQ(Z zqyZe_|F^gR3JM#n4CtX3{N&i_Xa$ZR%-3YTYbCWAYtgPAGN`rYif6s;1vo87ic^KO zUQr7%zA_hVF=AfHb}_RM7n7*&KCqN1@PsfjH;W6lA$lZ%-~NT^K_-%x%sqvIlA(K= zm0Q#r4w+49OY;~Zf`81yyO8)n(B5!^&} zTJv4o7x?C!2x@`wfmxS#RYGr#zvmG@5(N;L%s9+~c#_PLw-hx4A5`*w0y&2Sx2^nu z8t%c6HfU=SAGkl~$KLcvo-kF3`%D;6Jo|-Oj0{Y-QD6*BHN%%!Zu>|Wzq>hCh~4C|K~}}2nblnEFk+9t6+)=`9Vsua30Fy$CQIH zN4F<9<8K2Ne89c>pXdG&aKS1FDVMC$RtHo`cL6MTdk${kf0M+k?5{PnMU5R%c(Cp9 z?6}_K3XzQ_%w9kl_s&XeXJNl&pCUXMLRm$C1ybZN+g}AuBrApPDuFFjqjW{6wSfQv z_OEk)X@!?fI9M$3(v{|BWrb{c+FH*;Pw^sb3nrUhvYB(+V1F;@Cpl7~68VG(2V zvfRe5lft};M`}4Kd<3!~C^>My8+$Obt&#e6-WzydhS3+i^WL80A_xi%!kS>D?yk`; zB?==2M1~zogb70(JP4E=mL!2jt}w6guEU>!M*M+N8z1vH2Hh8dp!N>bH|s`ACyf)0 zf~5zM0y`YQQ(^OD4EN(#V@@wDO}YJmjqtv0uDo_DOgKlNAlL9Vu=Wacm?Xl%T=?>y zvqvl9wN*ML3!1!WOHib7VhFogOoXkB*?uULxQ@q?#AcIi+m-Of#ec<=W{CLvunJ@d z$pGThW14FC>9?27#=I!x9F~Gm`Q(boL@+|DiSE6e^DUqzAt=}&s}!ArYw$QM&Ze3R z(}S|Oj^FG-EYfj$(>#6Xcs0B75Y9+tAA7>8^Fxx_`i}Pn|q*XIt~BlSJ*Tl~r|W*tKidcR%y< z?EXW$4*0Ko`0Hx?ryKvv%m4rDo~Fj0@n@WWCGH;cKXTxndpdRMw9e~)`*u0`N%33H zH?CJyn%R2ncCYuv;=0sVviCGu(CdrF%ljN{xVGP^_$@i->J{}bb^5QrJ?DJFr~OVP zuI%$w%EI0UQ)lh;|f|doxi_Hqtz!G*DEYx?5+Nj8|0s9)_D2R^cFLUJ9Nli z@8?;o*L-qvM^Rzv^E00>_H$p5YtvF^@1g&^Pmud#c~6JzPV2LVcKs}ULid6eGqa1E z&hNE9d2#QpHeZGW!*dBF=?!OWNe8QX%qFY}afPHM2}Ol7PTmZUUXbFxWd?s54~X}I=O zpdMibk76p^tW}|)FQ9< z)s*Yn4(zh2_1JFPTTbt>6MTS^#8rKdCFJ!xUB96J1;LTJt#8n^rp0|Ox8Ifh?ZARg z*C%bvy!qePN!?bIG5gX z+UN8!IU(;VU#aZVjev)INSDnWx_7dj z*B#pT-q5_sf-frQh)F*d9m>iW9SDo<+78^*vgvF4Mb-e1smY5DwQtwA5)DgyUpgY54PSubx2wf{O7eto9g0mQ{F!4^qu{@FYVBt(6glY&1a!wc5QsTdi4n~^w!&N9kjb9 ztm7gFHA`A@IIK3kw1XUq>;VRlS*H(exf2|~JLZpRx_{BQo=jrzi88T$^wt|8SU}*dVdz|U_1^JDPXX4tRwb9NO=)&m!8C#(Vvqz@xdE;+Q z4)FbuO~C;e*fJyjoc^u-{-%xf(-OX>&Bf!B5Az%_GWoA*MaV5dbR@51*Re~dJos3v zN!<$@Po8q3?v%yf-8X09&$XA%`T73OMqbhJCBMO5;}w0rg4Th{%;8G!V6 z%{>l=azFa;M0U16TY%n{)9;K{6L-)LbOgKWhWE?df{Xz#vBF8=%z7n)2jmcFg5Y4% zL#+zI0Wu3T%I+DzhvV3BL?1Wh5M%7T^c#Hq=PP?`xq=>Nb9J&RKBRVn&Z* z_^4Cc@D5Y&H@+QxX`3~q5{7bea`HtV152@@L(s&=^|zb$MEWFs#-8@lh~~TD6)I++ zHP8&`4>SU7ajo3{G%6^+D3J$(4^E!d~!A6$W-2Fvo#IJNI|ZdBiX#UtD0-hQgbTfd-F z{n>bwJ~rs06|#;YU)cE^^!vj4jV~DAu;^~s#L?~C+Hco(z(#l&7(&l?yI#)6uh@JR z3}p=SZ!3q+Y@3l#`e=t$cl)&b*G=RfY4^{xMF)ouM0{5f8y)@wt9cyuxL^yyp9hc9 zbu;J>`kU8hqT5HXUs&SiGm|!veZWuhyv4rk$V2*MZ5F$3&z2uw1-JNJq}@Nu7N4a# z=H+@Q`Y8UvSiV1)z($SkMNEpw%53qGV8bR3AxIyH72#W=-+RG-+x`PL)nB#!JQ!;7 z(t!VmuLNK8&qX`{OPE;Xoq>IU?`P3FizK2NuCZ~b_;?J580 zb&xm#6))^VcZgMice%CWcHWGyNLc?h81gy~GKP=YCKyUsy8i1HPt7cDn=`;Ro(das z@e6Sm(XrrJBENf$H*tH1ntYz|jm*(VEEhUU>$J&5(Ee!cI#%zE-yYs%;H0F^@d4Mt z3p5Ab1P$`TpRC%qIu@a+(4aLZt@qc-Fo?OEmkysKx@;|o3mJ^KFo;Ox}RX?}jg5XHqrmop~ zdDv&G?vBb|daL<+tG-TpZOP&IQM)h2cRO@7z4K&Sd#Cg*7F&Fh#2Bh}Gv+C_GcUS_ zTc5xPzA9*XL^fD+GFE(wzJL#t=9Jq3!B80Q;r5>Dd6_3cWs(j(ve!dv(#B6Mg8n4W zdH2i43;ua*#M*a%7_n)^oet~P-w<5YUU>26T5sIATX)45R}z-wolbq`l|Aix+s7)Y z{fuTGI%DF-zzTRV{fY)=z>VmyY@zc(p99SizZJ4^TJx87dyy-HJ`dX;@w4(i;3yWf z)Tw{Sb|(EXVk^RYSA1I72$7vT_3OJ4ogaKbf9{)H`cvG}ecuSC;#Y1x4=r=*XEf*V zJB#jtofV9z-pJiju{DY($8`3t+e+!xI?Dt4ehdc1x#Z9CnYnLfS%UM0R3lSdnL$CT}S=5aVZ zha41W&&o-OU+LG09;@nKt;S9&1Vh*-J9G;#o>pjz$(M{+1-&m;zsvQPQev^3um-Ib z`v>F5d+D(aR_%vzjClag;k{wS9oqE^+n^aAZRn1P^*%3+yZ8F-#JF8$_~}xU-~BRd ze+#rn;=G8t(EDX4Yb7pN`4t#yJtCZ3u?p-M`l}yX2l6Q2h3`WfdjI)t`pPR}y9!J2 zLxjout)3~zz_cl^8S-+Q!QNxRd8tx#cP{ht`pj` zd}3ouKdYUthaMLeeu830-Vgl+{P3OhT*2z}mD4|X6@9}FDE$q4i`*}`!M6*YQTavK z&y)7tXpds`*~eN& zmgnkQ(FKU%(a%Nu`&XVEi9w2`%}Vbp@nFb3cC?4_2G{T~^ zCx(u1&OfrSpL_Ld;SHvZsGLtk=48ZDJ=n0@ z_5C$2TF!gf5|1fkNj!^}d%Rr3w;*4p)<5UnZq#&Z88pbtePLX~c#;p|6eEQ!O!)z6UYgf~=`E})JR@u$!p^6Av$>OQs+`iMNnad;IrXn0q%>E7dz)HabP z4eXq||ImP|>Z?$5Rg4o$C(qcy_qm5T4SuRa?qU4M&Ex%;A9mwO{xW?`Z#jJ@KKyzg7M6gY^ikt{$Ie4% z7$fFa-F**SYP7oV3AbD(yMF1%i3^wbOl0MRwK=C4`>^yK#z^e*j2ZcExLhR{b}7{Vj*$VV8?45n%YlnG8Mj1iKB*#ea@X*^J>aY}br4 z^`xR{8+k@_48{s9=)A~F`(TP3CuqLJ=FuMiDa7SBCP^ce`ueek|o6{l{-=ca8X_6KCfh2RjYlGvXe7>g&`vk@{h#-!OzYI<>#V zB|#&xbBcY3IV{f%>ZgQ;NUj_7g19>MxzX&?Hg;Q;F7Yh#w4HDy&qT&<)bG7>^&VY$ zBjLT#XLT709!Rbje&tyC+Fp31`7ZDSACrEmTd^J18+6==<@mgm7{)dOew$CN-lOir zuZX)e>8&w8pv7VFD|rrmw9{e5FQ(cPkzAspQtGwnZ9<>W-M|fFV9sG_afk6!ca^!dBj=He z1@F+&Sn*z-C-niG;-Ij{F>b_dNgwUD=u*P7z>eK@RdF2LB40><_(teEs_af22Kdo^ zOIH1Z9!dUKP5IChwh{I@iLYUc z4ktB_M8AO+tM{q<(0|d{z!18HdOq5H>M%+Fz&tVY=vw#B{rYC3lwD=eNvCJvix6yM zt6gVX^_)QGLj_2!_Tw8GOZKIyZ*{YIvtomYij6S00 zh;5R(C&)%3L+drZm^b*N(OH-~LWBL(qO$9Y)p6_((8yPpPrTXcUz@KI-<+7f-K;x| z9Bp+E$I#71cf|e>i+m;h*%7*J_|*;B$4gEY{NLoMhWx1WQ@#s!Vd3E_f6$*>6MiEH zsdZ3h4jOi*Nqj+>_$TpoFkgh`f*a;Ee%i3{%k~Ft_1hR@a4nOl*Zta*zH@k)s($IR~8)-i_W<6X}lhRo#kggpRo7*`$j@ z`n`WAb;9Bw6V~)M?TQuj#^6=hfBfj4>T~?;lS={5%FbK+{nEGkU0X9L<6=hREmz>L zdOOfYeCET-f&_a%fe^5b|!=b;PgL^66Q-(LGi^-s|e<4y*3; zN`LRXT*nqHoAxP#E}{!M)lgIK3u_;F2bu^C^4q55&L9^clY$-eo0`tEcu(xE}{Mcpo{QvXBl*zwroYmlh{vJP} z`3_3{l4;ke;`}Az2c>S4*ZL#sn3(+5z^f5z93juaN2h#QpJ zQse{bVwon&X3;T{&w?Sy|09AhqdcF$B`R}H-sNq(HH1UH1QYIr(=A`HBs{f zm?Q9L;*h|T*!cuY_(_mY#2)GN4xA%)r|!A~m+#9zd=(orbrh`bLB~nxoOh-E)(1`B zTiS}A$8w)ZG=0SM!71jiuVIVCZ!S23=V3c`qRIHQq;3oO$96R|(2*0`h|DkeoK^os z=5dPSVJz!^F!mz(3vsW%bj|L)k%92pLyMq&v8o9zb1K=W*%y@dFc!=!`YL>v_Y%H> z9&9yUUXQ`6#J(N3yMI~2x_+ni9BQv^MSGpt=Bc0Hw=H5T~zrA8NAH7W5J-vwI=GMf6#X!p(7!t%8=z1DiPdM4vS zAJIir+HB^`8*&JAC@3Gp7Af{Tcw*S`Syu1kbWCD-t^5W~_sKcFA!DWIZqJkR#FmS# zAq<%)QZGIFwZxH|g(lnCn$_AL_z3KHHt$Ldv6&-XPPb|T&5>^)+sHa{_;~!){N{eq zkJOwBYCt156aQ|N^M`Lm^b!1Sq6hk|w~9SV;x74SLDyHoRw(vVx7bV>GrO(KCopYy z4aWsT%prUO_^r{aiI-tah)Xx^HpY3bLH|Z>3OgUbsgGXI{b~y;xS-mC-0sH)B>5n! zZIRl%;K$0&Oq){o1U=pST`qGt#kAS=g+7R18<|LaXLi?H9haDRc(}e^jMeo{$B03P z9$UqC>-QnMNF1Dr5y6VGMb-f~Rz3v1z3Tieb)=kZL3;nhr;M(lo=bUk;X&}zeCls& z2~@;27_y)6??`+^QK?g0sM@~1k4z+e@hcNWY(3OmAtruIRQ1*+zaPEStDOqo1rI|O zB+dYzJ+cjc1n7_xZ_~%2I)BR=>|Sj_#HBIc`CjCosC_5r5B%tLp75#2+QDjmf@udg z>@8{=LH4n^h)hImu~RMz?PIr;9ON+Skx1SszMdfc|2^M>?&{SR1kaEdOma%q_r~UI z%05P|67%XPnD4OFXm8~AjE%ww}gm7hNF zT;>vXPGVI3-1|qlR$`-_Y(ek}vB4lC>bkSk>S?&B@>&PrMRK&%yac;?W6_K$_7|gX zCxt$;ML!fAso249>m{bytv@1zNluB|^?$_k;`hP!YWIGkZ^7fOYC#Ya2K~`%9!T9d zy}p21o7~`Cd`G)y20ad5z>SKd`H!Z3nU=iD^iPC^9rz@)2VEkpc$c8>T;2Ccevg$b zDgI<+3_II~)cV$I#iMJXV-S<4zN6SL(c#tOVeW$?_}I4TjV?~>GwkBh#k1F z1R8)oja|>LUo%J_)O)0UCAGt)#+_H}(2mH?YMaDOnRYUZoL)1hJVyLW`oJ^b$>@3T ztOvUH+@{wuk+>!+o-FOCTdouA*zt1p`mpzr*~E7#`m5a*Z27g#M$=yzYvdv7!!S?X z=#D%O{3I;?w36)=`v&+S&qJ=0Z7k$xX`3zYATjW)U#7~+=#k6~v0?L`{1bD*dn4DV zctUp|4uG0)5>Enlkk{2`#(Lk3jjUMTvfu)K1CB9InDfviVs6og`p3eQ1AD=Gu&$>EAX_*nY{++@($Mga1@*A3q`d3%{v)T=wxDFsFj}|D_GK5m_g)W<6sa z%QYd@=T^nO4FfzB$U8D7*>(BD?n>b5iSFHZ+@=m<83$GD5 z*w6SlwGHhN-ybvySv$y>VJ}4v6#kAM8+kI~52IF_;TJdh@6;Fd9Qet6xbm9irv1mr zU55tQ#g0qeaPaCR6Vfm01EITOW1xQxYM;5udS&cGFTs`Cr?B_Qqs2aojh%Hl@E1#7 zE$?slPb_cZTdR%{lL?Q<*Mq;%t$$LJKWHATUHg1jbKK3Ee39B%Jj?6&!LO(b1a^=U zbvqj0l5b*Vi?-_%W5@i{&r1yibb0+8zj+t28!*?XkxwiM@(cgaZ?k@!=&eS-=o|Mm zYrOm@_e7H?YSkw>#=5^vpMPyX-<~=}cKDzs1U0Lz{w0se>R#}N&H ze$aoBK^fDOgilX7*^8hr&>7)Z)TFV}L&X;DN7iS2tm5TG26D=w14H7&~ zV`0@6u|ML&a9fKCI~bUSN69~Y3BHAXWz~Kd$KWN+pMGH%_D}Vj!kbuc+{}Rtxc-k_ z|CnpYi>&hjZltb_JU@P}5eNL>@$1R0D#tU}wHNJi<{@J*@)kHsOIdW}=|MgAVOQPr zVq6)u60o1T!qXp(?9usWV_tkV>+(9^XkB7 ze)#yw)+PTm*7+Hc^V@Z6^=F2SA2t3^_rvSYu8QA$Cv(mlG*jj~^&Qe4pIlUxn6Z1; zc3t{xi0^*zO5Jhif2gr`Z=h5j+O~#Fkm&CS^pJJ7p!aOzQ{qpr0 z8GB?nucd1bpM6=T-le}faJvm z%>|dX?6%~8sPc`_n`mjh-Sc8`oR|x~3wAxH_L(EH#xUQ2e}3z}0NNlPQ{uJ34fY$o zeu2}o^mFhpumoMA&bmp9jD5Q`LiGF9-}D>&tH#2L8H&rzTd^7ANUgtP6 z5E!C=;WVXlSFHxgMJUyYY{uZnBnTS9}p%0cuC%m{|qI@Jrn zPJ@h&4l8wH7!UqqCF2-5=|^i_82DqI6Axa8-#Y!1qYYmsZjRU$Xl%4&FLDqu7goBM zRr_k5F!{og7mI#u%7^7^TQhF>;;^TBl{>7S7uGT4SK%e-KVI!}U`TiwxvJE@!JdH* zfxgW;Pr}ayFKl@h&p}4^YyWV2XX=!ayH@+ugWvt-#-O`(PCj^pK2np18Z5-*vX4y* z->}pMQ}KnZg7d^41m(~4Q*<%xcy9gXysTG@-^$9C!*^-&;u{Clm;z*1<|XyxygWm$ zVeFgE{QG|9HN3!!{Xp)u+VaiuQ=8w}z&ZGCF=<9Iyv6DpLpPWg&8N)RRd?H)-~7*! z_kX(gs|~;0pI>-c#fpg+!!LxN0r?QQCsuO?JC&?UguNVk;)Oqm_AD8+T*p}s9FI(saG^t|lm&*lw zD`*pRo`3u%D&4BR?bLU5KEucR@d@lsT&sRx?EcWEpg6*JK+Ftswa$aUDKS^{3EBxx zsM(tI&claftcjhDhW2|IJM|i~W}G4CfT1vIZA;r=iQ0W;JY9KBI^GePiQ2nfbO&$) ze)z|?p~nSD&K`MfUh5D^|I{sW6&mjpHwT6|&-c~!C1@5rNA($jtysyZYTsoaJxAh( zsJ#&On&R>tb&Kq7t|wxAUne%SVDi3nn>ncF`kLMg+Axhrnwe!c`T-xOJVpi ziQPeF7GIWIe2!E5R_BmCkW2VSZm^O=tnP#6KzoEJXrB;%DAO10kF@_cqJNRgiNhdy=mQsdKLchMcf1B$s zmD@9sN2;^$h~&pq6BA8}p8j+0AKfunMnTm22)BA*byIXU0NTR_i<9Ry>#Y#zoK(*`;m z`k7v5EUfmuv}4jDV@}GLqSx5T3SQdd8sNj0p{krd|QM9r(faTb+J5gFX2)Z}%&+rK33%(Km_yLF~ z!&elPeo!k}?0t+W_7%50A?cgCC69%Q4Qny8SaLb7umzsH#@EXlJJ|m8KBK$9U%-c3jdhtvGMB(p5W5T5!zV8CH8vcc z@5g2&_yK?VJJr;XA`C_=g_pI75FXU(8Ntb$Vy?6XX}u23StxksF|IPWN$6 z)^)*m<#ugNI8Xc_au2bDZKikIRpGxi<___lRcW(lJg8kzDNn<&aXRI{OTAu+)eu`T z-yhm4>*0CD0X#?j_Fyrn?+F?PpHyvf%uO(2XFCGlV7?~gr@7&i8dg#-O=_Alcfh{P zTjne>gIil+pGUSfW9toB2|j0MFCYfM^sO0w5d0tTEcmilyx8>{`itL^aWG>!44<~$ zwQk4ZrL03-!PlTk#{7gwF-O4@coE%(>#BO*y1j#bUd0ae(Dd`rT677)5juw5oYC(M z>o>AAb^&;rQ~b8*@=ohi2I&*uQ0PIl7~=WNO|YW-E@g~OtQz)!SmlER83X+ueCyPi zmKgYDPb3|&i+@KRg#HUpz^3iT*RMZ2$nQ$=+lHQJ)rPE-i{Ibsd^E=x1JTcs!^83^ zFccJMsBM`3!*W^<-Nk04o{#mu)Ko#o zw|W*e2H;`PA*=Jz9)k|aT58BIL3R9S`%%^RgAMG0)C*Sgiplx&Q`3}wGiGMKlz|`U zEOWA|crh09`DpnwC9isO`Y7BLsiYkqwTwTKef7uFJ*0SXbbfN z$&rwHUV<049OoL=rt`w9)aTgk!_UOV!Zy|z@`4{(H^r{cVI7w>#E=E8{Lo=NCulp+ z251Q1`x7Gu2RWBqVdNI6ZL8u#-zV;rwO+uMTKhg|f9&o9Gb)B+$;+g+C0o1xhzxCa zKCI*LabzIj;bFDwryXjJqCaE1qkbE_hIlOmyNNo%QcdBAST}{ zex^*FQnY66+EY7<3QP6>g2Ejo?=D(&C?_Y!bq!i%KJo4QjrW3|P@7G16@;XL@t z&UUYRPt5}Hv%C2T;ZN`ywRRG?VI8<=@B+P&nn^)w3=<F2F}Blns7+wfi4`5#zcTebZo+dyZKTl6-W@5HoVcbD2bDs6zKKueHm?EK1ln|^t~ST(0y6I06G+; z4YzyBb56{fxMA7UB5U_~uUSOiu@in)<>nrTro6epTkQyF57)o`hBu$As?$sE4fZ$m zD3NWTH@Xf@{2V+(r!%5Axy8@9eVZ`O(?{ta-zAJTX@fBnx`PZ5RxT8@hw+1EJK22H z_mCJ4^_c8Kd%(hHTeqC=)w@@Pjw|P_w&-TugB)aa-s%`W4UvTgzt;YU$i~?9bbll7 zNUn;iE18%vc(#|?*jCSvMiKU z`Mq@6(j#Eu@AK{L*ZO_kx_8gpR#0$(`@CX~Hqay5?d^H}kuN*mS-Lpo8g@MF#cKQH zHmR|?@P$~d-J?D?+I_wUa~j>xZ(G+_@Wn`T)qF3wQEl9-M{}EH+f0D2U%yq2dOv6M`*u0`#QW` zJrA!ESs1y->pQA#RM$RsN3-vSy~vB)4xKUMDh-TC3>lb#Mial`B_7=GyUO_bk=4u^ zKZfr@UpJR$Bkx?fcJ zCQmMs>mMKYxMLk0o+a49|De~r!M+&x!Nkk8R?WRzD|gPFhVP6xRTX2YkAdIc_%)#? z@D3*Uoxj)-JIVVXKzo zc3TxYR%^18o155ZduiOnWjE_?c=U=nHx2$zyaKd5EZ?hL|Ll$^ZdU$`&Cz7=Y}2H zmbI#p8<^9o-YVaOxL9mPoQ>=B{`>ije1U9=Jq39L`3t&0+>(`CBK=Uey(6br!&*XyV7t!?`L%_zGLW5Zr^r(eg1|sYy~&$!@u-<_1}UWWM#XxKg0%#%>=zt+CbI>D_}-q zs?~2N`<&yOBaf0FEB|1S90vKXz=m0%96Rfn5swCbF0AU$N>_ z7{@ZwpV(pAxs*CB5gb)sUp?rvupvl(AiUG7ZJeA_(Ydhw1bsgCAmV+z+6VEU!AcFQ!l~MTq`air0njty2Twhh#@bga0rAj&J<@!JVacoLnYeYfc%-9v9 z{;Rs)cSNUko}+4isojmQt14?Cf*s)g~`ci^(Q zMv_rOJV-l!?tx#aaXZA7l6U9ShPggOc|0lO;B@VO&UIQ>6=NXSLEZsFnL|cwiFLh0 zXpGbnh3+gGmwZT%_tM{;c)dtGF?rVB*3Z=2_|NZfF{NWC*0|AWj@LQ?#KRDO46lZt zLyxNq3#>oFdNr(PgkM?xr%ohsn#hpot*i$SWId7UdN)7MWqkwe%0hQyi5+l5zAky0 z&>OEbhxb9Blvo~g1V6ffpYd?I77Vcdk@#{LGe7^-4qy!ub?ul~uA%7kF43N2ELd|z z)}UqW-dJJB3O8WLNjI1GgXUl}kK~6$>RWk~}`wwP_fub%gu`JLT^&gun z$Dv8ALj&GqojohOagJ+fA9`l4%VrVd5Z1dy+YamPFc0Kis0S4b`f7(8Xb|U|-UHmA z8wkw-Kllr)i)X=;7%zM|)L#oSUW_~SN1QGz9IP*>K0rvud%Qceldrr38h{W#yH!;Q7$ru08x*0;f?#7gg<8_|&mqRTs^Xac2A&GpE=mxi-wLi7TO329Gd#p`jbA zG)mtWUI@1M=Fly8D|7sYlo*Waq&Iq>O*zrPPb}&_>d*4>8{SC_D0W`z z>3|ckEx8Tyt;5=~UL-PInDmW2VDf`iT0_nrwm>}(0$B#U5Q}V?OK#W#$>k-_vnJY- znZtYwwqCw(bzTF_f`))C)=x6!_<4&DlXnFU(6#xmL|2S;kL7rUyk+3UX+7O&-%<2$ zXbn7zI$Ua-_{efd-__9e@V)XK)BE>}pXu9lr@A{-qEhpI%aRGmb)PY8!Jxj`&D5srmJw!BKp z3#wC{hZ)s065)7cIMP29ABx0;cx)g%I-*p_)-igw^@v^h{mIj8{w% zp4@D)nl4sgltfl6O5!*qL%HC$AKzCyZoW$xQ33>5NjSjt!-RoI0J2FH9H4&gYVrR+&m#x_YiUv8<{C zbCaosbX*dJtZuJ~^_8WlsY>+~B|5p1D$WaIt7|jMr9wJu^qsNChoyylL!PQsCzr-d zJvA23OxCOJtSTf|iaj+&8#5RBVyWS&39VpNRZS4%3+~yeT6{&ApTI+kX>Dw7dDboH zk`xY|8XY;cVc=66ej8<2_%X}_c<_x+$2K6jysR2d%5-wXiKJvl?hS4Dt<`P4A<5Mo z*CGjnxQ-=jy`j8Y(o`iw8gu3{F%pKWX?_IX(}HO#u1*Yx13|lLr&POU+N8{R5#y)v z#Cf5_KMb9nu1%~gapW@WXwo6N&G;Cmt&QE=41ETJ?u=?Xc#vRl$85ufrIGdh|IDuQ zlBsD#aUc}!$T%^Gr798F^t`OO1mLVoeHSjQFP(KP)u{A_bXzekO)WJWLx{ld=~gHW z4$A#X|3Gv&7AL~c@WtN$6a3s2D_T z%cS97#Z+Zkj)#f%PT>&!IuTaJ z$7&^`;Fk1xVKP;4vr@cY6cY)onCv|;DjJsS0LbkRRYarQ3ovnNQ%B!0bUvyBkUbU9 z^VU^}714wHa|5ok6|RrN935QI|-TcL@ zw+*xg8w?(87J14kZ3UnO@J0B7e+kHDX+D4;Xku#XgD~J<2C})}5HKv7pDs8I1O5n* z%>^M~{D}PDPKCudP=c5!PuF}Wn$J*#UYqm;c2CZlk;@n=j6 zSV_~uk8%2>z{aQwLRM9r>Oh>Y%66XKwSr}`L@bMxLCmu(hCaO-;hPPhndyZF-_OZ~ zhQ**j>$4aGXwprCu;^PVLsz!SwtGzr*MsQDJ3%_|G0LS&_rDh29{;2J@K?vW+L#;l z#tsh=3zhdQG%vs3xvk?)iF@;}wcsbdzi$M7S_>vF-}-Sdu=AH|A0L|f?(p@GZg<{% zu~{x9YfdiF@sO^zyB5`YOV8 b@vW=Yz4z`O99a=Rd%cTeu72?QC?fm=v3zjG literal 0 HcmV?d00001 diff --git a/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h new file mode 100644 index 000000000..852c20974 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrb.h @@ -0,0 +1,30 @@ +// To recreate the data below, use the Paint.Net plugin "Arduino Progmem NeoPixel FileType" +// to save as/export the included Cylon.pdn +// Paint.Net - http://www.getpaint.net/download.html#download +// Plugin - http://forums.getpaint.net/index.php?/topic/107921-arduino-neopixel-sketch-exporter/ +// This uses Flatten, GRB, Hexadecimal +// + +const uint16_t myImageWidth = 16; +const uint16_t myImageHeight = 20; +const uint8_t PROGMEM myImage[] = { // (16 x 20) GRB in Hexadecimal + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h new file mode 100644 index 000000000..9314f2fb5 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/CylonGrbw.h @@ -0,0 +1,30 @@ +// To recreate the data below, use the Paint.Net plugin "Arduino Progmem NeoPixel FileType" +// to save as/export the included Cylon.pdn +// Paint.Net - http://www.getpaint.net/download.html#download +// Plugin - http://forums.getpaint.net/index.php?/topic/107921-arduino-neopixel-sketch-exporter/ +// This uses Flatten, GRBW, Hexadecimal +// + +const uint16_t myImageWidth = 16; +const uint16_t myImageHeight = 20; +const uint8_t PROGMEM myImage[] = { // (16 x 20) GRBW in Hexadecimal + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino new file mode 100644 index 000000000..34b97f2a6 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferCylon/NeoPixelBufferCylon.ino @@ -0,0 +1,74 @@ +// NeoPixelBufferCylon +// This example will move a Cylon Red Eye back and forth across the +// the full collection of pixels on the strip. +// +// This will demonstrate the use of the NeoVerticalSpriteSheet +// + +#include +#include + +// The actual image is contained in the data structure in one of the Cylon*.h files +// You will need to use the one that has the same color feature as your NeoPixelBus +// There are two provided, but you can create your own easily enough using +// free versions of Paint.Net and the plugin +#include "CylonGrb.h" +typedef NeoGrbFeature MyPixelColorFeature; + +// #include "CylonGrbw.h" +// typedef NeoGrbwFeature MyPixelColorFeature; + +const uint16_t PixelCount = 16; // the sample images are meant for 16 pixels +const uint16_t PixelPin = 2; +const uint16_t AnimCount = 1; // we only need one + +NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); +NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object + +// sprite sheet stored in progmem using the same pixel feature as the NeoPixelBus +NeoVerticalSpriteSheet> spriteSheet( + myImageWidth, // image width and sprite width since its vertical sprite sheet + myImageHeight, // image height + 1, // sprite is only one pixel high + myImage); + +uint16_t indexSprite; + +void LoopAnimUpdate(const AnimationParam& param) +{ + // wait for this animation to complete, + // we are using it as a timer of sorts + if (param.state == AnimationState_Completed) + { + // done, time to restart this position tracking animation/timer + animations.RestartAnimation(param.index); + + // draw the next frame in the sprite + spriteSheet.Blt(strip, 0, indexSprite); + indexSprite = (indexSprite + 1) % myImageHeight; // increment and wrap + } +} + +void setup() +{ + strip.Begin(); + strip.Show(); + + indexSprite = 0; + + // we use the index 0 animation to time how often we rotate all the pixels + animations.StartAnimation(0, 60, LoopAnimUpdate); +} + + +void loop() +{ + // this is all that is needed to keep it running + // and avoiding using delay() is always a good thing for + // any timing related routines + animations.UpdateAnimations(); + strip.Show(); +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino new file mode 100644 index 000000000..37a109f46 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelBufferShader/NeoPixelBufferShader.ino @@ -0,0 +1,167 @@ +// NeoPixelBufferShader +// This example will provide a shader class to the NeoPixelBuffer that will dim and brighten +// the pixels that are in the buffer (a device dependent bitmap) +// + +#include + +const uint16_t PixelCount = 64; // set this to the size of your strip +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +// three element GRB pixels, change to your needs +NeoPixelBus strip(PixelCount, PixelPin); + +// the buffer object, +// defined to use memory with the same feature as the strip +// initialized with the same number of pixels as our strip +NeoBuffer> image(8,8,NULL); + +const RgbColor BrightRed(255, 0, 0); +const RgbColor BrightGreen(0, 255, 0); +const RgbColor BrightBlue(0, 0, 255); + +const RgbColor BrightYellow(255, 255, 0); +const RgbColor BrightCyan(0, 255, 255); +const RgbColor BrightPurple(255, 0, 255); + +const RgbColor DarkRed(32, 0, 0); +const RgbColor DarkGreen(0, 32, 0); +const RgbColor DarkBlue(0, 0, 32); + +const RgbColor DarkYellow(32, 32, 0); +const RgbColor DarkCyan(0, 32, 32); +const RgbColor DarkPurple(32, 0, 32); + +const RgbColor White(255); +const RgbColor Black(0); + +// define a custom shader object that provides brightness support +// based upon the NeoBitsBase +template class BrightnessShader : public NeoBitsBase +{ +public: + BrightnessShader(): + NeoBitsBase(), + _brightness(255) // default to full bright + {} + + // required for a shader object, it will be called for + // every pixel + void Apply(uint16_t index, uint8_t* pDest, uint8_t* pSrc) + { + // we don't care what the index is so we ignore it + // + // to apply our brightness shader, + // use the source color, modify, and apply to the destination + + // for every byte in the pixel, + // scale the source value by the brightness and + // store it in the destination byte + const uint8_t* pSrcEnd = pSrc + T_COLOR_FEATURE::PixelSize; + while (pSrc != pSrcEnd) + { + *pDest++ = (*pSrc++ * (uint16_t(_brightness) + 1)) >> 8; + } + } + + // provide an accessor to set brightness + void setBrightness(uint8_t brightness) + { + _brightness = brightness; + Dirty(); // must call dirty when a property changes + } + + // provide an accessor to get brightness + uint8_t getBrightness() + { + return _brightness; + } + +private: + uint8_t _brightness; +}; + +// create an instance of our shader object with the same feature as our buffer +BrightnessShader shader; + +// some dimming tracking variables and settings +int8_t delta; + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + Serial.flush(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.Show(); + + // dibs do not default to any color, + // so clear it to black if you aren't going to draw + // into every pixel + image.ClearTo(Black); + + // draw a pattern into the image + uint8_t x = 0; + uint8_t y = 0; + image.SetPixelColor(x++, y, DarkRed); + image.SetPixelColor(x++, y, DarkYellow); + image.SetPixelColor(x++, y, DarkGreen); + image.SetPixelColor(x++, y, DarkCyan); + image.SetPixelColor(x++, y, DarkBlue); + image.SetPixelColor(x++, y, DarkPurple); + + x = 0; + y = 1; + image.SetPixelColor(x++, y, BrightRed); + image.SetPixelColor(x++, y, BrightYellow); + image.SetPixelColor(x++, y, BrightGreen); + image.SetPixelColor(x++, y, BrightCyan); + image.SetPixelColor(x++, y, BrightBlue); + image.SetPixelColor(x++, y, BrightPurple); + + Serial.println(); + Serial.println("Running..."); + + delta = -1; // start by dimming downward +} + +void loop() +{ + // we increment by delta every 30ms + delay(30); + + // update the brightness in shader + // + uint8_t brightness = shader.getBrightness(); + // check if we flip directions + if (brightness == 0) + { + delta = 1; // increment + } + else if (brightness == 255) + { + delta = -1; // decrement + } + // modify and apply + brightness += delta; + shader.setBrightness(brightness); + + Serial.println(brightness); + + + // render the image using the shader and then call Show() + // these two should be called together in order + // + + // need to provide the type of color feature for the strip and + // the type of our custom shader + image.Render>(strip, shader); + strip.Show(); + +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino new file mode 100644 index 000000000..c421b5b1b --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/bitmaps/NeoPixelDibTest/NeoPixelDibTest.ino @@ -0,0 +1,158 @@ +// NeoPixelDibTest +// This example will provide a shader class to the NeoPixelDib that will dim and brighten +// the pixels that are in the Dib (Device Independant Bitmap) +// + +#include + +const uint16_t PixelCount = 64; // set this to the size of your strip +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +// three element GRB pixels, change to your needs +NeoPixelBus strip(PixelCount, PixelPin); + +// the DIB object, using RgbColor and initialized with the same number of pixels as our strip +NeoDib image(PixelCount); + +const RgbColor BrightRed(255, 0, 0); +const RgbColor BrightGreen(0, 255, 0); +const RgbColor BrightBlue(0, 0, 255); + +const RgbColor BrightYellow(255, 255, 0); +const RgbColor BrightCyan(0, 255, 255); +const RgbColor BrightPurple(255, 0, 255); + +const RgbColor DarkRed(32, 0, 0); +const RgbColor DarkGreen(0, 32, 0); +const RgbColor DarkBlue(0, 0, 32); + +const RgbColor DarkYellow(32, 32, 0); +const RgbColor DarkCyan(0, 32, 32); +const RgbColor DarkPurple(32, 0, 32); + +const RgbColor White(255); +const RgbColor Black(0); + +// define a custom shader object that provides brightness support +// based upon the NeoBitsBase +class BrightnessShader : public NeoBitsBase +{ +public: + BrightnessShader(): + NeoBitsBase(), + _brightness(255) // default to full bright + {} + + // required for a shader object, it will be called for + // every pixel + RgbColor Apply(uint16_t index, RgbColor original) + { + // we don't care what the index is so we ignore it + // + // to apply our brightness shader, modify the original color and return the color we want + // blend from black (_brightness == 0.0) to the original color (_brightness == 1.0) + + return RgbColor::LinearBlend(Black, original, (float)_brightness / 255.0f); + } + + // provide an accessor to set brightness + void setBrightness(uint8_t brightness) + { + _brightness = brightness; + Dirty(); // must call dirty when a property changes + } + + // provide an accessor to get brightness + uint8_t getBrightness() + { + return _brightness; + } + +private: + uint8_t _brightness; +}; + +// create an instance of our shader object +BrightnessShader shader; + +// some dimming tracking variables and settings +int8_t delta; + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + Serial.flush(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.Show(); + + // dibs do not default to any color, + // so clear it to black if you aren't going to draw + // into every pixel + image.ClearTo(Black); + + // draw a pattern into the image + uint8_t index = 0; + image.SetPixelColor(index++, DarkRed); + image.SetPixelColor(index++, DarkYellow); + image.SetPixelColor(index++, DarkGreen); + image.SetPixelColor(index++, DarkCyan); + image.SetPixelColor(index++, DarkBlue); + image.SetPixelColor(index++, DarkPurple); + + image.SetPixelColor(index++, Black); + image.SetPixelColor(index++, Black); + + image.SetPixelColor(index++, BrightRed); + image.SetPixelColor(index++, BrightYellow); + image.SetPixelColor(index++, BrightGreen); + image.SetPixelColor(index++, BrightCyan); + image.SetPixelColor(index++, BrightBlue); + image.SetPixelColor(index++, BrightPurple); + + Serial.println(); + Serial.println("Running..."); + + delta = -1; // start by dimming downward +} + +void loop() +{ + // we increment by delta every 30ms + delay(30); + + // update the brightness in shader + // + uint8_t brightness = shader.getBrightness(); + // check if we flip directions + if (brightness == 0) + { + delta = 1; // increment + } + else if (brightness == 255) + { + delta = -1; // decrement + } + // modify and apply + brightness += delta; + shader.setBrightness(brightness); + + Serial.println(brightness); + + + // render the image using the shader and then call Show() + // these two should be called together in order + // + + // need to provide the type of color feature for the strip and + // the type of our custom shader + image.Render(strip, shader); + strip.Show(); + +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino new file mode 100644 index 000000000..6b70b6f42 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicDump/NeoPixelMosaicDump.ino @@ -0,0 +1,98 @@ +//---------------------------------------------------------------------- +// NeoPixelMosaicDump +// This will dump to the serial output a grid map of the defined mosaic +// The output is displayed as row column labeled grid with the NeoPixelBus +// index of the pixel at the intersection of the row and column. +// +// To help with physical layout, there maybe included a symbol following the index +// < means the index is the input index for the panel, the first on the panel +// > means the index is the output index for the panel, the last on the panel +// +// This is useful in visualising the mosaic layout of your panels to +// confirm you have them correctly wired together for this mosaic pattern +// +// It does not require that you have the actual panel connected +//---------------------------------------------------------------------- + +#include +#include + +// uncomment one of these that matches your panel pixel layouts +// rotation is ignored for mosaic as it applies a rotation for you +// that is specific to the location of the panel within the mosaic +// to reduce connection lengths + +typedef ColumnMajorAlternatingLayout MyPanelLayout; +// typedef ColumnMajorLayout MyPanelLayout; +// typedef RowMajorAlternatingLayout MyPanelLayout; +// typedef RowMajorLayout MyPanelLayout; + +// make sure to set these panel and tile layout to match your sizes +const uint8_t PanelWidth = 8; // a 8 pixel x 8 pixel matrix of leds on the panel +const uint8_t PanelHeight = 8; +const uint8_t TileWidth = 4; // laid out in 4 panels x 2 panels mosaic +const uint8_t TileHeight = 2; + +NeoMosaic mosaic( + PanelWidth, + PanelHeight, + TileWidth, + TileHeight); + +void DumpMosaic() +{ + Serial.println(); + + Serial.print("\t\t"); + for (int x = 0; x < mosaic.getWidth(); x++) + { + Serial.print(x); + Serial.print("\t"); + } + Serial.println(); + + Serial.print("\t---"); + for (int x = 0; x < mosaic.getWidth(); x++) + { + Serial.print("--------"); + } + Serial.println(); + + for (int y = 0; y < mosaic.getHeight(); y++) + { + Serial.print(" "); + Serial.print(y); + Serial.print("\t|\t"); + + for (int x = 0; x < mosaic.getWidth(); x++) + { + NeoTopologyHint hint = mosaic.TopologyHint(x, y); + + Serial.print(mosaic.Map(x, y)); + if (hint == NeoTopologyHint_FirstOnPanel) + { + Serial.print("<"); + } + else if (hint == NeoTopologyHint_LastOnPanel) + { + Serial.print(">"); + } + Serial.print("\t"); + } + Serial.println(); + } +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + DumpMosaic(); +} + +void loop() +{ + +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino new file mode 100644 index 000000000..2f6500c9f --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelMosaicTest/NeoPixelMosaicTest.ino @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------- +// NeoPixelTopologyTest +// This will display specific colors in specific locations on the led panels +// +// This is useful in confirming the layout of your panels +// +// It does require that you have the actual panels connected +//---------------------------------------------------------------------- + +#include +#include + +// uncomment one of these that matches your panel pixel layouts +// rotation is ignored for mosaic as it applies a rotation for you +// that is specific to the location of the panel within the mosaic +// to reduce connection lengths + +typedef ColumnMajorAlternatingLayout MyPanelLayout; +// typedef ColumnMajorLayout MyPanelLayout; +// typedef RowMajorAlternatingLayout MyPanelLayout; +// typedef RowMajorLayout MyPanelLayout; + +// make sure to set these panel values to the sizes of yours +const uint8_t PanelWidth = 8; // 8 pixel x 8 pixel matrix of leds +const uint8_t PanelHeight = 8; +const uint8_t TileWidth = 4; // laid out in 4 panels x 2 panels mosaic +const uint8_t TileHeight = 2; + +const uint16_t PixelCount = PanelWidth * PanelHeight * TileWidth * TileHeight; +const uint8_t PixelPin = 2; + +NeoMosaic mosaic( + PanelWidth, + PanelHeight, + TileWidth, + TileHeight); + +NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); + +RgbColor red(128, 0, 0); +RgbColor green(0, 128, 0); +RgbColor blue(0, 0, 128); +RgbColor white(128); +// if using NeoRgbwFeature above, use this white instead to use +// the correct white element of the LED +//RgbwColor white(128); +RgbColor black(0); + +const uint16_t left = 0; +const uint16_t right = PanelWidth - 1; +const uint16_t top = 0; +const uint16_t bottom = PanelHeight - 1; + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + + strip.Begin(); + strip.Show(); + + Serial.println(); + Serial.println("Running..."); +} + +void loop() +{ + delay(2500); + + Serial.println(); + Serial.println("If your panel is correctly defined, you should see ..."); + Serial.println("Upper left is white."); + Serial.println("Upper right is Red."); + Serial.println("Lower right is Green"); + Serial.println("Lower Left is Blue"); + + // use the topo to map the 2d cordinate to the pixel + // and use that to SetPixelColor + strip.SetPixelColor(mosaic.Map(left, top), white); + strip.SetPixelColor(mosaic.Map(right, top), red); + strip.SetPixelColor(mosaic.Map(right, bottom), green); + strip.SetPixelColor(mosaic.Map(left, bottom), blue); + strip.Show(); + + delay(5000); + + Serial.println(); + Serial.println("Cleared to black ..."); + strip.ClearTo(black); + strip.Show(); +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino new file mode 100644 index 000000000..64a1bcdde --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino @@ -0,0 +1,100 @@ +//---------------------------------------------------------------------- +// NeoPixelRingTopologyTest +// This will display specific colors in specific locations on the led rings +// +// This is useful in confirming the layout of your rings +// +// It does require that you have the actual series of rings connected +//---------------------------------------------------------------------- + +#include + +const uint8_t PixelCount = 119; +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +// define the layout of your series of rings +// +// This example is using all of Adafruits rings and a Jewel in the center. +// The center is the input and all the rings are connected in series going outward +// +// Rings: +// 0 - 1 (virtual ring, the center of the jewel) +// 1 - 6 (virtual ring, the outer ring of the jewel) +// 2 - 12 count ring +// 3 - 16 count ring +// 4 - 24 count ring +// 5 - 60 count ring comprised of four arc segments +// +// The values below in Rings[] are the index of the first pixel in each ring. +// An extra value is appended for a virtual ring start that also +// represents the total count of pixels in the complete series and this extra +// value is required. +// +class MyRingsLayout +{ +protected: + const uint16_t Rings[7] = {0, 1, 7, 19, 35, 59, PixelCount}; +}; + +// use the MyRingsLayout to declare the topo object +// +NeoRingTopology topo; + +// declare our strip +// +NeoPixelBus strip(PixelCount, PixelPin); + +// define some handy colors +// +RgbColor red(128, 0, 0); +RgbColor green(0, 128, 0); +RgbColor blue(0, 0, 128); +RgbColor black(0); + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + + strip.Begin(); + strip.Show(); + + Serial.println(); + Serial.println("Running..."); +} + +void loop() +{ + delay(2500); + + Serial.println(); + Serial.println("If your panel is correctly defined, you should see ..."); + Serial.println("First pixel in each ring is Red."); + Serial.println("Middle pixel in each ring is Green."); + Serial.println("Last Pixel in each ring is Blue."); + + + // use the topo to map the 2d polar cordinate to the pixel + // and use that to SetPixelColor + for (uint16_t ring = 0; ring < topo.getCountOfRings(); ring++) + { + // first pixel in each ring is red + strip.SetPixelColor(topo.Map(ring, 0), red); + // last pixel in each ring is blue + strip.SetPixelColor(topo.Map(ring, topo.getPixelCountAtRing(ring) - 1), blue); + // middle pixel in each ring is green + strip.SetPixelColor(topo.Map(ring, topo.getPixelCountAtRing(ring) / 2), green); + } + strip.Show(); + + delay(5000); + + Serial.println(); + Serial.println("Cleared to black ..."); + strip.ClearTo(black); + strip.Show(); +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino new file mode 100644 index 000000000..2849c5619 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesDump/NeoPixelTilesDump.ino @@ -0,0 +1,102 @@ +//---------------------------------------------------------------------- +// NeoPixelTileDump +// This will dump to the serial output a grid map of the defined tiles +// The output is displayed as row column labeled grid with the NeoPixelBus +// index of the pixel at the intersection of the row and column +// +// To help with physical layout, there maybe included a symbol following the index +// < means the index is the input index for the panel, the first on the panel +// > means the index is the output index for the panel, the last on the panel +// +// This is useful in visualising the tile layout of your panels to +// confirm you have them correctly wired together for the defined pattern +// +// It does not require that you have the actual panel connected +//---------------------------------------------------------------------- + +#include +#include + +// uncomment one of these that matches your panel pixel layouts and +// how you want them rotated. Not all the rotations are listed here +// but you can modifiy the name to include the rotation of 90,180, or 270. + +typedef ColumnMajorAlternatingLayout MyPanelLayout; +// typedef ColumnMajorLayout MyPanelLayout; +// typedef RowMajorAlternatingLayout MyPanelLayout; +// typedef RowMajorLayout MyPanelLayout; +// typedef RowMajor90Layout MyPanelLayout; // note rotation 90 was used + +// change this to be one of the layouts which will define the layout +// of the panels themselves +typedef ColumnMajorLayout MyTilesLayout; + +// make sure to set these panel and tile layout to match your sizes +const uint8_t PanelWidth = 8; // 8 pixel x 8 pixel matrix of leds +const uint8_t PanelHeight = 8; +const uint8_t TileWidth = 4; // laid out in 4 panels x 2 panels mosaic +const uint8_t TileHeight = 2; + +NeoTiles tiles( + PanelWidth, + PanelHeight, + TileWidth, + TileHeight); + +void DumpTopo() +{ + Serial.println(); + + Serial.print("\t\t"); + for (int x = 0; x < tiles.getWidth(); x++) + { + Serial.print(x); + Serial.print("\t"); + } + Serial.println(); + + Serial.print("\t---"); + for (int x = 0; x < tiles.getWidth(); x++) + { + Serial.print("--------"); + } + Serial.println(); + + for (int y = 0; y < tiles.getHeight(); y++) + { + Serial.print(" "); + Serial.print(y); + Serial.print("\t|\t"); + + for (int x = 0; x < tiles.getWidth(); x++) + { + NeoTopologyHint hint = tiles.TopologyHint(x, y); + + Serial.print(tiles.Map(x, y)); + if (hint == NeoTopologyHint_FirstOnPanel) + { + Serial.print("<"); + } + else if (hint == NeoTopologyHint_LastOnPanel) + { + Serial.print(">"); + } + Serial.print("\t"); + } + Serial.println(); + } +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + DumpTopo(); +} + +void loop() +{ + +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino new file mode 100644 index 000000000..1dfc64516 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTilesTest/NeoPixelTilesTest.ino @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------- +// NeoPixelTilesTest +// This will display specific colors in specific locations on the led panels +// +// This is useful in confirming the layout of your panels +// +// It does require that you have the actual panels connected +//---------------------------------------------------------------------- + +#include +#include + +// uncomment one of these that matches your panel pixel layouts and +// how you want them rotated. Not all the rotations are listed here +// but you can modifiy the name to include the rotation of 90,180, or 270. + +typedef ColumnMajorAlternatingLayout MyPanelLayout; +// typedef ColumnMajorLayout MyPanelLayout; +// typedef RowMajorAlternatingLayout MyPanelLayout; +// typedef RowMajorLayout MyPanelLayout; +// typedef RowMajor90Layout MyPanelLayout; // note rotation 90 was used + +// change this to be one of the layouts which will define the layout +// of the panels themselves +typedef ColumnMajorLayout MyTilesLayout; + +// make sure to set these panel values to the sizes of yours +const uint8_t PanelWidth = 8; // 8 pixel x 8 pixel matrix of leds +const uint8_t PanelHeight = 8; +const uint8_t TileWidth = 4; // laid out in 4 panels x 2 panels mosaic +const uint8_t TileHeight = 2; + +const uint16_t PixelCount = PanelWidth * PanelHeight * TileWidth * TileHeight; +const uint8_t PixelPin = 2; + +NeoTiles tiles( + PanelWidth, + PanelHeight, + TileWidth, + TileHeight); + +NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); + +RgbColor red(128, 0, 0); +RgbColor green(0, 128, 0); +RgbColor blue(0, 0, 128); +RgbColor white(128); +// if using NeoRgbwFeature above, use this white instead to use +// the correct white element of the LED +//RgbwColor white(128); +RgbColor black(0); + +const uint16_t left = 0; +const uint16_t right = PanelWidth - 1; +const uint16_t top = 0; +const uint16_t bottom = PanelHeight - 1; + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + + strip.Begin(); + strip.Show(); + + Serial.println(); + Serial.println("Running..."); +} + +void loop() +{ + delay(2500); + + Serial.println(); + Serial.println("If your panel is correctly defined, you should see ..."); + Serial.println("Upper left is white."); + Serial.println("Upper right is Red."); + Serial.println("Lower right is Green"); + Serial.println("Lower Left is Blue"); + + // use the topo to map the 2d cordinate to the pixel + // and use that to SetPixelColor + strip.SetPixelColor(tiles.Map(left, top), white); + strip.SetPixelColor(tiles.Map(right, top), red); + strip.SetPixelColor(tiles.Map(right, bottom), green); + strip.SetPixelColor(tiles.Map(left, bottom), blue); + strip.Show(); + + delay(5000); + + Serial.println(); + Serial.println("Cleared to black ..."); + strip.ClearTo(black); + strip.Show(); +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino new file mode 100644 index 000000000..aa78a2539 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyDump/NeoPixelTopologyDump.ino @@ -0,0 +1,78 @@ +//---------------------------------------------------------------------- +// NeoPixelTopologyDump +// This will dump to the serial output a grid map of the defined topology +// The output is displayed as row column labeled grid with the NeoPixelBus +// index of the pixel at the intersection of the row and column +// +// This is useful in visualising the layout of your panel so you can +// confirm you have the correct pattern +// +// It does not require that you have the actual panel connected +//---------------------------------------------------------------------- + +#include +#include + +// uncomment one of these that matches your panel pixel layouts and +// how you want them rotated. Not all the rotations are listed here +// but you can modifiy the name to include the rotation of 90,180, or 270. + +typedef ColumnMajorAlternatingLayout MyPanelLayout; +// typedef ColumnMajorLayout MyPanelLayout; +// typedef RowMajorAlternatingLayout MyPanelLayout; +// typedef RowMajorLayout MyPanelLayout; +// typedef RowMajor90Layout MyPanelLayout; // note rotation 90 was used + +// make sure to set these panel values to the sizes of yours +const uint8_t PanelWidth = 8; // 8 pixel x 8 pixel matrix of leds +const uint8_t PanelHeight = 8; + +NeoTopology topo(PanelWidth, PanelHeight); + +void DumpTopo() +{ + Serial.println(); + + Serial.print("\t\t"); + for (int x = 0; x < topo.getWidth(); x++) + { + Serial.print(x); + Serial.print("\t"); + } + Serial.println(); + + Serial.print("\t--"); + for (int x = 0; x < topo.getWidth(); x++) + { + Serial.print("--------"); + } + Serial.println(); + + for (int y = 0; y < topo.getHeight(); y++) + { + Serial.print(" "); + Serial.print(y); + Serial.print("\t|\t"); + + for (int x = 0; x < topo.getWidth(); x++) + { + Serial.print(topo.Map(x, y)); + Serial.print("\t"); + } + Serial.println(); + } +} + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + DumpTopo(); +} + +void loop() +{ + +} + diff --git a/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino new file mode 100644 index 000000000..2071abb34 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/examples/topologies/NeoPixelTopologyTest/NeoPixelTopologyTest.ino @@ -0,0 +1,92 @@ +//---------------------------------------------------------------------- +// NeoPixelTopologyTest +// This will display specific colors in specific locations on the led panel +// +// This is useful in confirming the layout of your panel +// +// It does require that you have the actual panel connected +//---------------------------------------------------------------------- + +#include +#include + +// uncomment one of these that matches your panel pixel layouts and +// how you want them rotated. Not all the rotations are listed here +// but you can modifiy the name to include the rotation of 90,180, or 270. + +typedef ColumnMajorAlternatingLayout MyPanelLayout; +// typedef ColumnMajorLayout MyPanelLayout; +// typedef RowMajorAlternatingLayout MyPanelLayout; +// typedef RowMajorLayout MyPanelLayout; +// typedef RowMajor90Layout MyPanelLayout; // note rotation 90 was used + +// make sure to set these panel values to the sizes of yours +const uint8_t PanelWidth = 8; // 8 pixel x 8 pixel matrix of leds +const uint8_t PanelHeight = 8; +const uint16_t PixelCount = PanelWidth * PanelHeight; +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +NeoTopology topo(PanelWidth, PanelHeight); + +NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); +//NeoPixelBus strip(PixelCount, PixelPin); +// for esp8266 omit the pin +//NeoPixelBus strip(PixelCount); + +RgbColor red(128, 0, 0); +RgbColor green(0, 128, 0); +RgbColor blue(0, 0, 128); +RgbColor white(128); +// if using NeoRgbwFeature above, use this white instead to use +// the correct white element of the LED +//RgbwColor white(128); +RgbColor black(0); + +const uint16_t left = 0; +const uint16_t right = PanelWidth - 1; +const uint16_t top = 0; +const uint16_t bottom = PanelHeight - 1; + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + + strip.Begin(); + strip.Show(); + + Serial.println(); + Serial.println("Running..."); +} + +void loop() +{ + delay(2500); + + Serial.println(); + Serial.println("If your panel is correctly defined, you should see ..."); + Serial.println("Upper left is white."); + Serial.println("Upper right is Red."); + Serial.println("Lower right is Green"); + Serial.println("Lower Left is Blue"); + + // use the topo to map the 2d cordinate to the pixel + // and use that to SetPixelColor + strip.SetPixelColor(topo.Map(left, top), white); + strip.SetPixelColor(topo.Map(right, top), red); + strip.SetPixelColor(topo.Map(right, bottom), green); + strip.SetPixelColor(topo.Map(left, bottom), blue); + strip.Show(); + + delay(5000); + + Serial.println(); + Serial.println("Cleared to black ..."); + strip.ClearTo(black); + strip.Show(); +} + diff --git a/lib/NeoPixelBus-2.2.9/keywords.txt b/lib/NeoPixelBus-2.2.9/keywords.txt new file mode 100644 index 000000000..75771ef97 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/keywords.txt @@ -0,0 +1,184 @@ +####################################### +# Syntax Coloring Map NeoPixelBus +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +NeoPixelBus KEYWORD1 +RgbwColor KEYWORD1 +RgbColor KEYWORD1 +HslColor KEYWORD1 +HsbColor KEYWORD1 +HtmlColor KEYWORD1 +NeoGrbFeature KEYWORD1 +NeoGrbwFeature KEYWORD1 +NeoRgbwFeature KEYWORD1 +NeoRgbFeature KEYWORD1 +NeoBrgFeature KEYWORD1 +NeoRbgFeature KEYWORD1 +DotStarBgrFeature KEYWORD1 +DotStarLbgrFeature KEYWORD1 +NeoWs2813Method KEYWORD1 +Neo800KbpsMethod KEYWORD1 +Neo400KbpsMethod KEYWORD1 +NeoAvrWs2813Method KEYWORD1 +NeoAvr800KbpsMethod KEYWORD1 +NeoAvr400KbpsMethod KEYWORD1 +NeoEsp8266DmaWs2813Method KEYWORD1 +NeoEsp8266Dma800KbpsMethod KEYWORD1 +NeoEsp8266Dma400KbpsMethod KEYWORD1 +NeoEsp8266UartWs2813Method KEYWORD1 +NeoEsp8266Uart800KbpsMethod KEYWORD1 +NeoEsp8266Uart400KbpsMethod KEYWORD1 +NeoEsp8266AsyncUartWs2813Method KEYWORD1 +NeoEsp8266AsyncUart800KbpsMethod KEYWORD1 +NeoEsp8266AsyncUart400KbpsMethod KEYWORD1 +NeoEsp8266BitBangWs2813Method KEYWORD1 +NeoEsp8266BitBang800KbpsMethod KEYWORD1 +NeoEsp8266BitBang400KbpsMethod KEYWORD1 +NeoEsp32BitBangWs2813Method KEYWORD1 +NeoEsp32BitBang800KbpsMethod KEYWORD1 +NeoEsp32BitBang400KbpsMethod KEYWORD1 +DotStarMethod KEYWORD1 +DotStarSpiMethod KEYWORD1 +NeoPixelAnimator KEYWORD1 +AnimUpdateCallback KEYWORD1 +AnimationParam KEYWORD1 +NeoEase KEYWORD1 +AnimEaseFunction KEYWORD1 +RowMajorLayout KEYWORD1 +RowMajor90Layout KEYWORD1 +RowMajor180Layout KEYWORD1 +RowMajor270Layout KEYWORD1 +RowMajorAlternatingLayout KEYWORD1 +RowMajorAlternating90Layout KEYWORD1 +RowMajorAlternating180Layout KEYWORD1 +RowMajorAlternating270Layout KEYWORD1 +ColumnMajorLayout KEYWORD1 +ColumnMajor90Layout KEYWORD1 +ColumnMajor180Layout KEYWORD1 +ColumnMajor270Layout KEYWORD1 +ColumnMajorAlternatingLayout KEYWORD1 +ColumnMajorAlternating90Layout KEYWORD1 +ColumnMajorAlternating180Layout KEYWORD1 +ColumnMajorAlternating270Layout KEYWORD1 +NeoTopology KEYWORD1 +NeoRingTopology KEYWORD1 +NeoTiles KEYWORD1 +NeoMosaic KEYWORD1 +NeoGammaEquationMethod KEYWORD1 +NeoGammaTableMethod KEYWORD1 +NeoGamma KEYWORD1 +NeoHueBlendShortestDistance KEYWORD1 +NeoHueBlendLongestDistance KEYWORD1 +NeoHueBlendClockwiseDirection KEYWORD1 +NeoHueBlendCounterClockwiseDirection KEYWORD1 +NeoBufferContext KEYWORD1 +LayoutMapCallback KEYWORD1 +NeoBufferMethod KEYWORD1 +NeoBufferProgmemMethod KEYWORD1 +NeoBuffer KEYWORD1 +NeoVerticalSpriteSheet KEYWORD1 +NeoBitmapFile KEYWORD1 +HtmlShortColorNames KEYWORD1 +HtmlColorNames KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +Begin KEYWORD2 +Show KEYWORD2 +CanShow KEYWORD2 +ClearTo KEYWORD2 +RotateLeft KEYWORD2 +ShiftLeft KEYWORD2 +RotateRight KEYWORD2 +ShiftRight KEYWORD2 +IsDirty KEYWORD2 +Dirty KEYWORD2 +ResetDirty KEYWORD2 +Pixels KEYWORD2 +PixelsSize KEYWORD2 +PixelCount KEYWORD2 +SetPixelColor KEYWORD2 +GetPixelColor KEYWORD2 +CalculateBrightness KEYWORD2 +Darken KEYWORD2 +Lighten KEYWORD2 +LinearBlend KEYWORD2 +BilinearBlend KEYWORD2 +IsAnimating KEYWORD2 +NextAvailableAnimation KEYWORD2 +StartAnimation KEYWORD2 +StopAnimation KEYWORD2 +RestartAnimation KEYWORD2 +IsAnimationActive KEYWORD2 +AnimationDuration KEYWORD2 +UpdateAnimations KEYWORD2 +IsPaused KEYWORD2 +Pause KEYWORD2 +Resume KEYWORD2 +getTimeScale KEYWORD2 +setTimeScale KEYWORD2 +QuadraticIn KEYWORD2 +QuadraticOut KEYWORD2 +QuadraticInOut KEYWORD2 +CubicIn KEYWORD2 +CubicOut KEYWORD2 +CubicInOut KEYWORD2 +QuarticIn KEYWORD2 +QuarticOut KEYWORD2 +QuarticInOut KEYWORD2 +QuinticIn KEYWORD2 +QuinticOut KEYWORD2 +QuinticInOut KEYWORD2 +SinusoidalIn KEYWORD2 +SinusoidalOut KEYWORD2 +SinusoidalInOut KEYWORD2 +ExponentialIn KEYWORD2 +ExponentialOut KEYWORD2 +ExponentialInOut KEYWORD2 +CircularIn KEYWORD2 +CircularOut KEYWORD2 +CircularInOut KEYWORD2 +Gamma KEYWORD2 +Map KEYWORD2 +MapProbe KEYWORD2 +getWidth KEYWORD2 +getHeight KEYWORD2 +getCountOfRings KEYWORD2 +getPixelCountAtRing KEYWORD2 +getPixelCount KEYWORD2 +TopologyHint KEYWORD2 +Correct KEYWORD2 +SpriteWidth KEYWORD2 +SpriteHeight KEYWORD2 +SpriteCount KEYWORD2 +Blt KEYWORD2 +Width KEYWORD2 +Height KEYWORD2 +Parse KEYWORD2 +ToString KEYWORD2 +ToNumericalString KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### + +NEO_MILLISECONDS LITERAL1 +NEO_CENTISECONDS LITERAL1 +NEO_DECISECONDS LITERAL1 +NEO_SECONDS LITERAL1 +NEO_DECASECONDS LITERAL1 +AnimationState_Started LITERAL1 +AnimationState_Progress LITERAL1 +AnimationState_Completed LITERAL1 +NeoTopologyHint_FirstOnPanel LITERAL1 +NeoTopologyHint_InPanel LITERAL1 +NeoTopologyHint_LastOnPanel LITERAL1 +NeoTopologyHint_OutOfBounds LITERAL1 +PixelIndex_OutOfBounds LITERAL1 \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/library.json b/lib/NeoPixelBus-2.2.9/library.json new file mode 100644 index 000000000..35e8ea0c2 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/library.json @@ -0,0 +1,15 @@ +{ + "name": "NeoPixelBus", + "keywords": "NeoPixel, WS2811, WS2812, WS2813, SK6812, DotStar, APA102, RGB, RGBW", + "description": "A library that makes controlling NeoPixels (WS2811, WS2812, WS2813 & SK6812) and DotStars (APA102) easy. Supports most Arduino platforms. Support for RGBW pixels. Includes seperate RgbColor, RgbwColor, HslColor, and HsbColor objects. Includes an animator class that helps create asyncronous animations. For Esp8266 it has three methods of sending NeoPixel data, DMA, UART, and Bit Bang; and two methods of sending DotStar data, hardware SPI and software SPI.", + "homepage": "https://github.com/Makuna/NeoPixelBus/wiki", + "repository": + { + "type": "git", + "url": "https://github.com/Makuna/NeoPixelBus" + }, + "version": "2.2.9", + "frameworks": "arduino", + "platforms": "*" +} + diff --git a/lib/NeoPixelBus-2.2.9/library.properties b/lib/NeoPixelBus-2.2.9/library.properties new file mode 100644 index 000000000..029a6db39 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/library.properties @@ -0,0 +1,9 @@ +name=NeoPixelBus by Makuna +version=2.2.9 +author=Michael C. Miller (makuna@live.com) +maintainer=Michael C. Miller (makuna@live.com) +sentence=A library that makes controlling NeoPixels (WS2811, WS2812, WS2813 & SK6812) and DotStars (APA102) easy. +paragraph=Supports most Arduino platforms, including Esp8266 and Esp32. Support for RGBW pixels. Includes seperate RgbColor, RgbwColor, HslColor, and HsbColor objects. Includes an animator class that helps create asyncronous animations. Supports Matrix layout of pixels. Includes Gamma corretion object. For Esp8266 it has three methods of sending NeoPixel data, DMA, UART, and Bit Bang; and two methods of sending DotStar data, hardware SPI and software SPI. +category=Display +url=https://github.com/Makuna/NeoPixelBus/wiki +architectures=* \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/NeoPixelAnimator.h b/lib/NeoPixelBus-2.2.9/src/NeoPixelAnimator.h new file mode 100644 index 000000000..21eb2ad8b --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/NeoPixelAnimator.h @@ -0,0 +1,174 @@ +/*------------------------------------------------------------------------- +NeoPixelAnimator provides animation timing support. + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#include +#include "internal/NeoEase.h" + +enum AnimationState +{ + AnimationState_Started, + AnimationState_Progress, + AnimationState_Completed +}; + +struct AnimationParam +{ + float progress; + uint16_t index; + AnimationState state; +}; + +#ifdef ARDUINO_ARCH_AVR + +typedef void(*AnimUpdateCallback)(const AnimationParam& param); + +#else + +#undef max +#undef min +#include +typedef std::function AnimUpdateCallback; + +#endif + + +#define NEO_MILLISECONDS 1 // ~65 seconds max duration, ms updates +#define NEO_CENTISECONDS 10 // ~10.9 minutes max duration, centisecond updates +#define NEO_DECISECONDS 100 // ~1.8 hours max duration, decisecond updates +#define NEO_SECONDS 1000 // ~18.2 hours max duration, second updates +#define NEO_DECASECONDS 10000 // ~7.5 days, 10 second updates + +class NeoPixelAnimator +{ +public: + NeoPixelAnimator(uint16_t countAnimations, uint16_t timeScale = NEO_MILLISECONDS); + ~NeoPixelAnimator(); + + bool IsAnimating() const + { + return _activeAnimations > 0; + } + + + bool NextAvailableAnimation(uint16_t* indexAvailable, uint16_t indexStart = 0); + + void StartAnimation(uint16_t indexAnimation, uint16_t duration, AnimUpdateCallback animUpdate); + void StopAnimation(uint16_t indexAnimation); + void StopAll(); + + void RestartAnimation(uint16_t indexAnimation) + { + if (indexAnimation >= _countAnimations || _animations[indexAnimation]._duration == 0) + { + return; + } + + StartAnimation(indexAnimation, _animations[indexAnimation]._duration, (_animations[indexAnimation]._fnCallback)); + } + + bool IsAnimationActive(uint16_t indexAnimation) const + { + if (indexAnimation >= _countAnimations) + { + return false; + } + return (IsAnimating() && _animations[indexAnimation]._remaining != 0); + } + + uint16_t AnimationDuration(uint16_t indexAnimation) + { + if (indexAnimation >= _countAnimations) + { + return 0; + } + return _animations[indexAnimation]._duration; + } + + void UpdateAnimations(); + + bool IsPaused() + { + return (!_isRunning); + } + + void Pause() + { + _isRunning = false; + } + + void Resume() + { + _isRunning = true; + _animationLastTick = millis(); + } + + uint16_t getTimeScale() + { + return _timeScale; + } + + void setTimeScale(uint16_t timeScale) + { + _timeScale = (timeScale < 1) ? (1) : (timeScale > 32768) ? 32768 : timeScale; + } + +private: + struct AnimationContext + { + AnimationContext() : + _duration(0), + _remaining(0), + _fnCallback(NULL) + {} + + void StartAnimation(uint16_t duration, AnimUpdateCallback animUpdate) + { + _duration = duration; + _remaining = duration; + _fnCallback = animUpdate; + + } + + void StopAnimation() + { + _remaining = 0; + } + + uint16_t _duration; + uint16_t _remaining; + + AnimUpdateCallback _fnCallback; + }; + + uint16_t _countAnimations; + AnimationContext* _animations; + uint32_t _animationLastTick; + uint16_t _activeAnimations; + uint16_t _timeScale; + bool _isRunning; +}; diff --git a/lib/NeoPixelBus-2.2.9/src/NeoPixelBrightnessBus.h b/lib/NeoPixelBus-2.2.9/src/NeoPixelBrightnessBus.h new file mode 100644 index 000000000..0ff1d5221 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/NeoPixelBrightnessBus.h @@ -0,0 +1,161 @@ +/*------------------------------------------------------------------------- +NeoPixelBus library wrapper template class that provides overall brightness control + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#include "NeoPixelBus.h" + +template class NeoPixelBrightnessBus : + public NeoPixelBus +{ +private: + void ConvertColor(typename T_COLOR_FEATURE::ColorObject* color) + { + if (_brightness) + { + uint8_t* ptr = (uint8_t*) color; + uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize; + + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value * _brightness) >> 8; + } + } + } + + void RecoverColor(typename T_COLOR_FEATURE::ColorObject* color) const + { + if (_brightness) + { + uint8_t* ptr = (uint8_t*) color; + uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize; + + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value << 8) / _brightness; + } + } + } + +public: + NeoPixelBrightnessBus(uint16_t countPixels, uint8_t pin) : + NeoPixelBus(countPixels, pin), + _brightness(0) + { + } + + NeoPixelBrightnessBus(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) : + NeoPixelBus(countPixels, pinClock, pinData), + _brightness(0) + { + } + + NeoPixelBrightnessBus(uint16_t countPixels) : + NeoPixelBus(countPixels), + _brightness(0) + { + } + + void SetBrightness(uint8_t brightness) + { + // Due to using fixed point math, we modifiy the brightness + // before storing making the math faster + uint8_t newBrightness = brightness + 1; + + // Only update if there is a change + if (newBrightness != _brightness) + { + // calculate a scale to modify from old brightness to new brightness + // + uint8_t oldBrightness = _brightness - 1; // unmodify brightness value + uint16_t scale; + + if (oldBrightness == 0) + { + scale = 0; // Avoid divide by 0 + } + else if (brightness == 255) + { + scale = 65535 / oldBrightness; + } + else + { + scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; + } + + // re-scale existing pixels + // + uint8_t* ptr = this->Pixels(); + uint8_t* ptrEnd = ptr + this->PixelsSize(); + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value * scale) >> 8; + } + + _brightness = newBrightness; + this->Dirty(); + } + } + + uint8_t GetBrightness() const + { + return _brightness - 1; + } + + void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color) + { + ConvertColor(&color); + NeoPixelBus::SetPixelColor(indexPixel, color); + } + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(uint16_t indexPixel) const + { + typename T_COLOR_FEATURE::ColorObject color = NeoPixelBus::GetPixelColor(indexPixel); + RecoverColor(&color); + return color; + } + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color) + { + ConvertColor(&color); + NeoPixelBus::ClearTo(color); + }; + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color, uint16_t first, uint16_t last) + { + ConvertColor(&color); + NeoPixelBus::ClearTo(color, first, last); + } + + +protected: + uint8_t _brightness; +}; + + diff --git a/lib/NeoPixelBus-2.2.9/src/NeoPixelBus.h b/lib/NeoPixelBus-2.2.9/src/NeoPixelBus.h new file mode 100644 index 000000000..f6a6b7bab --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/NeoPixelBus.h @@ -0,0 +1,400 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +#include + +// some platforms do not define this standard progmem type for some reason +// +#ifndef PGM_VOID_P +#define PGM_VOID_P const void * +#endif + +// '_state' flags for internal state +#define NEO_DIRTY 0x80 // a change was made to pixel data that requires a show + +#include "internal/NeoHueBlend.h" + +#include "internal/RgbColor.h" +#include "internal/HslColor.h" +#include "internal/HsbColor.h" +#include "internal/HtmlColor.h" +#include "internal/RgbwColor.h" + +#include "internal/NeoColorFeatures.h" +#include "internal/DotStarColorFeatures.h" + +#include "internal/Layouts.h" +#include "internal/NeoTopology.h" +#include "internal/NeoRingTopology.h" +#include "internal/NeoTiles.h" +#include "internal/NeoMosaic.h" + +#include "internal/NeoBufferContext.h" +#include "internal/NeoBufferMethods.h" +#include "internal/NeoBuffer.h" +#include "internal/NeoSpriteSheet.h" +#include "internal/NeoBitmapFile.h" +#include "internal/NeoDib.h" +#include "internal/NeoEase.h" +#include "internal/NeoGamma.h" + +#if defined(ARDUINO_ARCH_ESP8266) + +#include "internal/NeoEsp8266DmaMethod.h" +#include "internal/NeoEsp8266UartMethod.h" +#include "internal/NeoEspBitBangMethod.h" +#include "internal/DotStarGenericMethod.h" + +#elif defined(ARDUINO_ARCH_ESP32) + +#include "internal/NeoEspBitBangMethod.h" +#include "internal/DotStarGenericMethod.h" + +#elif defined(__arm__) // must be before ARDUINO_ARCH_AVR due to Teensy incorrectly having it set + +#include "internal/NeoArmMethod.h" +#include "internal/DotStarGenericMethod.h" + +#elif defined(ARDUINO_ARCH_AVR) + +#include "internal/NeoAvrMethod.h" +#include "internal/DotStarAvrMethod.h" + +#else +#error "Platform Currently Not Supported, please add an Issue at Github/Makuna/NeoPixelBus" +#endif + +#if !defined(__AVR_ATtiny85__) +#include "internal/DotStarSpiMethod.h" +#endif + + +template class NeoPixelBus +{ +public: + // Constructor: number of LEDs, pin number + // NOTE: Pin Number maybe ignored due to hardware limitations of the method. + + NeoPixelBus(uint16_t countPixels, uint8_t pin) : + _countPixels(countPixels), + _state(0), + _method(pin, countPixels, T_COLOR_FEATURE::PixelSize) + { + } + + NeoPixelBus(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) : + _countPixels(countPixels), + _state(0), + _method(pinClock, pinData, countPixels, T_COLOR_FEATURE::PixelSize) + { + } + + NeoPixelBus(uint16_t countPixels) : + _countPixels(countPixels), + _state(0), + _method(countPixels, T_COLOR_FEATURE::PixelSize) + { + } + + ~NeoPixelBus() + { + } + + operator NeoBufferContext() + { + Dirty(); // we assume you are playing with bits + return NeoBufferContext(_method.getPixels(), _method.getPixelsSize()); + } + + void Begin() + { + _method.Initialize(); + Dirty(); + } + + void Show() + { + if (!IsDirty()) + { + return; + } + + _method.Update(); + + ResetDirty(); + } + + inline bool CanShow() const + { + return _method.IsReadyToUpdate(); + }; + + bool IsDirty() const + { + return (_state & NEO_DIRTY); + }; + + void Dirty() + { + _state |= NEO_DIRTY; + }; + + void ResetDirty() + { + _state &= ~NEO_DIRTY; + }; + + uint8_t* Pixels() + { + return _method.getPixels(); + }; + + size_t PixelsSize() const + { + return _method.getPixelsSize(); + }; + + size_t PixelSize() const + { + return T_COLOR_FEATURE::PixelSize; + }; + + uint16_t PixelCount() const + { + return _countPixels; + }; + + void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color) + { + if (indexPixel < _countPixels) + { + T_COLOR_FEATURE::applyPixelColor(_method.getPixels(), indexPixel, color); + Dirty(); + } + }; + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(uint16_t indexPixel) const + { + if (indexPixel < _countPixels) + { + return T_COLOR_FEATURE::retrievePixelColor(_method.getPixels(), indexPixel); + } + else + { + // Pixel # is out of bounds, this will get converted to a + // color object type initialized to 0 (black) + return 0; + } + }; + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color) + { + uint8_t temp[T_COLOR_FEATURE::PixelSize]; + uint8_t* pixels = _method.getPixels(); + + T_COLOR_FEATURE::applyPixelColor(temp, 0, color); + + T_COLOR_FEATURE::replicatePixel(pixels, temp, _countPixels); + + Dirty(); + }; + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color, uint16_t first, uint16_t last) + { + if (first < _countPixels && + last < _countPixels && + first <= last) + { + uint8_t temp[T_COLOR_FEATURE::PixelSize]; + uint8_t* pixels = _method.getPixels(); + uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first); + + T_COLOR_FEATURE::applyPixelColor(temp, 0, color); + + T_COLOR_FEATURE::replicatePixel(pFront, temp, last - first + 1); + + Dirty(); + } + } + + void RotateLeft(uint16_t rotationCount) + { + if ((_countPixels - 1) >= rotationCount) + { + _rotateLeft(rotationCount, 0, _countPixels - 1); + } + } + + void RotateLeft(uint16_t rotationCount, uint16_t first, uint16_t last) + { + if (first < _countPixels && + last < _countPixels && + first < last && + (last - first) >= rotationCount) + { + _rotateLeft(rotationCount, first, last); + } + } + + void ShiftLeft(uint16_t shiftCount) + { + if ((_countPixels - 1) >= shiftCount) + { + _shiftLeft(shiftCount, 0, _countPixels - 1); + Dirty(); + } + } + + void ShiftLeft(uint16_t shiftCount, uint16_t first, uint16_t last) + { + if (first < _countPixels && + last < _countPixels && + first < last && + (last - first) >= shiftCount) + { + _shiftLeft(shiftCount, first, last); + Dirty(); + } + } + + void RotateRight(uint16_t rotationCount) + { + if ((_countPixels - 1) >= rotationCount) + { + _rotateRight(rotationCount, 0, _countPixels - 1); + } + } + + void RotateRight(uint16_t rotationCount, uint16_t first, uint16_t last) + { + if (first < _countPixels && + last < _countPixels && + first < last && + (last - first) >= rotationCount) + { + _rotateRight(rotationCount, first, last); + } + } + + void ShiftRight(uint16_t shiftCount) + { + if ((_countPixels - 1) >= shiftCount) + { + _shiftRight(shiftCount, 0, _countPixels - 1); + Dirty(); + } + } + + void ShiftRight(uint16_t shiftCount, uint16_t first, uint16_t last) + { + if (first < _countPixels && + last < _countPixels && + first < last && + (last - first) >= shiftCount) + { + _shiftRight(shiftCount, first, last); + Dirty(); + } + } + + + +protected: + const uint16_t _countPixels; // Number of RGB LEDs in strip + + uint8_t _state; // internal state + T_METHOD _method; + + void _rotateLeft(uint16_t rotationCount, uint16_t first, uint16_t last) + { + // store in temp + uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize]; + uint8_t* pixels = _method.getPixels(); + + uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first); + + T_COLOR_FEATURE::movePixelsInc(temp, pFront, rotationCount); + + // shift data + _shiftLeft(rotationCount, first, last); + + // move temp back + pFront = T_COLOR_FEATURE::getPixelAddress(pixels, last - (rotationCount - 1)); + T_COLOR_FEATURE::movePixelsInc(pFront, temp, rotationCount); + + Dirty(); + } + + void _shiftLeft(uint16_t shiftCount, uint16_t first, uint16_t last) + { + uint16_t front = first + shiftCount; + uint16_t count = last - front + 1; + + uint8_t* pixels = _method.getPixels(); + uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first); + uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, front); + + T_COLOR_FEATURE::movePixelsInc(pFirst, pFront, count); + + // intentional no dirty + } + + void _rotateRight(uint16_t rotationCount, uint16_t first, uint16_t last) + { + // store in temp + uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize]; + uint8_t* pixels = _method.getPixels(); + + uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, last - (rotationCount - 1)); + + T_COLOR_FEATURE::movePixelsDec(temp, pFront, rotationCount); + + // shift data + _shiftRight(rotationCount, first, last); + + // move temp back + pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first); + T_COLOR_FEATURE::movePixelsDec(pFront, temp, rotationCount); + + Dirty(); + } + + void _shiftRight(uint16_t shiftCount, uint16_t first, uint16_t last) + { + uint16_t front = first + shiftCount; + uint16_t count = last - front + 1; + + uint8_t* pixels = _method.getPixels(); + uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first); + uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, front); + + T_COLOR_FEATURE::movePixelsDec(pFront, pFirst, count); + // intentional no dirty + } +}; + + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/DotStarAvrMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/DotStarAvrMethod.h new file mode 100644 index 000000000..66bd00b0b --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/DotStarAvrMethod.h @@ -0,0 +1,153 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for DotStars on AVR (APA102). + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +// must also check for arm due to Teensy incorrectly having ARDUINO_ARCH_AVR set +#if defined(ARDUINO_ARCH_AVR) && !defined(__arm__) + +class DotStarAvrMethod +{ +public: + DotStarAvrMethod(uint8_t pinClock, uint8_t pinData, uint16_t pixelCount, size_t elementSize) : + _pinClock(pinClock), + _pinData(pinData), + _sizePixels(pixelCount * elementSize) + { + pinMode(pinClock, OUTPUT); + pinMode(pinData, OUTPUT); + + _pixels = (uint8_t*)malloc(_sizePixels); + memset(_pixels, 0, _sizePixels); + + _portClock = portOutputRegister(digitalPinToPort(_pinClock)); + _pinMaskClock = digitalPinToBitMask(_pinClock); + _portData = portOutputRegister(digitalPinToPort(_pinData)); + _pinMaskData = digitalPinToBitMask(_pinData); + } + + ~DotStarAvrMethod() + { + pinMode(_pinClock, INPUT); + pinMode(_pinData, INPUT); + + free(_pixels); + } + + bool IsReadyToUpdate() const + { + return true; // dot stars don't have a required delay + } + + void Initialize() + { + digitalWrite(_pinClock, LOW); + digitalWrite(_pinData, LOW); + } + + void Update() + { + // start frame + for (int startFrameByte = 0; startFrameByte < 4; startFrameByte++) + { + _transmitByte(0x00); + } + + // data + uint8_t* data = _pixels; + const uint8_t* endData = _pixels + _sizePixels; + while (data < endData) + { + _transmitByte(*data++); + } + + // end frame + // one bit for every two pixels with no less than 1 byte + const uint16_t countEndFrameBytes = ((_sizePixels / 4) + 15) / 16; + for (uint16_t endFrameByte = 0; endFrameByte < countEndFrameBytes; endFrameByte++) + { + _transmitByte(0xff); + } + + // set clock and data back to low between updates + digitalWrite(_pinData, LOW); + } + + uint8_t* getPixels() const + { + return _pixels; + }; + + size_t getPixelsSize() const + { + return _sizePixels; + }; + +private: + const uint8_t _pinClock; // output pin number for clock line + const uint8_t _pinData; // output pin number for data line + const size_t _sizePixels; // Size of '_pixels' buffer below + + uint8_t* _pixels; // Holds LED color values + + volatile uint8_t* _portData; // Output PORT register + uint8_t _pinMaskData; // Output PORT bitmask + volatile uint8_t* _portClock; // Output PORT register + uint8_t _pinMaskClock; // Output PORT bitmask + + void _transmitByte(uint8_t data) + { + for (int bit = 7; bit >= 0; bit--) + { + // set data bit on pin + // digitalWrite(_pinData, (data & 0x80) == 0x80 ? HIGH : LOW); + if (data & 0x80) + { + *_portData |= _pinMaskData; + } + else + { + *_portData &= ~_pinMaskData; + } + + + // set clock high as data is ready + // digitalWrite(_pinClock, HIGH); + *_portClock |= _pinMaskClock; + + // done between clock toggle to give a little time + data <<= 1; + + // set clock low as data pin is changed + // digitalWrite(_pinClock, LOW); + *_portClock &= ~_pinMaskClock; + } + } +}; + +typedef DotStarAvrMethod DotStarMethod; + +#endif diff --git a/lib/NeoPixelBus-2.2.9/src/internal/DotStarColorFeatures.h b/lib/NeoPixelBus-2.2.9/src/internal/DotStarColorFeatures.h new file mode 100644 index 000000000..3719d6fc1 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/DotStarColorFeatures.h @@ -0,0 +1,326 @@ +/*------------------------------------------------------------------------- +DotStarColorFeatures provides feature classes to describe color order and +color depth for NeoPixelBus template class when used with DotStars + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +class DotStar3Elements +{ +public: + static const size_t PixelSize = 4; // still requires 4 to be sent + + static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + static const uint8_t* getPixelAddress(const uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + + static void replicatePixel(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + while (pPixelDest < pEnd) + { + *pPixelDest++ = pPixelSrc[0]; + *pPixelDest++ = pPixelSrc[1]; + *pPixelDest++ = pPixelSrc[2]; + *pPixelDest++ = pPixelSrc[3]; + } + } + + static void movePixelsInc(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + while (pPixelDest < pEnd) + { + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + } + } + + static void movePixelsInc_P(uint8_t* pPixelDest, PGM_VOID_P pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + const uint8_t* pSrc = (const uint8_t*)pPixelSrc; + while (pPixelDest < pEnd) + { + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + } + } + + static void movePixelsDec(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pDestBack = pPixelDest + (count * PixelSize); + const uint8_t* pSrcBack = pPixelSrc + (count * PixelSize); + while (pDestBack > pPixelDest) + { + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + } + } + + typedef RgbColor ColorObject; +}; + +class DotStar4Elements +{ +public: + static const size_t PixelSize = 4; + + static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + static const uint8_t* getPixelAddress(const uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + + static void replicatePixel(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + while (pPixelDest < pEnd) + { + *pPixelDest++ = pPixelSrc[0]; + *pPixelDest++ = pPixelSrc[1]; + *pPixelDest++ = pPixelSrc[2]; + *pPixelDest++ = pPixelSrc[3]; + } + } + + static void movePixelsInc(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + while (pPixelDest < pEnd) + { + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + } + } + + static void movePixelsInc_P(uint8_t* pPixelDest, PGM_VOID_P pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + const uint8_t* pSrc = (const uint8_t*)pPixelSrc; + while (pPixelDest < pEnd) + { + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + } + } + + static void movePixelsDec(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pDestBack = pPixelDest + (count * PixelSize); + const uint8_t* pSrcBack = pPixelSrc + (count * PixelSize); + while (pDestBack > pPixelDest) + { + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + } + } + + typedef RgbwColor ColorObject; +}; + +class DotStarBgrFeature : public DotStar3Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = 0xff; // upper three bits are always 111 and brightness at max + *p++ = color.B; + *p++ = color.G; + *p = color.R; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + p++; // ignore the first byte + color.B = *p++; + color.G = *p++; + color.R = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + pgm_read_byte(p++); // ignore the first byte + color.B = pgm_read_byte(p++); + color.G = pgm_read_byte(p++); + color.R = pgm_read_byte(p); + + return color; + } + +}; + +class DotStarLbgrFeature : public DotStar4Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = 0xE0 | (color.W < 31 ? color.W : 31); // upper three bits are always 111 + *p++ = color.B; + *p++ = color.G; + *p = color.R; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.W = (*p++) & 0x1F; // mask out upper three bits + color.B = *p++; + color.G = *p++; + color.R = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.W = pgm_read_byte(p++) & 0x1F; // mask out upper three bits + color.B = pgm_read_byte(p++); + color.G = pgm_read_byte(p++); + color.R = pgm_read_byte(p); + + return color; + } + +}; + +class DotStarGrbFeature : public DotStar3Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = 0xff; // upper three bits are always 111 and brightness at max + *p++ = color.G; + *p++ = color.R; + *p = color.B; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + p++; // ignore the first byte + color.G = *p++; + color.R = *p++; + color.B = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + pgm_read_byte(p++); // ignore the first byte + color.G = pgm_read_byte(p++); + color.R = pgm_read_byte(p++); + color.B = pgm_read_byte(p); + + return color; + } + +}; + +class DotStarLgrbFeature : public DotStar4Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = 0xE0 | (color.W < 31 ? color.W : 31); // upper three bits are always 111 + *p++ = color.G; + *p++ = color.R; + *p = color.B; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.W = (*p++) & 0x1F; // mask out upper three bits + color.G = *p++; + color.R = *p++; + color.B = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.W = pgm_read_byte(p++) & 0x1F; // mask out upper three bits + color.G = pgm_read_byte(p++); + color.R = pgm_read_byte(p++); + color.B = pgm_read_byte(p); + + return color; + } + +}; + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/DotStarGenericMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/DotStarGenericMethod.h new file mode 100644 index 000000000..d59d0e0dd --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/DotStarGenericMethod.h @@ -0,0 +1,128 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for DotStars using general Pins (APA102). + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +class DotStarGenericMethod +{ +public: + DotStarGenericMethod(uint8_t pinClock, uint8_t pinData, uint16_t pixelCount, size_t elementSize) : + _pinClock(pinClock), + _pinData(pinData), + _sizePixels(pixelCount * elementSize) + { + pinMode(pinClock, OUTPUT); + pinMode(pinData, OUTPUT); + + _pixels = (uint8_t*)malloc(_sizePixels); + memset(_pixels, 0, _sizePixels); + } + + ~DotStarGenericMethod() + { + pinMode(_pinClock, INPUT); + pinMode(_pinData, INPUT); + + free(_pixels); + } + + bool IsReadyToUpdate() const + { + return true; // dot stars don't have a required delay + } + + void Initialize() + { + digitalWrite(_pinClock, LOW); + digitalWrite(_pinData, LOW); + } + + void Update() + { + // start frame + for (int startFrameByte = 0; startFrameByte < 4; startFrameByte++) + { + _transmitByte(0x00); + } + + // data + uint8_t* data = _pixels; + const uint8_t* endData = _pixels + _sizePixels; + while (data < endData) + { + _transmitByte(*data++); + } + + // end frame + // one bit for every two pixels with no less than 1 byte + const uint16_t countEndFrameBytes = ((_sizePixels / 4) + 15) / 16; + for (uint16_t endFrameByte = 0; endFrameByte < countEndFrameBytes; endFrameByte++) + { + _transmitByte(0xff); + } + + // set clock and data back to low between updates + digitalWrite(_pinData, LOW); + } + + uint8_t* getPixels() const + { + return _pixels; + }; + + size_t getPixelsSize() const + { + return _sizePixels; + }; + +private: + const uint8_t _pinClock; // output pin number for clock line + const uint8_t _pinData; // output pin number for data line + const size_t _sizePixels; // Size of '_pixels' buffer below + + uint8_t* _pixels; // Holds LED color values + + void _transmitByte(uint8_t data) + { + for (int bit = 7; bit >= 0; bit--) + { + // set data bit on pin + digitalWrite(_pinData, (data & 0x80) == 0x80 ? HIGH : LOW); + + // set clock high as data is ready + digitalWrite(_pinClock, HIGH); + + data <<= 1; + + // set clock low as data pin is changed + digitalWrite(_pinClock, LOW); + } + } +}; + +typedef DotStarGenericMethod DotStarMethod; + + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/DotStarSpiMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/DotStarSpiMethod.h new file mode 100644 index 000000000..4aabc29c2 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/DotStarSpiMethod.h @@ -0,0 +1,125 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for DotStars using SPI hardware (APA102). + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#include + +class DotStarSpiMethod +{ +public: + DotStarSpiMethod(uint16_t pixelCount, size_t elementSize) : + _sizeData(pixelCount * elementSize), + _sizeSendBuffer(calcBufferSize(pixelCount * elementSize)) + { + _sendBuffer = (uint8_t*)malloc(_sizeSendBuffer); + memset(_sendBuffer, 0, _sizeSendBuffer); + setEndFrameBytes(); + } + + ~DotStarSpiMethod() + { + SPI.end(); + free(_sendBuffer); + } + + bool IsReadyToUpdate() const + { + return true; // dot stars don't have a required delay + } + + void Initialize() + { + SPI.begin(); + +#if defined(ARDUINO_ARCH_ESP8266) + SPI.setFrequency(20000000L); +#elif defined(ARDUINO_ARCH_AVR) + SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (6 MHz on Pro Trinket 3V) +#else + SPI.setClockDivider((F_CPU + 4000000L) / 8000000L); // 8-ish MHz on Due +#endif + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + } + + void Update() + { + // due to API inconsistencies need to call different methods on SPI +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) + SPI.writeBytes(_sendBuffer, _sizeSendBuffer); +#else + SPI.transfer(_sendBuffer, _sizeSendBuffer); +#endif + } + + uint8_t* getPixels() const + { + return _sendBuffer + _countStartFrame; + }; + + size_t getPixelsSize() const + { + return _sizeData; + }; + +private: + const size_t _countStartFrame = 4; + const size_t _sizeData; // size of actuall pixel data within _sendBuffer + const size_t _sizeSendBuffer; // Size of '_sendBuffer' buffer below + + uint8_t* _sendBuffer; // Holds SPI send Buffer, including LED color values + + size_t calcBufferSize(size_t sizePixels) const + { + const size_t countEndFrameBytes = calcEndFrameSize(sizePixels); + + // start frame + data + end frame + const size_t bufferSize = _countStartFrame + sizePixels + countEndFrameBytes; + return bufferSize; + } + + size_t calcEndFrameSize(size_t sizePixels) const + { + // end frame + // one bit for every two pixels with no less than 1 byte + return ((sizePixels / 4) + 15) / 16; + } + + void setEndFrameBytes() + { + uint8_t* pEndFrame = _sendBuffer + _countStartFrame + _sizeData; + uint8_t* pEndFrameStop = pEndFrame + calcEndFrameSize(_sizeData); + while (pEndFrame != pEndFrameStop) + { + *pEndFrame++ = 0xff; + } + } +}; + + + + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HsbColor.cpp b/lib/NeoPixelBus-2.2.9/src/internal/HsbColor.cpp new file mode 100644 index 000000000..e47912fa9 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HsbColor.cpp @@ -0,0 +1,68 @@ +/*------------------------------------------------------------------------- +HsbColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "RgbColor.h" +#include "HsbColor.h" + + +HsbColor::HsbColor(const RgbColor& color) +{ + // convert colors to float between (0.0 - 1.0) + float r = color.R / 255.0f; + float g = color.G / 255.0f; + float b = color.B / 255.0f; + + float max = (r > g && r > b) ? r : (g > b) ? g : b; + float min = (r < g && r < b) ? r : (g < b) ? g : b; + + float d = max - min; + + float h = 0.0; + float v = max; + float s = (v == 0.0f) ? 0 : (d / v); + + if (d != 0.0f) + { + if (r == max) + { + h = (g - b) / d + (g < b ? 6.0f : 0.0f); + } + else if (g == max) + { + h = (b - r) / d + 2.0f; + } + else + { + h = (r - g) / d + 4.0f; + } + h /= 6.0f; + } + + + H = h; + S = s; + B = v; +} diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HsbColor.h b/lib/NeoPixelBus-2.2.9/src/internal/HsbColor.h new file mode 100644 index 000000000..4d0bdfaa9 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HsbColor.h @@ -0,0 +1,113 @@ + +/*------------------------------------------------------------------------- +HsbColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +#include + +// ------------------------------------------------------------------------ +// HsbColor represents a color object that is represented by Hue, Saturation, Brightness +// component values. It contains helpful color routines to manipulate the +// color. +// ------------------------------------------------------------------------ +struct HsbColor +{ + // ------------------------------------------------------------------------ + // Construct a HsbColor using H, S, B values (0.0 - 1.0) + // ------------------------------------------------------------------------ + HsbColor(float h, float s, float b) : + H(h), S(s), B(b) + { + }; + + // ------------------------------------------------------------------------ + // Construct a HsbColor using RgbColor + // ------------------------------------------------------------------------ + HsbColor(const RgbColor& color); + + // ------------------------------------------------------------------------ + // Construct a HsbColor that will have its values set in latter operations + // CAUTION: The H,S,B members are not initialized and may not be consistent + // ------------------------------------------------------------------------ + HsbColor() + { + }; + + // ------------------------------------------------------------------------ + // LinearBlend between two colors by the amount defined by progress variable + // left - the color to start the blend at + // right - the color to end the blend at + // progress - (0.0 - 1.0) value where 0.0 will return left and 1.0 will return right + // and a value between will blend the color weighted linearly between them + // ------------------------------------------------------------------------ + template static HsbColor LinearBlend(const HsbColor& left, + const HsbColor& right, + float progress) + { + return HsbColor(T_NEOHUEBLEND::HueBlend(left.H, right.H, progress), + left.S + ((right.S - left.S) * progress), + left.B + ((right.B - left.B) * progress)); + } + + // ------------------------------------------------------------------------ + // BilinearBlend between four colors by the amount defined by 2d variable + // c00 - upper left quadrant color + // c01 - upper right quadrant color + // c10 - lower left quadrant color + // c11 - lower right quadrant color + // x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space + // y - unit value (0.0 - 1.0) that defines the blend progress in vertical space + // ------------------------------------------------------------------------ + template static HsbColor BilinearBlend(const HsbColor& c00, + const HsbColor& c01, + const HsbColor& c10, + const HsbColor& c11, + float x, + float y) + { + float v00 = (1.0f - x) * (1.0f - y); + float v10 = x * (1.0f - y); + float v01 = (1.0f - x) * y; + float v11 = x * y; + + return HsbColor( + T_NEOHUEBLEND::HueBlend( + T_NEOHUEBLEND::HueBlend(c00.H, c10.H, x), + T_NEOHUEBLEND::HueBlend(c01.H, c11.H, x), + y), + c00.S * v00 + c10.S * v10 + c01.S * v01 + c11.S * v11, + c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11); + }; + + // ------------------------------------------------------------------------ + // Hue, Saturation, Brightness color members + // ------------------------------------------------------------------------ + + float H; + float S; + float B; +}; + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HslColor.cpp b/lib/NeoPixelBus-2.2.9/src/internal/HslColor.cpp new file mode 100644 index 000000000..ce9b2388b --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HslColor.cpp @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------- +HslColor provides a color object that can be directly consumed by NeoPixelBus + + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "RgbColor.h" +#include "HslColor.h" + + +HslColor::HslColor(const RgbColor& color) +{ + // convert colors to float between (0.0 - 1.0) + float r = color.R / 255.0f; + float g = color.G / 255.0f; + float b = color.B / 255.0f; + + float max = (r > g && r > b) ? r : (g > b) ? g : b; + float min = (r < g && r < b) ? r : (g < b) ? g : b; + + float h, s, l; + l = (max + min) / 2.0f; + + if (max == min) + { + h = s = 0.0f; + } + else + { + float d = max - min; + s = (l > 0.5f) ? d / (2.0f - (max + min)) : d / (max + min); + + if (r > g && r > b) + { + h = (g - b) / d + (g < b ? 6.0f : 0.0f); + } + else if (g > b) + { + h = (b - r) / d + 2.0f; + } + else + { + h = (r - g) / d + 4.0f; + } + h /= 6.0f; + } + + H = h; + S = s; + L = l; +} diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HslColor.h b/lib/NeoPixelBus-2.2.9/src/internal/HslColor.h new file mode 100644 index 000000000..f6988bd57 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HslColor.h @@ -0,0 +1,113 @@ +/*------------------------------------------------------------------------- +HslColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +#include + +// ------------------------------------------------------------------------ +// HslColor represents a color object that is represented by Hue, Saturation, Lightness +// component values. It contains helpful color routines to manipulate the +// color. +// ------------------------------------------------------------------------ +struct HslColor +{ + + // ------------------------------------------------------------------------ + // Construct a HslColor using H, S, L values (0.0 - 1.0) + // L should be limited to between (0.0 - 0.5) + // ------------------------------------------------------------------------ + HslColor(float h, float s, float l) : + H(h), S(s), L(l) + { + }; + + // ------------------------------------------------------------------------ + // Construct a HslColor using RgbColor + // ------------------------------------------------------------------------ + HslColor(const RgbColor& color); + + // ------------------------------------------------------------------------ + // Construct a HslColor that will have its values set in latter operations + // CAUTION: The H,S,L members are not initialized and may not be consistent + // ------------------------------------------------------------------------ + HslColor() + { + }; + + // ------------------------------------------------------------------------ + // LinearBlend between two colors by the amount defined by progress variable + // left - the color to start the blend at + // right - the color to end the blend at + // progress - (0.0 - 1.0) value where 0.0 will return left and 1.0 will return right + // and a value between will blend the color weighted linearly between them + // ------------------------------------------------------------------------ + template static HslColor LinearBlend(const HslColor& left, + const HslColor& right, + float progress) + { + return HslColor(T_NEOHUEBLEND::HueBlend(left.H, right.H, progress), + left.S + ((right.S - left.S) * progress), + left.L + ((right.L - left.L) * progress)); + }; + + // ------------------------------------------------------------------------ + // BilinearBlend between four colors by the amount defined by 2d variable + // c00 - upper left quadrant color + // c01 - upper right quadrant color + // c10 - lower left quadrant color + // c11 - lower right quadrant color + // x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space + // y - unit value (0.0 - 1.0) that defines the blend progress in vertical space + // ------------------------------------------------------------------------ + template static HslColor BilinearBlend(const HslColor& c00, + const HslColor& c01, + const HslColor& c10, + const HslColor& c11, + float x, + float y) + { + float v00 = (1.0f - x) * (1.0f - y); + float v10 = x * (1.0f - y); + float v01 = (1.0f - x) * y; + float v11 = x * y; + + return HslColor( + T_NEOHUEBLEND::HueBlend( + T_NEOHUEBLEND::HueBlend(c00.H, c10.H, x), + T_NEOHUEBLEND::HueBlend(c01.H, c11.H, x), + y), + c00.S * v00 + c10.S * v10 + c01.S * v01 + c11.S * v11, + c00.L * v00 + c10.L * v10 + c01.L * v01 + c11.L * v11); + }; + + // ------------------------------------------------------------------------ + // Hue, Saturation, Lightness color members + // ------------------------------------------------------------------------ + float H; + float S; + float L; +}; + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.cpp b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.cpp new file mode 100644 index 000000000..018d58f56 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.cpp @@ -0,0 +1,58 @@ +/*------------------------------------------------------------------------- +This file contains the HtmlColor implementation + +Written by Unai Uribarri + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#include "HtmlColor.h" + +static inline char hexdigit(uint8_t v) +{ + return v + (v < 10 ? '0' : 'a' - 10); +} + + +size_t HtmlColor::ToNumericalString(char* buf, size_t bufSize) const +{ + size_t bufLen = bufSize - 1; + + if (bufLen-- > 0) + { + if (bufLen > 0) + { + buf[0] = '#'; + } + + uint32_t color = Color; + for (uint8_t indexDigit = 6; indexDigit > 0; indexDigit--) + { + if (bufLen > indexDigit) + { + buf[indexDigit] = hexdigit(color & 0x0000000f); + } + color >>= 4; + } + + buf[(bufLen < 7 ? bufLen : 7)] = 0; + } + return 7; +} diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.h b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.h new file mode 100644 index 000000000..a40d6223c --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColor.h @@ -0,0 +1,340 @@ +/*------------------------------------------------------------------------- +HtmlColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +#include +#include "RgbColor.h" + +#define MAX_HTML_COLOR_NAME_LEN 21 + +#ifndef pgm_read_ptr +// ESP8266 doesn't define this macro +#define pgm_read_ptr(addr) (*reinterpret_cast(addr)) +#endif + +#ifndef countof +#define countof(array) (sizeof(array)/sizeof(array[0])) +#endif + +// ------------------------------------------------------------------------ +// HtmlColorPair represents an association between a name and a HTML color code +// ------------------------------------------------------------------------ +struct HtmlColorPair +{ + PGM_P Name; + uint32_t Color; +}; + +// ------------------------------------------------------------------------ +// HtmlShortColorNames is a template class used for Parse and ToString +// ------------------------------------------------------------------------ +class HtmlShortColorNames +{ +public: + static const HtmlColorPair* Pair(uint8_t index); + static uint8_t Count(); +}; + +// ------------------------------------------------------------------------ +// HtmlColorNames is a template class used for Parse and ToString +// ------------------------------------------------------------------------ +class HtmlColorNames +{ +public: + static const HtmlColorPair* Pair(uint8_t index); + static uint8_t Count(); +}; + +// ------------------------------------------------------------------------ +// HtmlColor represents a color object that is represented by a single uint32 +// value. It contains minimal routines and used primarily as a helper to +// initialize other color objects +// ------------------------------------------------------------------------ +struct HtmlColor +{ + // ------------------------------------------------------------------------ + // Construct a HtmlColor using a single value (0-0xffffff) + // This works well for hexidecimal color definitions + // 0xff0000 = red, 0x00ff00 = green, and 0x0000ff = blue + // ------------------------------------------------------------------------ + HtmlColor(uint32_t color) : + Color(color) + { + }; + + // ------------------------------------------------------------------------ + // Construct a HtmlColor using RgbColor + // ------------------------------------------------------------------------ + HtmlColor(const RgbColor& color) + { + Color = (uint32_t)color.R << 16 | (uint32_t)color.G << 8 | (uint32_t)color.B; + } + + // ------------------------------------------------------------------------ + // Construct a HtmlColor that will have its values set in latter operations + // CAUTION: The Color member is not initialized and may not be consistent + // ------------------------------------------------------------------------ + HtmlColor() + { + }; + + // ------------------------------------------------------------------------ + // Comparison operators + // ------------------------------------------------------------------------ + bool operator==(const HtmlColor& other) const + { + return (Color == other.Color); + }; + + bool operator!=(const HtmlColor& other) const + { + return !(*this == other); + }; + + // ------------------------------------------------------------------------ + // Parse a HTML4/CSS3 color name + // T_HTMLCOLORNAMES - template class that defines the collection of names + // name - the color name + // nameSize - the max size of name to check + // + // returns - zero if failed, or the number of chars parsed + // + // It will stop parsing name when a null terminator is reached, + // nameSize is reached, no match is found in the name/color pair table, or + // a non-alphanumeric is read like seperators or whitespace. + // + // It also accepts 3 or 6 digit hexadecimal notation (#rgb or #rrggbb), + // but it doesn't accept RGB, RGBA nor HSL values. + // + // See https://www.w3.org/TR/css3-color/#SRGB + // + // name must point to the first non-whitespace character to be parsed + // parsing will stop at the first non-alpha numeric + // + // Name MUST NOT be a PROGMEM pointer + // + // examples: + // Parse(buff, buffSize); + // Parse(buff, buffSize); + // ------------------------------------------------------------------------ + + template size_t Parse(const char* name, size_t nameSize) + { + if (nameSize > 0) + { + if (name[0] == '#') + { + // Parse an hexadecimal notation "#rrbbgg" or "#rgb" + // + uint8_t temp[6]; // stores preconverted chars to hex values + uint8_t tempSize = 0; + + for (uint8_t indexChar = 1; indexChar < nameSize && indexChar < 8; ++indexChar) + { + char c = name[indexChar]; + if (c >= '0' && c <= '9') + { + c -= '0'; + } + else + { + // Convert a letter to lower case (only for ASCII letters) + // It's faster & smaller than tolower() + c |= 32; + if (c >= 'a' && c <= 'f') + { + c = c - 'a' + 10; + } + else + { + // we found an non hexidecimal char + // which could be null, deliminator, or other spacing + break; + } + } + + temp[tempSize] = c; + tempSize++; + } + + if (tempSize != 3 && tempSize != 6) + { + // invalid count of numerical chars + return 0; + } + else + { + uint32_t color = 0; + for (uint8_t indexChar = 0; indexChar < tempSize; ++indexChar) + { + color = color * 16 + temp[indexChar]; + if (tempSize == 3) + { + // 3 digit hexadecimal notation can be supported easily + // duplicating digits. + color = color * 16 + temp[indexChar]; + } + } + + Color = color; + return tempSize; + } + } + else + { + // parse a standard name for the color + // + + // the normal list is small enough a binary search isn't interesting, + for (uint8_t indexName = 0; indexName < T_HTMLCOLORNAMES::Count(); ++indexName) + { + const HtmlColorPair* colorPair = T_HTMLCOLORNAMES::Pair(indexName); + PGM_P searchName = (PGM_P)pgm_read_ptr(&colorPair->Name); + size_t str1Size = nameSize; + const char* str1 = name; + const char* str2P = searchName; + + uint16_t result; + + while (str1Size > 0) + { + char ch1 = tolower(*str1++); + char ch2 = tolower(pgm_read_byte(str2P++)); + result = ch1 - ch2; + if (result != 0 || ch2 == '\0') + { + if (ch2 == '\0' && !isalnum(ch1)) + { + // the string continues but is not part of a + // valid color name, + // ends in white space, deliminator, etc + result = 0; + } + break; + } + result = -1; // have not reached the end of searchName; + str1Size--; + } + + if (result == 0) + { + Color = pgm_read_dword(&colorPair->Color); + return nameSize - str1Size; + } + } + } + } + + return 0; + } + + template size_t Parse(const char* name) + { + return Parse(name, MAX_HTML_COLOR_NAME_LEN + 1); + } + + template size_t Parse(String const &name) + { + return Parse(name.c_str(), name.length() + 1); + } + + // ------------------------------------------------------------------------ + // Converts this color code to its HTML4/CSS3 name + // T_HTMLCOLORNAMES - template class that defines the collection of names + // buf - buffer to write the string + // bufSize - actual size of buf array + // + // It returns the number of chars required not including the NUL terminator. + // + // If there is not enough space in the buffer, it will write as many + // characters as allowed and will always finish the buffer with a NUL char + // + // examples: + // ToString(buf, bufSize); + // ToString(buf, bufSize); + // ------------------------------------------------------------------------ + + template size_t ToString(char* buf, size_t bufSize) const + { + // search for a color value/name pairs first + for (uint8_t indexName = 0; indexName < T_HTMLCOLORNAMES::Count(); ++indexName) + { + const HtmlColorPair* colorPair = T_HTMLCOLORNAMES::Pair(indexName); + if (pgm_read_dword(&colorPair->Color) == Color) + { + PGM_P name = (PGM_P)pgm_read_ptr(&colorPair->Name); + strncpy_P(buf, name, bufSize); + return strlen_P(name); + } + } + + // no color name pair match, convert using numerical format + return ToNumericalString(buf, bufSize); + } + + // ------------------------------------------------------------------------ + // Converts this color code to its HTML4/CSS3 numerical name + // + // buf - buffer to write the string + // bufSize - actual size of buf array + // + // It returns the number of chars required not including the NUL terminator. + // + // If there is not enough space in the buffer, it will write as many + // characters as allowed and will always finish the buffer with a NUL char + // ------------------------------------------------------------------------ + + size_t ToNumericalString(char* buf, size_t bufSize) const; + + // ------------------------------------------------------------------------ + // BilinearBlend between four colors by the amount defined by 2d variable + // c00 - upper left quadrant color + // c01 - upper right quadrant color + // c10 - lower left quadrant color + // c11 - lower right quadrant color + // x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space + // y - unit value (0.0 - 1.0) that defines the blend progress in vertical space + // ------------------------------------------------------------------------ + + static HtmlColor BilinearBlend(const HtmlColor& c00, + const HtmlColor& c01, + const HtmlColor& c10, + const HtmlColor& c11, + float x, + float y) + { + return RgbColor::BilinearBlend(c00, c01, c10, c11, x, y); + } + + // ------------------------------------------------------------------------ + // Color member (0-0xffffff) where + // 0xff0000 is red + // 0x00ff00 is green + // 0x0000ff is blue + // ------------------------------------------------------------------------ + uint32_t Color; +}; + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.cpp b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.cpp new file mode 100644 index 000000000..87dda4b3d --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.cpp @@ -0,0 +1,178 @@ +/*------------------------------------------------------------------------- +HtmlColorNameStrings provides the implemenation of the color string names + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "HtmlColorNameStrings.h" + +/* HTML4 color names */ +const char c_HtmlNameAqua[] PROGMEM = "aqua"; +const char c_HtmlNameBlack[] PROGMEM = "black"; +const char c_HtmlNameBlue[] PROGMEM = "blue"; +const char c_HtmlNameFuchsia[] PROGMEM = "fuchsia"; +const char c_HtmlNameGray[] PROGMEM = "gray"; +const char c_HtmlNameGreen[] PROGMEM = "green"; +const char c_HtmlNameLime[] PROGMEM = "lime"; +const char c_HtmlNameMaroon[] PROGMEM = "maroon"; +const char c_HtmlNameNavy[] PROGMEM = "navy"; +const char c_HtmlNameOlive[] PROGMEM = "olive"; +const char c_HtmlNameOrange[] PROGMEM = "orange"; +const char c_HtmlNamePurple[] PROGMEM = "purple"; +const char c_HtmlNameRed[] PROGMEM = "red"; +const char c_HtmlNameSilver[] PROGMEM = "silver"; +const char c_HtmlNameTeal[] PROGMEM = "teal"; +const char c_HtmlNameWhite[] PROGMEM = "white"; +const char c_HtmlNameYellow[] PROGMEM = "yellow"; + +/* Additional CSS3 color names */ +const char c_HtmlNameAliceBlue[] PROGMEM = "aliceblue"; +const char c_HtmlNameAntiqueWhite[] PROGMEM = "antiquewhite"; +const char c_HtmlNameAquamarine[] PROGMEM = "aquamarine"; +const char c_HtmlNameAzure[] PROGMEM = "azure"; +const char c_HtmlNameBeige[] PROGMEM = "beige"; +const char c_HtmlNameBisque[] PROGMEM = "bisque"; +const char c_HtmlNameBlanchedAlmond[] PROGMEM = "blanchedalmond"; +const char c_HtmlNameBlueViolet[] PROGMEM = "blueviolet"; +const char c_HtmlNameBrown[] PROGMEM = "brown"; +const char c_HtmlNameBurlyWood[] PROGMEM = "burlywood"; +const char c_HtmlNameCadetBlue[] PROGMEM = "cadetblue"; +const char c_HtmlNameChartreuse[] PROGMEM = "chartreuse"; +const char c_HtmlNameChocolate[] PROGMEM = "chocolate"; +const char c_HtmlNameCoral[] PROGMEM = "coral"; +const char c_HtmlNameCornflowerBlue[] PROGMEM = "cornflowerblue"; +const char c_HtmlNameCornsilk[] PROGMEM = "cornsilk"; +const char c_HtmlNameCrimson[] PROGMEM = "crimson"; +const char c_HtmlNameCyan[] PROGMEM = "cyan"; +const char c_HtmlNameDarkBlue[] PROGMEM = "darkblue"; +const char c_HtmlNameDarkCyan[] PROGMEM = "darkcyan"; +const char c_HtmlNameDarkGoldenrod[] PROGMEM = "darkgoldenrod"; +const char c_HtmlNameDarkGray[] PROGMEM = "darkgray"; +const char c_HtmlNameDarkGreen[] PROGMEM = "darkgreen"; +const char c_HtmlNameDarkGrey[] PROGMEM = "darkgrey"; +const char c_HtmlNameDarkKhaki[] PROGMEM = "darkkhaki"; +const char c_HtmlNameDarkMagenta[] PROGMEM = "darkmagenta"; +const char c_HtmlNameDarkOliveGreen[] PROGMEM = "darkolivegreen"; +const char c_HtmlNameDarkOrange[] PROGMEM = "darkorange"; +const char c_HtmlNameDarkOrchid[] PROGMEM = "darkorchid"; +const char c_HtmlNameDarkRed[] PROGMEM = "darkred"; +const char c_HtmlNameDarkSalmon[] PROGMEM = "darksalmon"; +const char c_HtmlNameDarkSeaGreen[] PROGMEM = "darkseagreen"; +const char c_HtmlNameDarkSlateBlue[] PROGMEM = "darkslateblue"; +const char c_HtmlNameDarkSlateGray[] PROGMEM = "darkslategray"; +const char c_HtmlNameDarkSlateGrey[] PROGMEM = "darkslategrey"; +const char c_HtmlNameDarkTurquoise[] PROGMEM = "darkturquoise"; +const char c_HtmlNameDarkViolet[] PROGMEM = "darkviolet"; +const char c_HtmlNameDeepPink[] PROGMEM = "deeppink"; +const char c_HtmlNameDeepSkyBlue[] PROGMEM = "deepskyblue"; +const char c_HtmlNameDimGray[] PROGMEM = "dimgray"; +const char c_HtmlNameDimGrey[] PROGMEM = "dimgrey"; +const char c_HtmlNameDodgerBlue[] PROGMEM = "dodgerblue"; +const char c_HtmlNameFirebrick[] PROGMEM = "firebrick"; +const char c_HtmlNameFloralWhite[] PROGMEM = "floralwhite"; +const char c_HtmlNameForestGreen[] PROGMEM = "forestgreen"; +const char c_HtmlNameGainsboro[] PROGMEM = "gainsboro"; +const char c_HtmlNameGhostWhite[] PROGMEM = "ghostwhite"; +const char c_HtmlNameGold[] PROGMEM = "gold"; +const char c_HtmlNameGoldenrod[] PROGMEM = "goldenrod"; +const char c_HtmlNameGreenYellow[] PROGMEM = "greenyellow"; +const char c_HtmlNameGrey[] PROGMEM = "grey"; +const char c_HtmlNameHoneydew[] PROGMEM = "honeydew"; +const char c_HtmlNameHotPink[] PROGMEM = "hotpink"; +const char c_HtmlNameIndianRed[] PROGMEM = "indianred"; +const char c_HtmlNameIndigo[] PROGMEM = "indigo"; +const char c_HtmlNameIvory[] PROGMEM = "ivory"; +const char c_HtmlNameKhaki[] PROGMEM = "khaki"; +const char c_HtmlNameLavender[] PROGMEM = "lavender"; +const char c_HtmlNameLavenderBlush[] PROGMEM = "lavenderblush"; +const char c_HtmlNameLawnGreen[] PROGMEM = "lawngreen"; +const char c_HtmlNameLemonChiffon[] PROGMEM = "lemonchiffon"; +const char c_HtmlNameLightBlue[] PROGMEM = "lightblue"; +const char c_HtmlNameLightCoral[] PROGMEM = "lightcoral"; +const char c_HtmlNameLightCyan[] PROGMEM = "lightcyan"; +const char c_HtmlNameLightGoldenrodYellow[] PROGMEM = "lightgoldenrodyellow"; +const char c_HtmlNameLightGray[] PROGMEM = "lightgray"; +const char c_HtmlNameLightGreen[] PROGMEM = "lightgreen"; +const char c_HtmlNameLightGrey[] PROGMEM = "lightgrey"; +const char c_HtmlNameLightPink[] PROGMEM = "lightpink"; +const char c_HtmlNameLightSalmon[] PROGMEM = "lightsalmon"; +const char c_HtmlNameLightSeaGreen[] PROGMEM = "lightseagreen"; +const char c_HtmlNameLightSkyBlue[] PROGMEM = "lightskyblue"; +const char c_HtmlNameLightSlateGray[] PROGMEM = "lightslategray"; +const char c_HtmlNameLightSlateGrey[] PROGMEM = "lightslategrey"; +const char c_HtmlNameLightSteelBlue[] PROGMEM = "lightsteelblue"; +const char c_HtmlNameLightYellow[] PROGMEM = "lightyellow"; +const char c_HtmlNameLimeGreen[] PROGMEM = "limegreen"; +const char c_HtmlNameLinen[] PROGMEM = "linen"; +const char c_HtmlNameMagenta[] PROGMEM = "magenta"; +const char c_HtmlNameMediumAquamarine[] PROGMEM = "mediumaquamarine"; +const char c_HtmlNameMediumBlue[] PROGMEM = "mediumblue"; +const char c_HtmlNameMediumOrchid[] PROGMEM = "mediumorchid"; +const char c_HtmlNameMediumPurple[] PROGMEM = "mediumpurple"; +const char c_HtmlNameMediumSeagreen[] PROGMEM = "mediumseagreen"; +const char c_HtmlNameMediumSlateBlue[] PROGMEM = "mediumslateblue"; +const char c_HtmlNameMediumSpringGreen[] PROGMEM = "mediumspringgreen"; +const char c_HtmlNameMediumTurquoise[] PROGMEM = "mediumturquoise"; +const char c_HtmlNameMediumVioletRed[] PROGMEM = "mediumvioletred"; +const char c_HtmlNameMidnightBlue[] PROGMEM = "midnightblue"; +const char c_HtmlNameMintCream[] PROGMEM = "mintcream"; +const char c_HtmlNameMistyRose[] PROGMEM = "mistyrose"; +const char c_HtmlNameMoccasin[] PROGMEM = "moccasin"; +const char c_HtmlNameNavajoWhite[] PROGMEM = "navajowhite"; +const char c_HtmlNameOldLace[] PROGMEM = "oldlace"; +const char c_HtmlNameOliveDrab[] PROGMEM = "olivedrab"; +const char c_HtmlNameOrangeRed[] PROGMEM = "orangered"; +const char c_HtmlNameOrchid[] PROGMEM = "orchid"; +const char c_HtmlNamePaleGoldenrod[] PROGMEM = "palegoldenrod"; +const char c_HtmlNamePaleGreen[] PROGMEM = "palegreen"; +const char c_HtmlNamePaleTurquoise[] PROGMEM = "paleturquoise"; +const char c_HtmlNamePaleVioletRed[] PROGMEM = "palevioletred"; +const char c_HtmlNamePapayaWhip[] PROGMEM = "papayawhip"; +const char c_HtmlNamePeachPuff[] PROGMEM = "peachpuff"; +const char c_HtmlNamePeru[] PROGMEM = "peru"; +const char c_HtmlNamePink[] PROGMEM = "pink"; +const char c_HtmlNamePlum[] PROGMEM = "plum"; +const char c_HtmlNamePowderBlue[] PROGMEM = "powderblue"; +const char c_HtmlNameRosyBrown[] PROGMEM = "rosybrown"; +const char c_HtmlNameRoyalBlue[] PROGMEM = "royalblue"; +const char c_HtmlNameSaddleBrown[] PROGMEM = "saddlebrown"; +const char c_HtmlNameSalmon[] PROGMEM = "salmon"; +const char c_HtmlNameSandyBrown[] PROGMEM = "sandybrown"; +const char c_HtmlNameSeaGreen[] PROGMEM = "seagreen"; +const char c_HtmlNameSeaShell[] PROGMEM = "seashell"; +const char c_HtmlNameSienna[] PROGMEM = "sienna"; +const char c_HtmlNameSkyBlue[] PROGMEM = "skyblue"; +const char c_HtmlNameSlateBlue[] PROGMEM = "slateblue"; +const char c_HtmlNameSlateGray[] PROGMEM = "slategray"; +const char c_HtmlNameSlateGrey[] PROGMEM = "slategrey"; +const char c_HtmlNameSnow[] PROGMEM = "snow"; +const char c_HtmlNameSpringGreen[] PROGMEM = "springgreen"; +const char c_HtmlNameSteelBlue[] PROGMEM = "steelblue"; +const char c_HtmlNameTan[] PROGMEM = "tan"; +const char c_HtmlNameThistle[] PROGMEM = "thistle"; +const char c_HtmlNameTomato[] PROGMEM = "tomato"; +const char c_HtmlNameTurquoise[] PROGMEM = "turquoise"; +const char c_HtmlNameViolet[] PROGMEM = "violet"; +const char c_HtmlNameWheat[] PROGMEM = "wheat"; +const char c_HtmlNameWhiteSmoke[] PROGMEM = "whitesmoke"; +const char c_HtmlNameYellowGreen[] PROGMEM = "yellowgreen"; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.h b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.h new file mode 100644 index 000000000..86ffcf4f2 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNameStrings.h @@ -0,0 +1,180 @@ +/*------------------------------------------------------------------------- +HtmlColorNameStrings provides the declaration of the color string names + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#include + +/* HTML4 color names */ +extern const char c_HtmlNameAqua[] PROGMEM; +extern const char c_HtmlNameBlack[] PROGMEM; +extern const char c_HtmlNameBlue[] PROGMEM; +extern const char c_HtmlNameFuchsia[] PROGMEM; +extern const char c_HtmlNameGray[] PROGMEM; +extern const char c_HtmlNameGreen[] PROGMEM; +extern const char c_HtmlNameLime[] PROGMEM; +extern const char c_HtmlNameMaroon[] PROGMEM; +extern const char c_HtmlNameNavy[] PROGMEM; +extern const char c_HtmlNameOlive[] PROGMEM; +extern const char c_HtmlNameOrange[] PROGMEM; +extern const char c_HtmlNamePurple[] PROGMEM; +extern const char c_HtmlNameRed[] PROGMEM; +extern const char c_HtmlNameSilver[] PROGMEM; +extern const char c_HtmlNameTeal[] PROGMEM; +extern const char c_HtmlNameWhite[] PROGMEM; +extern const char c_HtmlNameYellow[] PROGMEM; + +/* Additional CSS3 color names */ +extern const char c_HtmlNameAliceBlue[] PROGMEM; +extern const char c_HtmlNameAntiqueWhite[] PROGMEM; +extern const char c_HtmlNameAquamarine[] PROGMEM; +extern const char c_HtmlNameAzure[] PROGMEM; +extern const char c_HtmlNameBeige[] PROGMEM; +extern const char c_HtmlNameBisque[] PROGMEM; +extern const char c_HtmlNameBlanchedAlmond[] PROGMEM; +extern const char c_HtmlNameBlueViolet[] PROGMEM; +extern const char c_HtmlNameBrown[] PROGMEM; +extern const char c_HtmlNameBurlyWood[] PROGMEM; +extern const char c_HtmlNameCadetBlue[] PROGMEM; +extern const char c_HtmlNameChartreuse[] PROGMEM; +extern const char c_HtmlNameChocolate[] PROGMEM; +extern const char c_HtmlNameCoral[] PROGMEM; +extern const char c_HtmlNameCornflowerBlue[] PROGMEM; +extern const char c_HtmlNameCornsilk[] PROGMEM; +extern const char c_HtmlNameCrimson[] PROGMEM; +extern const char c_HtmlNameCyan[] PROGMEM; +extern const char c_HtmlNameDarkBlue[] PROGMEM; +extern const char c_HtmlNameDarkCyan[] PROGMEM; +extern const char c_HtmlNameDarkGoldenrod[] PROGMEM; +extern const char c_HtmlNameDarkGray[] PROGMEM; +extern const char c_HtmlNameDarkGreen[] PROGMEM; +extern const char c_HtmlNameDarkGrey[] PROGMEM; +extern const char c_HtmlNameDarkKhaki[] PROGMEM; +extern const char c_HtmlNameDarkMagenta[] PROGMEM; +extern const char c_HtmlNameDarkOliveGreen[] PROGMEM; +extern const char c_HtmlNameDarkOrange[] PROGMEM; +extern const char c_HtmlNameDarkOrchid[] PROGMEM; +extern const char c_HtmlNameDarkRed[] PROGMEM; +extern const char c_HtmlNameDarkSalmon[] PROGMEM; +extern const char c_HtmlNameDarkSeaGreen[] PROGMEM; +extern const char c_HtmlNameDarkSlateBlue[] PROGMEM; +extern const char c_HtmlNameDarkSlateGray[] PROGMEM; +extern const char c_HtmlNameDarkSlateGrey[] PROGMEM; +extern const char c_HtmlNameDarkTurquoise[] PROGMEM; +extern const char c_HtmlNameDarkViolet[] PROGMEM; +extern const char c_HtmlNameDeepPink[] PROGMEM; +extern const char c_HtmlNameDeepSkyBlue[] PROGMEM; +extern const char c_HtmlNameDimGray[] PROGMEM; +extern const char c_HtmlNameDimGrey[] PROGMEM; +extern const char c_HtmlNameDodgerBlue[] PROGMEM; +extern const char c_HtmlNameFirebrick[] PROGMEM; +extern const char c_HtmlNameFloralWhite[] PROGMEM; +extern const char c_HtmlNameForestGreen[] PROGMEM; +extern const char c_HtmlNameGainsboro[] PROGMEM; +extern const char c_HtmlNameGhostWhite[] PROGMEM; +extern const char c_HtmlNameGold[] PROGMEM; +extern const char c_HtmlNameGoldenrod[] PROGMEM; +extern const char c_HtmlNameGreenYellow[] PROGMEM; +extern const char c_HtmlNameGrey[] PROGMEM; +extern const char c_HtmlNameHoneydew[] PROGMEM; +extern const char c_HtmlNameHotPink[] PROGMEM; +extern const char c_HtmlNameIndianRed[] PROGMEM; +extern const char c_HtmlNameIndigo[] PROGMEM; +extern const char c_HtmlNameIvory[] PROGMEM; +extern const char c_HtmlNameKhaki[] PROGMEM; +extern const char c_HtmlNameLavender[] PROGMEM; +extern const char c_HtmlNameLavenderBlush[] PROGMEM; +extern const char c_HtmlNameLawnGreen[] PROGMEM; +extern const char c_HtmlNameLemonChiffon[] PROGMEM; +extern const char c_HtmlNameLightBlue[] PROGMEM; +extern const char c_HtmlNameLightCoral[] PROGMEM; +extern const char c_HtmlNameLightCyan[] PROGMEM; +extern const char c_HtmlNameLightGoldenrodYellow[] PROGMEM; +extern const char c_HtmlNameLightGray[] PROGMEM; +extern const char c_HtmlNameLightGreen[] PROGMEM; +extern const char c_HtmlNameLightGrey[] PROGMEM; +extern const char c_HtmlNameLightPink[] PROGMEM; +extern const char c_HtmlNameLightSalmon[] PROGMEM; +extern const char c_HtmlNameLightSeaGreen[] PROGMEM; +extern const char c_HtmlNameLightSkyBlue[] PROGMEM; +extern const char c_HtmlNameLightSlateGray[] PROGMEM; +extern const char c_HtmlNameLightSlateGrey[] PROGMEM; +extern const char c_HtmlNameLightSteelBlue[] PROGMEM; +extern const char c_HtmlNameLightYellow[] PROGMEM; +extern const char c_HtmlNameLimeGreen[] PROGMEM; +extern const char c_HtmlNameLinen[] PROGMEM; +extern const char c_HtmlNameMagenta[] PROGMEM; +extern const char c_HtmlNameMediumAquamarine[] PROGMEM; +extern const char c_HtmlNameMediumBlue[] PROGMEM; +extern const char c_HtmlNameMediumOrchid[] PROGMEM; +extern const char c_HtmlNameMediumPurple[] PROGMEM; +extern const char c_HtmlNameMediumSeagreen[] PROGMEM; +extern const char c_HtmlNameMediumSlateBlue[] PROGMEM; +extern const char c_HtmlNameMediumSpringGreen[] PROGMEM; +extern const char c_HtmlNameMediumTurquoise[] PROGMEM; +extern const char c_HtmlNameMediumVioletRed[] PROGMEM; +extern const char c_HtmlNameMidnightBlue[] PROGMEM; +extern const char c_HtmlNameMintCream[] PROGMEM; +extern const char c_HtmlNameMistyRose[] PROGMEM; +extern const char c_HtmlNameMoccasin[] PROGMEM; +extern const char c_HtmlNameNavajoWhite[] PROGMEM; +extern const char c_HtmlNameOldLace[] PROGMEM; +extern const char c_HtmlNameOliveDrab[] PROGMEM; +extern const char c_HtmlNameOrangeRed[] PROGMEM; +extern const char c_HtmlNameOrchid[] PROGMEM; +extern const char c_HtmlNamePaleGoldenrod[] PROGMEM; +extern const char c_HtmlNamePaleGreen[] PROGMEM; +extern const char c_HtmlNamePaleTurquoise[] PROGMEM; +extern const char c_HtmlNamePaleVioletRed[] PROGMEM; +extern const char c_HtmlNamePapayaWhip[] PROGMEM; +extern const char c_HtmlNamePeachPuff[] PROGMEM; +extern const char c_HtmlNamePeru[] PROGMEM; +extern const char c_HtmlNamePink[] PROGMEM; +extern const char c_HtmlNamePlum[] PROGMEM; +extern const char c_HtmlNamePowderBlue[] PROGMEM; +extern const char c_HtmlNameRosyBrown[] PROGMEM; +extern const char c_HtmlNameRoyalBlue[] PROGMEM; +extern const char c_HtmlNameSaddleBrown[] PROGMEM; +extern const char c_HtmlNameSalmon[] PROGMEM; +extern const char c_HtmlNameSandyBrown[] PROGMEM; +extern const char c_HtmlNameSeaGreen[] PROGMEM; +extern const char c_HtmlNameSeaShell[] PROGMEM; +extern const char c_HtmlNameSienna[] PROGMEM; +extern const char c_HtmlNameSkyBlue[] PROGMEM; +extern const char c_HtmlNameSlateBlue[] PROGMEM; +extern const char c_HtmlNameSlateGray[] PROGMEM; +extern const char c_HtmlNameSlateGrey[] PROGMEM; +extern const char c_HtmlNameSnow[] PROGMEM; +extern const char c_HtmlNameSpringGreen[] PROGMEM; +extern const char c_HtmlNameSteelBlue[] PROGMEM; +extern const char c_HtmlNameTan[] PROGMEM; +extern const char c_HtmlNameThistle[] PROGMEM; +extern const char c_HtmlNameTomato[] PROGMEM; +extern const char c_HtmlNameTurquoise[] PROGMEM; +extern const char c_HtmlNameViolet[] PROGMEM; +extern const char c_HtmlNameWheat[] PROGMEM; +extern const char c_HtmlNameWhiteSmoke[] PROGMEM; +extern const char c_HtmlNameYellowGreen[] PROGMEM; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNames.cpp b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNames.cpp new file mode 100644 index 000000000..b1098eaae --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorNames.cpp @@ -0,0 +1,188 @@ +/*------------------------------------------------------------------------- +HtmlColorNames provides a template class for access to the full name table + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "HtmlColor.h" +#include "HtmlColorNameStrings.h" + +static const HtmlColorPair c_ColorNames[] PROGMEM = { + { c_HtmlNameAliceBlue, 0xf0f8ff }, + { c_HtmlNameAntiqueWhite, 0xfaebd7 }, + { c_HtmlNameAqua, 0xffff }, + { c_HtmlNameAquamarine, 0x7fffd4 }, + { c_HtmlNameAzure, 0xf0ffff }, + { c_HtmlNameBeige, 0xf5f5dc }, + { c_HtmlNameBisque, 0xffe4c4 }, + { c_HtmlNameBlack, 0x0 }, + { c_HtmlNameBlanchedAlmond, 0xffebcd }, + { c_HtmlNameBlue, 0xff }, + { c_HtmlNameBlueViolet, 0x8a2be2 }, + { c_HtmlNameBrown, 0xa52a2a }, + { c_HtmlNameBurlyWood, 0xdeb887 }, + { c_HtmlNameCadetBlue, 0x5f9ea0 }, + { c_HtmlNameChartreuse, 0x7fff00 }, + { c_HtmlNameChocolate, 0xd2691e }, + { c_HtmlNameCoral, 0xff7f50 }, + { c_HtmlNameCornflowerBlue, 0x6495ed }, + { c_HtmlNameCornsilk, 0xfff8dc }, + { c_HtmlNameCrimson, 0xdc143c }, + { c_HtmlNameCyan, 0xffff }, + { c_HtmlNameDarkBlue, 0x8b }, + { c_HtmlNameDarkCyan, 0x8b8b }, + { c_HtmlNameDarkGoldenrod, 0xb8860b }, + { c_HtmlNameDarkGray, 0xa9a9a9 }, + { c_HtmlNameDarkGreen, 0x6400 }, + { c_HtmlNameDarkGrey, 0xa9a9a9 }, + { c_HtmlNameDarkKhaki, 0xbdb76b }, + { c_HtmlNameDarkMagenta, 0x8b008b }, + { c_HtmlNameDarkOliveGreen, 0x556b2f }, + { c_HtmlNameDarkOrange, 0xff8c00 }, + { c_HtmlNameDarkOrchid, 0x9932cc }, + { c_HtmlNameDarkRed, 0x8b0000 }, + { c_HtmlNameDarkSalmon, 0xe9967a }, + { c_HtmlNameDarkSeaGreen, 0x8fbc8f }, + { c_HtmlNameDarkSlateBlue, 0x483d8b }, + { c_HtmlNameDarkSlateGray, 0x2f4f4f }, + { c_HtmlNameDarkSlateGrey, 0x2f4f4f }, + { c_HtmlNameDarkTurquoise, 0xced1 }, + { c_HtmlNameDarkViolet, 0x9400d3 }, + { c_HtmlNameDeepPink, 0xff1493 }, + { c_HtmlNameDeepSkyBlue, 0xbfff }, + { c_HtmlNameDimGray, 0x696969 }, + { c_HtmlNameDimGrey, 0x696969 }, + { c_HtmlNameDodgerBlue, 0x1e90ff }, + { c_HtmlNameFirebrick, 0xb22222 }, + { c_HtmlNameFloralWhite, 0xfffaf0 }, + { c_HtmlNameForestGreen, 0x228b22 }, + { c_HtmlNameFuchsia, 0xff00ff }, + { c_HtmlNameGainsboro, 0xdcdcdc }, + { c_HtmlNameGhostWhite, 0xf8f8ff }, + { c_HtmlNameGold, 0xffd700 }, + { c_HtmlNameGoldenrod, 0xdaa520 }, + { c_HtmlNameGray, 0x808080 }, + { c_HtmlNameGreen, 0x8000 }, + { c_HtmlNameGreenYellow, 0xadff2f }, + { c_HtmlNameGrey, 0x808080 }, + { c_HtmlNameHoneydew, 0xf0fff0 }, + { c_HtmlNameHotPink, 0xff69b4 }, + { c_HtmlNameIndianRed, 0xcd5c5c }, + { c_HtmlNameIndigo, 0x4b0082 }, + { c_HtmlNameIvory, 0xfffff0 }, + { c_HtmlNameKhaki, 0xf0e68c }, + { c_HtmlNameLavender, 0xe6e6fa }, + { c_HtmlNameLavenderBlush, 0xfff0f5 }, + { c_HtmlNameLawnGreen, 0x7cfc00 }, + { c_HtmlNameLemonChiffon, 0xfffacd }, + { c_HtmlNameLightBlue, 0xadd8e6 }, + { c_HtmlNameLightCoral, 0xf08080 }, + { c_HtmlNameLightCyan, 0xe0ffff }, + { c_HtmlNameLightGoldenrodYellow, 0xfafad2 }, + { c_HtmlNameLightGray, 0xd3d3d3 }, + { c_HtmlNameLightGreen, 0x90ee90 }, + { c_HtmlNameLightGrey, 0xd3d3d3 }, + { c_HtmlNameLightPink, 0xffb6c1 }, + { c_HtmlNameLightSalmon, 0xffa07a }, + { c_HtmlNameLightSeaGreen, 0x20b2aa }, + { c_HtmlNameLightSkyBlue, 0x87cefa }, + { c_HtmlNameLightSlateGray, 0x778899 }, + { c_HtmlNameLightSlateGrey, 0x778899 }, + { c_HtmlNameLightSteelBlue, 0xb0c4de }, + { c_HtmlNameLightYellow, 0xffffe0 }, + { c_HtmlNameLime, 0xff00 }, + { c_HtmlNameLimeGreen, 0x32cd32 }, + { c_HtmlNameLinen, 0xfaf0e6 }, + { c_HtmlNameMagenta, 0xff00ff }, + { c_HtmlNameMaroon, 0x800000 }, + { c_HtmlNameMediumAquamarine, 0x66cdaa }, + { c_HtmlNameMediumBlue, 0xcd }, + { c_HtmlNameMediumOrchid, 0xba55d3 }, + { c_HtmlNameMediumPurple, 0x9370d8 }, + { c_HtmlNameMediumSeagreen, 0x3cb371 }, + { c_HtmlNameMediumSlateBlue, 0x7b68ee }, + { c_HtmlNameMediumSpringGreen, 0xfa9a }, + { c_HtmlNameMediumTurquoise, 0x48d1cc }, + { c_HtmlNameMediumVioletRed, 0xc71585 }, + { c_HtmlNameMidnightBlue, 0x191970 }, + { c_HtmlNameMintCream, 0xf5fffa }, + { c_HtmlNameMistyRose, 0xffe4e1 }, + { c_HtmlNameMoccasin, 0xffe4b5 }, + { c_HtmlNameNavajoWhite, 0xffdead }, + { c_HtmlNameNavy, 0x80 }, + { c_HtmlNameOldLace, 0xfdf5e6 }, + { c_HtmlNameOlive, 0x808000 }, + { c_HtmlNameOliveDrab, 0x6b8e23 }, + { c_HtmlNameOrange, 0xffa500 }, + { c_HtmlNameOrangeRed, 0xff4500 }, + { c_HtmlNameOrchid, 0xda70d6 }, + { c_HtmlNamePaleGoldenrod, 0xeee8aa }, + { c_HtmlNamePaleGreen, 0x98fb98 }, + { c_HtmlNamePaleTurquoise, 0xafeeee }, + { c_HtmlNamePaleVioletRed, 0xd87093 }, + { c_HtmlNamePapayaWhip, 0xffefd5 }, + { c_HtmlNamePeachPuff, 0xffdab9 }, + { c_HtmlNamePeru, 0xcd853f }, + { c_HtmlNamePink, 0xffc0cb }, + { c_HtmlNamePlum, 0xdda0dd }, + { c_HtmlNamePowderBlue, 0xb0e0e6 }, + { c_HtmlNamePurple, 0x800080 }, + { c_HtmlNameRed, 0xff0000 }, + { c_HtmlNameRosyBrown, 0xbc8f8f }, + { c_HtmlNameRoyalBlue, 0x4169e1 }, + { c_HtmlNameSaddleBrown, 0x8b4513 }, + { c_HtmlNameSalmon, 0xfa8072 }, + { c_HtmlNameSandyBrown, 0xf4a460 }, + { c_HtmlNameSeaGreen, 0x2e8b57 }, + { c_HtmlNameSeaShell, 0xfff5ee }, + { c_HtmlNameSienna, 0xa0522d }, + { c_HtmlNameSilver, 0xc0c0c0 }, + { c_HtmlNameSkyBlue, 0x87ceeb }, + { c_HtmlNameSlateBlue, 0x6a5acd }, + { c_HtmlNameSlateGray, 0x708090 }, + { c_HtmlNameSlateGrey, 0x708090 }, + { c_HtmlNameSnow, 0xfffafa }, + { c_HtmlNameSpringGreen, 0xff7f }, + { c_HtmlNameSteelBlue, 0x4682b4 }, + { c_HtmlNameTan, 0xd2b48c }, + { c_HtmlNameTeal, 0x8080 }, + { c_HtmlNameThistle, 0xd8bfd8 }, + { c_HtmlNameTomato, 0xff6347 }, + { c_HtmlNameTurquoise, 0x40e0d0 }, + { c_HtmlNameViolet, 0xee82ee }, + { c_HtmlNameWheat, 0xf5deb3 }, + { c_HtmlNameWhite, 0xffffff }, + { c_HtmlNameWhiteSmoke, 0xf5f5f5 }, + { c_HtmlNameYellow, 0xffff00 }, + { c_HtmlNameYellowGreen, 0x9acd32 }, +}; + +const HtmlColorPair* HtmlColorNames::Pair(uint8_t index) +{ + return &c_ColorNames[index]; +} + +uint8_t HtmlColorNames::Count() +{ + return countof(c_ColorNames); +} diff --git a/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorShortNames.cpp b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorShortNames.cpp new file mode 100644 index 000000000..3c4e27c3e --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/HtmlColorShortNames.cpp @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- +HtmlShortColorNames provides a template class for access to the short name table + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "HtmlColor.h" +#include "HtmlColorNameStrings.h" + +static const HtmlColorPair c_ShortColorNames[] PROGMEM = { + { c_HtmlNameAqua, 0xffff }, + { c_HtmlNameBlack, 0x0 }, + { c_HtmlNameBlue, 0xff }, + { c_HtmlNameFuchsia, 0xff00ff }, + { c_HtmlNameGray, 0x808080 }, + { c_HtmlNameGreen, 0x8000 }, + { c_HtmlNameLime, 0xff00 }, + { c_HtmlNameMaroon, 0x800000 }, + { c_HtmlNameNavy, 0x80 }, + { c_HtmlNameOlive, 0x808000 }, + { c_HtmlNameOrange, 0xffa500 }, + { c_HtmlNamePurple, 0x800080 }, + { c_HtmlNameRed, 0xff0000 }, + { c_HtmlNameSilver, 0xc0c0c0 }, + { c_HtmlNameTeal, 0x8080 }, + { c_HtmlNameWhite, 0xffffff }, + { c_HtmlNameYellow, 0xffff00 }, +}; + + +const HtmlColorPair* HtmlShortColorNames::Pair(uint8_t index) +{ + return &c_ShortColorNames[index]; +} + +uint8_t HtmlShortColorNames::Count() +{ + return countof(c_ShortColorNames); +} \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/Layouts.h b/lib/NeoPixelBus-2.2.9/src/internal/Layouts.h new file mode 100644 index 000000000..0df0049d7 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/Layouts.h @@ -0,0 +1,426 @@ +#pragma once +/*------------------------------------------------------------------------- +Layout provides a collection of class objects that are used with NeoTopology +object. +They define the specific layout of pixels and do the math to change the 2d +cordinate space to 1d cordinate space + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +const uint16_t PixelIndex_OutOfBounds = 0xffff; + +//----------------------------------------------------------------------------- +// RowMajor +//----------------------------------------------------------------------------- + +class RowMajorLayout; +class RowMajor90Layout; +class RowMajor180Layout; +class RowMajor270Layout; + +class RowMajorTilePreference +{ +public: + typedef RowMajorLayout EvenRowEvenColumnLayout; + typedef RowMajor270Layout EvenRowOddColumnLayout; + typedef RowMajor90Layout OddRowEvenColumnLayout; + typedef RowMajor180Layout OddRowOddColumnLayout; +}; + +// layout example of 4x4 +// 00 01 02 03 +// 04 05 06 07 +// 08 09 10 11 +// 12 13 14 15 +// +class RowMajorLayout : public RowMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return x + y * width; + } +}; + +// layout example of 4x4 +// 12 08 04 00 +// 13 09 05 01 +// 14 10 06 02 +// 15 11 07 03 +// +class RowMajor90Layout : public RowMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return (width - 1 - x) * height + y; + } +}; + +// layout example of 4x4 +// 15 14 13 12 +// 11 10 09 08 +// 07 06 05 04 +// 03 02 01 00 +// +class RowMajor180Layout : public RowMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return (width - 1 - x) + (height - 1 - y) * width; + } +}; + +// layout example of 4x4 +// 03 07 11 15 +// 02 06 10 14 +// 01 05 09 13 +// 00 04 08 12 +// +class RowMajor270Layout : public RowMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return x * height + (height - 1 - y); + } +}; + + +//----------------------------------------------------------------------------- +// ColumnMajor +//----------------------------------------------------------------------------- + +class ColumnMajorLayout; +class ColumnMajor90Layout; +class ColumnMajor180Layout; +class ColumnMajor270Layout; + +class ColumnMajorTilePreference +{ +public: + typedef ColumnMajorLayout EvenRowEvenColumnLayout; + typedef ColumnMajor270Layout EvenRowOddColumnLayout; + typedef ColumnMajor90Layout OddRowEvenColumnLayout; + typedef ColumnMajor180Layout OddRowOddColumnLayout; +}; + +// layout example of 4x4 +// 00 04 08 12 +// 01 05 09 13 +// 02 06 10 14 +// 03 07 11 15 +// +class ColumnMajorLayout : public ColumnMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return x * height + y; + } +}; + +// layout example of 4x4 +// 03 02 01 00 +// 07 06 05 04 +// 11 10 09 08 +// 15 14 13 12 +// +class ColumnMajor90Layout : public ColumnMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return (width - 1 - x) + y * width; + } +}; + +// layout example of 4x4 +// 15 11 07 03 +// 14 10 06 02 +// 13 09 05 01 +// 12 08 04 00 +// +class ColumnMajor180Layout : public ColumnMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return (width - 1 - x) * height + (height - 1 - y); + } +}; + +// layout example of 4x4 +// 12 13 14 15 +// 08 09 10 11 +// 04 05 06 07 +// 00 01 02 03 +// +class ColumnMajor270Layout : public ColumnMajorTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + return x + (height - 1 - y) * width; + } +}; + + +//----------------------------------------------------------------------------- +// RowMajorAlternating +//----------------------------------------------------------------------------- + +class RowMajorAlternating270Layout; +class RowMajorAlternating90Layout; + +class RowMajorAlternatingTilePreference +{ +public: + typedef RowMajorAlternating270Layout EvenRowEvenColumnLayout; + typedef RowMajorAlternating270Layout EvenRowOddColumnLayout; + typedef RowMajorAlternating90Layout OddRowEvenColumnLayout; + typedef RowMajorAlternating90Layout OddRowOddColumnLayout; +}; + +// layout example of 4x4 +// 00 01 02 03 +// 07 06 05 04 +// 08 09 10 11 +// 15 14 13 12 +// +class RowMajorAlternatingLayout : public RowMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t index = y * width; + + if (y & 0x0001) + { + index += ((width - 1) - x); + } + else + { + index += x; + } + return index; + } +}; + +// layout example of 4x4 +// 15 08 07 00 +// 14 09 06 01 +// 13 10 05 02 +// 12 11 04 03 +// +class RowMajorAlternating90Layout : public RowMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t mx = ((width - 1) - x); + uint16_t index = mx * height; + + if (mx & 0x0001) + { + index += ((height - 1) - y); + } + else + { + index += y; + } + return index; + } +}; + +// layout example of 4x4 +// 12 13 14 15 +// 11 10 09 08 +// 04 05 06 07 +// 03 02 01 00 +// +class RowMajorAlternating180Layout : public RowMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t my = ((height - 1) - y); + uint16_t index = my * width; + + if (my & 0x0001) + { + index += x; + } + else + { + index += ((width - 1) - x); + } + return index; + } +}; + +// layout example of 4x4 +// 03 04 11 12 +// 02 05 10 13 +// 01 06 09 14 +// 00 07 08 15 +// +class RowMajorAlternating270Layout : public RowMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t index = x * height; + + if (x & 0x0001) + { + index += y; + } + else + { + index += ((height - 1) - y); + } + return index; + } +}; + + +//----------------------------------------------------------------------------- +// ColumnMajorAlternating +//----------------------------------------------------------------------------- + +class ColumnMajorAlternatingLayout; +class ColumnMajorAlternating180Layout; + +class ColumnMajorAlternatingTilePreference +{ +public: + typedef ColumnMajorAlternatingLayout EvenRowEvenColumnLayout; + typedef ColumnMajorAlternatingLayout EvenRowOddColumnLayout; + typedef ColumnMajorAlternating180Layout OddRowEvenColumnLayout; + typedef ColumnMajorAlternating180Layout OddRowOddColumnLayout; +}; + +// layout example of 4x4 +// 00 07 08 15 +// 01 06 09 14 +// 02 05 10 13 +// 03 04 11 12 +// +class ColumnMajorAlternatingLayout : public ColumnMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t index = x * height; + + if (x & 0x0001) + { + index += ((height - 1) - y); + } + else + { + index += y; + } + return index; + } +}; + +// layout example of 4x4 +// 03 02 01 00 +// 04 05 06 07 +// 11 10 09 08 +// 12 13 14 15 +// +class ColumnMajorAlternating90Layout : public ColumnMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t index = y * width; + + if (y & 0x0001) + { + index += x; + } + else + { + index += ((width - 1) - x); + } + return index; + } +}; + +// layout example of 4x4 +// 12 11 04 03 +// 13 10 05 02 +// 14 09 06 01 +// 15 08 07 00 +// +class ColumnMajorAlternating180Layout : public ColumnMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t mx = ((width - 1) - x); + uint16_t index = mx * height; + + if (mx & 0x0001) + { + index += y; + } + else + { + index += ((height - 1) - y); + } + return index; + } +}; + +// layout example of 4x4 +// 15 14 13 12 +// 08 09 10 11 +// 07 06 05 04 +// 00 01 02 03 +// +class ColumnMajorAlternating270Layout : public ColumnMajorAlternatingTilePreference +{ +public: + static uint16_t Map(uint16_t width, uint16_t height, uint16_t x, uint16_t y) + { + uint16_t my = ((height - 1) - y); + uint16_t index = my * width; + + if (my & 0x0001) + { + index += ((width - 1) - x); + } + else + { + index += x; + } + return index; + } +}; diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoArmMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoArmMethod.h new file mode 100644 index 000000000..34b42a853 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoArmMethod.h @@ -0,0 +1,697 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for ARM MCUs. +Teensy 3.0, 3.1, LC, Arduino Due + +Written by Michael C. Miller. +Some work taken from the Adafruit NeoPixel library. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. +The contents of this file were taken from the Adafruit NeoPixel library +and modified only to fit within individual calling functions. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#if defined(__arm__) + +template class NeoArmMethodBase +{ +public: + NeoArmMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) : + _pin(pin) + { + pinMode(pin, OUTPUT); + + _sizePixels = pixelCount * elementSize; + _pixels = (uint8_t*)malloc(_sizePixels); + memset(_pixels, 0, _sizePixels); + } + + ~NeoArmMethodBase() + { + pinMode(_pin, INPUT); + + free(_pixels); + } + + bool IsReadyToUpdate() const + { + uint32_t delta = micros() - _endTime; + + return (delta >= T_SPEED::ResetTimeUs); + } + + void Initialize() + { + digitalWrite(_pin, LOW); + + _endTime = micros(); + } + + void Update() + { + // Data latch = 50+ microsecond pause in the output stream. Rather than + // put a delay at the end of the function, the ending time is noted and + // the function will simply hold off (if needed) on issuing the + // subsequent round of data until the latch time has elapsed. This + // allows the mainline code to start generating the next frame of data + // rather than stalling for the latch. + while (!IsReadyToUpdate()) + { + yield(); // allows for system yield if needed + } + + noInterrupts(); // Need 100% focus on instruction timing + + T_SPEED::send_pixels(_pixels, _sizePixels, _pin); + + interrupts(); + + // save EOD time for latch on next call + _endTime = micros(); + } + + uint8_t* getPixels() const + { + return _pixels; + }; + + size_t getPixelsSize() const + { + return _sizePixels; + }; + +private: + uint32_t _endTime; // Latch timing reference + size_t _sizePixels; // Size of '_pixels' buffer below + uint8_t* _pixels; // Holds LED color values + uint8_t _pin; // output pin number +}; + + +#if defined(__MK20DX128__) || defined(__MK20DX256__) // Teensy 3.0 & 3.1 + +class NeoArmMk20dxSpeedPropsWs2813 +{ +public: + static const uint32_t CyclesT0h = (F_CPU / 4000000); + static const uint32_t CyclesT1h = (F_CPU / 1250000); + static const uint32_t Cycles = (F_CPU / 800000); + static const uint32_t ResetTimeUs = 250; +}; + +class NeoArmMk20dxSpeedProps800Kbps +{ +public: + static const uint32_t CyclesT0h = (F_CPU / 4000000); + static const uint32_t CyclesT1h = (F_CPU / 1250000); + static const uint32_t Cycles = (F_CPU / 800000); + static const uint32_t ResetTimeUs = 50; +}; + +class NeoArmMk20dxSpeedProps400Kbps +{ +public: + static const uint32_t CyclesT0h = (F_CPU / 2000000); + static const uint32_t CyclesT1h = (F_CPU / 833333); + static const uint32_t Cycles = (F_CPU / 400000); + static const uint32_t ResetTimeUs = 50; +}; + +template class NeoArmMk20dxSpeedBase +{ +public: + static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs; + + static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin) + { + uint8_t* p = pixels; + uint8_t* end = p + sizePixels; + uint8_t pix; + uint8_t mask; + + volatile uint8_t* set = portSetRegister(pin); + volatile uint8_t* clr = portClearRegister(pin); + + uint32_t cyc; + + ARM_DEMCR |= ARM_DEMCR_TRCENA; + ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; + + cyc = ARM_DWT_CYCCNT + T_SPEEDPROPS::Cycles; + while (p < end) + { + pix = *p++; + for (mask = 0x80; mask; mask >>= 1) + { + while (ARM_DWT_CYCCNT - cyc < T_SPEEDPROPS::Cycles); + + cyc = ARM_DWT_CYCCNT; + *set = 1; + if (pix & mask) + { + while (ARM_DWT_CYCCNT - cyc < T_SPEEDPROPS::CyclesT1h); + } + else + { + while (ARM_DWT_CYCCNT - cyc < T_SPEEDPROPS::CyclesT0h); + } + *clr = 1; + } + } + } +}; + +typedef NeoArmMethodBase> NeoArmWs2813Method; +typedef NeoArmMethodBase> NeoArm800KbpsMethod; +typedef NeoArmMethodBase> NeoArm400KbpsMethod; + +#elif defined(__MKL26Z64__) // Teensy-LC + +#if F_CPU == 48000000 + + + +class NeoArmMk26z64Speed800KbpsBase +{ +public: + static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin) + { + uint8_t* p = pixels; + uint8_t pix; + uint8_t count; + uint8_t dly; + uint8_t bitmask = digitalPinToBitMask(pin); + volatile uint8_t* reg = portSetRegister(pin); + uint32_t num = sizePixels; + + asm volatile( + "L%=_begin:" "\n\t" + "ldrb %[pix], [%[p], #0]" "\n\t" + "lsl %[pix], #24" "\n\t" + "movs %[count], #7" "\n\t" + "L%=_loop:" "\n\t" + "lsl %[pix], #1" "\n\t" + "bcs L%=_loop_one" "\n\t" + "L%=_loop_zero:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #4" "\n\t" + "L%=_loop_delay_T0H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T0H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #13" "\n\t" + "L%=_loop_delay_T0L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T0L" "\n\t" + "b L%=_next" "\n\t" + "L%=_loop_one:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #13" "\n\t" + "L%=_loop_delay_T1H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T1H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #4" "\n\t" + "L%=_loop_delay_T1L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_loop_delay_T1L" "\n\t" + "nop" "\n\t" + "L%=_next:" "\n\t" + "sub %[count], #1" "\n\t" + "bne L%=_loop" "\n\t" + "lsl %[pix], #1" "\n\t" + "bcs L%=_last_one" "\n\t" + "L%=_last_zero:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #4" "\n\t" + "L%=_last_delay_T0H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T0H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #10" "\n\t" + "L%=_last_delay_T0L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T0L" "\n\t" + "b L%=_repeat" "\n\t" + "L%=_last_one:" + "strb %[bitmask], [%[reg], #0]" "\n\t" + "movs %[dly], #13" "\n\t" + "L%=_last_delay_T1H:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T1H" "\n\t" + "strb %[bitmask], [%[reg], #4]" "\n\t" + "movs %[dly], #1" "\n\t" + "L%=_last_delay_T1L:" "\n\t" + "sub %[dly], #1" "\n\t" + "bne L%=_last_delay_T1L" "\n\t" + "nop" "\n\t" + "L%=_repeat:" "\n\t" + "add %[p], #1" "\n\t" + "sub %[num], #1" "\n\t" + "bne L%=_begin" "\n\t" + "L%=_done:" "\n\t" + : [p] "+r" (p), + [pix] "=&r" (pix), + [count] "=&r" (count), + [dly] "=&r" (dly), + [num] "+r" (num) + : [bitmask] "r" (bitmask), + [reg] "r" (reg) + ); + } +}; + +class NeoArmMk26z64SpeedWs2813 : public NeoArmMk26z64Speed800KbpsBase +{ +public: + const static uint32_t ResetTimeUs = 250; +}; + +class NeoArmMk26z64Speed800Kbps : public NeoArmMk26z64Speed800KbpsBase +{ +public: + const static uint32_t ResetTimeUs = 50; +} + +typedef NeoArmMethodBase NeoArmWs2813Method; +typedef NeoArmMethodBase NeoArm800KbpsMethod; + +#else +#error "Teensy-LC: Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz" +#endif // F_CPU == 48000000 + +#elif defined(__SAMD21G18A__) // Arduino Zero + + +class NeoArmSamd21g18aSpeedProps800KbpsBase +{ +public: + static void BitPreWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;"); + } + static void BitT1hWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop;"); + } + static void BitT0lWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop;"); + } + static void BitPostWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + } +}; + +class NeoArmSamd21g18aSpeedPropsWs2813 : public NeoArmSamd21g18aSpeedProps800KbpsBase +{ +public: + static const uint32_t ResetTimeUs = 250; +}; + +class NeoArmSamd21g18aSpeedProps800Kbps : public NeoArmSamd21g18aSpeedProps800KbpsBase +{ +public: + static const uint32_t ResetTimeUs = 50; +}; + + +class NeoArmSamd21g18aSpeedProps400Kbps +{ +public: + static void BitPreWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + } + static void BitT1hWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop;"); + } + static void BitT0lWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop;"); + } + static void BitPostWait() + { + asm("nop; nop; nop; nop; nop; nop; nop;"); + } + static const uint32_t ResetTimeUs = 50; +}; + +template class NeoArmSamd21g18aSpeedBase +{ +public: + static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs; + + static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin) + { + // Tried this with a timer/counter, couldn't quite get adequate + // resolution. So yay, you get a load of goofball NOPs... + uint8_t* ptr = pixels; + uint8_t* end = ptr + sizePixels;; + uint8_t p = *ptr++; + uint8_t bitMask = 0x80; + uint8_t portNum = g_APinDescription[pin].ulPort; + uint32_t pinMask = 1ul << g_APinDescription[pin].ulPin; + + volatile uint32_t* set = &(PORT->Group[portNum].OUTSET.reg); + volatile uint32_t* clr = &(PORT->Group[portNum].OUTCLR.reg); + + for (;;) + { + *set = pinMask; + T_SPEEDPROPS::BitPreWait(); + + if (p & bitMask) + { + T_SPEEDPROPS::BitT1hWait(); + *clr = pinMask; + } + else + { + *clr = pinMask; + T_SPEEDPROPS::BitT0lWait(); + } + if (bitMask >>= 1) + { + T_SPEEDPROPS::BitPostWait(); + } + else + { + if (ptr >= end) + { + break; + } + p = *ptr++; + bitMask = 0x80; + } + } + } +}; + +typedef NeoArmMethodBase> NeoArmWs2813Method; +typedef NeoArmMethodBase> NeoArm800KbpsMethod; +typedef NeoArmMethodBase> NeoArm400KbpsMethod; + +#elif defined (ARDUINO_STM32_FEATHER) // FEATHER WICED (120MHz) + +class NeoArmStm32SpeedProps800KbpsBase +{ +public: + static void BitT1hWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop;"); + } + static void BitT1lWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop;"); + } + static void BitT0hWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop;"); + } + static void BitT0lWait() + { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop;"); + } +}; + +class NeoArmStm32SpeedProps800Kbps : public NeoArmStm32SpeedProps800KbpsBase +{ +public: + static const uint32_t ResetTimeUs = 50; +}; + +class NeoArmStm32SpeedPropsWs2813 : public NeoArmStm32SpeedProps800KbpsBase +{ +public: + static const uint32_t ResetTimeUs = 250; +}; + +/* TODO - not found in Adafruit library +class NeoArmStm32SpeedProps400Kbps +{ +static void BitT1hWait() +{ +} +static void BitT1lWait() +{ +} +static void BitT0hWait() +{ +} +static void BitT0lWait() +{ +} +}; +*/ + +template class NeoArmStm32SpeedBase +{ +public: + static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs; + + static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin) + { + // Tried this with a timer/counter, couldn't quite get adequate + // resolution. So yay, you get a load of goofball NOPs... + + uint8_t* ptr = pixels; + uint8_t* end = ptr + sizePixels; + uint8_t p = *ptr++; + uint8_t bitMask = 0x80; + uint32_t pinMask = BIT(PIN_MAP[pin].gpio_bit); + + volatile uint16_t* set = &(PIN_MAP[pin].gpio_device->regs->BSRRL); + volatile uint16_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH); + + for (;;) + { + if (p & bitMask) + { + // ONE + // High 800ns + *set = pinMask; + T_SPEEDPROPS::BitT1hWait(); + // Low 450ns + *clr = pinMask; + T_SPEEDPROPS::BitT1lWait(); + } + else + { + // ZERO + // High 400ns + *set = pinMask; + T_SPEEDPROPS::BitT0hWait(); + // Low 850ns + *clr = pinMask; + T_SPEEDPROPS::BitT0lWait(); + } + if (bitMask >>= 1) + { + // Move on to the next pixel + asm("nop;"); + } + else + { + if (ptr >= end) + { + break; + } + + p = *ptr++; + bitMask = 0x80; + } + } + } +}; + +typedef NeoArmMethodBase> NeoArmWs2813Method; +typedef NeoArmMethodBase> NeoArm800KbpsMethod; + +#else // Other ARM architecture -- Presumed Arduino Due + + +#define ARM_OTHER_SCALE VARIANT_MCK / 2UL / 1000000UL +#define ARM_OTHER_INST (2UL * F_CPU / VARIANT_MCK) + +class NeoArmOtherSpeedPropsWs2813 +{ +public: + static const uint32_t CyclesT0h = ((uint32_t)(0.40 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t CyclesT1h = ((uint32_t)(0.80 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t Cycles = ((uint32_t)(1.25 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t ResetTimeUs = 250; +}; + +class NeoArmOtherSpeedProps800Kbps +{ +public: + static const uint32_t CyclesT0h = ((uint32_t)(0.40 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t CyclesT1h = ((uint32_t)(0.80 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t Cycles = ((uint32_t)(1.25 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t ResetTimeUs = 50; +}; + +class NeoArmOtherSpeedProps400Kbps +{ +public: + static const uint32_t CyclesT0h = ((uint32_t)(0.50 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t CyclesT1h = ((uint32_t)(1.20 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t Cycles = ((uint32_t)(2.50 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST)); + static const uint32_t ResetTimeUs = 50; +}; + +template class NeoArmOtherSpeedBase +{ +public: + static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs; + + static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin) + { + uint32_t pinMask; + uint32_t t; + Pio* port; + volatile WoReg* portSet; + volatile WoReg* portClear; + volatile WoReg* timeValue; + volatile WoReg* timeReset; + uint8_t* p; + uint8_t* end; + uint8_t pix; + uint8_t mask; + + pmc_set_writeprotect(false); + pmc_enable_periph_clk((uint32_t)TC3_IRQn); + + TC_Configure(TC1, 0, + TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1); + TC_Start(TC1, 0); + + pinMask = g_APinDescription[pin].ulPin; // Don't 'optimize' these into + port = g_APinDescription[pin].pPort; // declarations above. Want to + portSet = &(port->PIO_SODR); // burn a few cycles after + portClear = &(port->PIO_CODR); // starting timer to minimize + timeValue = &(TC1->TC_CHANNEL[0].TC_CV); // the initial 'while'. + timeReset = &(TC1->TC_CHANNEL[0].TC_CCR); + p = pixels; + end = p + sizePixels; + pix = *p++; + mask = 0x80; + + for (;;) + { + if (pix & mask) + { + t = T_SPEEDPROPS::CyclesT1h; + } + else + { + t = T_SPEEDPROPS::CyclesT0h; + } + + // wait for the end of the previous cycle + while (*timeValue < T_SPEEDPROPS::Cycles); + + *portSet = pinMask; + *timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG; + + while (*timeValue < t); + + *portClear = pinMask; + if (!(mask >>= 1)) + { + // This 'inside-out' loop logic utilizes + if (p >= end) + { + break; // idle time to minimize inter-byte delays. + } + pix = *p++; + mask = 0x80; + } + } + + // not really needed as the wait for latch does this and + // while (*timeValue < T_SPEEDPROPS::Cycles); // Wait for last bit + + TC_Stop(TC1, 0); + } +}; + +typedef NeoArmMethodBase> NeoArmWs2813Method; +typedef NeoArmMethodBase> NeoArm800KbpsMethod; +typedef NeoArmMethodBase> NeoArm400KbpsMethod; + +#endif + + +// Arm doesn't have alternatives methods yet, so only one to make the default +typedef NeoArmWs2813Method NeoWs2813Method; +typedef NeoArm800KbpsMethod Neo800KbpsMethod; +#ifdef NeoArm400KbpsMethod // this is needed due to missing 400Kbps for some platforms +typedef NeoArm400KbpsMethod Neo400KbpsMethod; +#endif + +#endif // defined(__arm__) + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoAvrMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoAvrMethod.h new file mode 100644 index 000000000..9843816f8 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoAvrMethod.h @@ -0,0 +1,200 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Atmel AVR. + +Written by Michael C. Miller. +Some work taken from the Adafruit NeoPixel library. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#ifdef ARDUINO_ARCH_AVR + +extern "C" +{ + void send_pixels_8mhz_800_PortD(uint8_t* pixels, size_t sizePixels, uint8_t pinMask); + void send_pixels_8mhz_800_PortB(uint8_t* pixels, size_t sizePixels, uint8_t pinMask); + void send_pixels_8mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask); + void send_pixels_12mhz_800_PortD(uint8_t* pixels, size_t sizePixels, uint8_t pinMask); + void send_pixels_12mhz_800_PortB(uint8_t* pixels, size_t sizePixels, uint8_t pinMask); + void send_pixels_12mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask); + void send_pixels_16mhz_800(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask); + void send_pixels_16mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask); +} + +class NeoAvrSpeed800KbpsBase +{ +public: + static void send_pixels(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask) + { +#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) // 8Mhz CPU +#ifdef PORTD // PORTD isn't present on ATtiny85, etc. + if (port == &PORTD) + send_pixels_8mhz_800_PortD(pixels, sizePixels, pinMask); + else if (port == &PORTB) +#endif // PORTD + send_pixels_8mhz_800_PortB(pixels, sizePixels, pinMask); + +#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) // 12Mhz CPU +#ifdef PORTD // PORTD + if (port == &PORTD) + send_pixels_12mhz_800_PortD(pixels, sizePixels, pinMask); + else if (port == &PORTB) +#endif // PORTD + send_pixels_12mhz_800_PortB(pixels, sizePixels, pinMask); + +#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) // 16Mhz CPU + send_pixels_16mhz_800(pixels, sizePixels, port, pinMask); +#else +#error "CPU SPEED NOT SUPPORTED" +#endif + } + +}; + +class NeoAvrSpeedWs2813 : public NeoAvrSpeed800KbpsBase +{ +public: + static const uint32_t ResetTimeUs = 250; +}; + +class NeoAvrSpeed800Kbps: public NeoAvrSpeed800KbpsBase +{ +public: + static const uint32_t ResetTimeUs = 50; +}; + +class NeoAvrSpeed400Kbps +{ +public: + static void send_pixels(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask) + { +#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) // 8Mhz CPU + send_pixels_8mhz_400(pixels, sizePixels, port, pinMask); + +#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) // 12Mhz CPU + send_pixels_12mhz_400(pixels, sizePixels, port, pinMask); + +#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) // 16Mhz CPU + send_pixels_16mhz_400(pixels, sizePixels, port, pinMask); +#else +#error "CPU SPEED NOT SUPPORTED" +#endif + } + static const uint32_t ResetTimeUs = 50; +}; + +template class NeoAvrMethodBase +{ +public: + NeoAvrMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) : + _pin(pin), + _port(NULL), + _pinMask(0) + { + pinMode(pin, OUTPUT); + + _sizePixels = pixelCount * elementSize; + _pixels = (uint8_t*)malloc(_sizePixels); + memset(_pixels, 0, _sizePixels); + + _port = portOutputRegister(digitalPinToPort(pin)); + _pinMask = digitalPinToBitMask(pin); + } + + ~NeoAvrMethodBase() + { + pinMode(_pin, INPUT); + + free(_pixels); + } + + bool IsReadyToUpdate() const + { + uint32_t delta = micros() - _endTime; + + return (delta >= T_SPEED::ResetTimeUs); + } + + void Initialize() + { + digitalWrite(_pin, LOW); + + _endTime = micros(); + } + + void Update() + { + // Data latch = 50+ microsecond pause in the output stream. Rather than + // put a delay at the end of the function, the ending time is noted and + // the function will simply hold off (if needed) on issuing the + // subsequent round of data until the latch time has elapsed. This + // allows the mainline code to start generating the next frame of data + // rather than stalling for the latch. + while (!IsReadyToUpdate()) + { +#if !defined(ARDUINO_TEEONARDU_LEO) && !defined(ARDUINO_TEEONARDU_FLORA) + yield(); // allows for system yield if needed +#endif + } + + noInterrupts(); // Need 100% focus on instruction timing + + T_SPEED::send_pixels(_pixels, _sizePixels, _port, _pinMask); + + interrupts(); + + // save EOD time for latch on next call + _endTime = micros(); + } + + uint8_t* getPixels() const + { + return _pixels; + }; + + size_t getPixelsSize() const + { + return _sizePixels; + }; + +private: + uint32_t _endTime; // Latch timing reference + size_t _sizePixels; // Size of '_pixels' buffer below + uint8_t* _pixels; // Holds LED color values + uint8_t _pin; // output pin number + + volatile uint8_t* _port; // Output PORT register + uint8_t _pinMask; // Output PORT bitmask +}; + +typedef NeoAvrMethodBase NeoAvrWs2813Method; +typedef NeoAvrMethodBase NeoAvr800KbpsMethod; +typedef NeoAvrMethodBase NeoAvr400KbpsMethod; + +// AVR doesn't have alternatives yet, so there is just the default +typedef NeoAvrWs2813Method NeoWs2813Method; +typedef NeoAvr800KbpsMethod Neo800KbpsMethod; +typedef NeoAvr400KbpsMethod Neo400KbpsMethod; + +#endif + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoBitmapFile.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoBitmapFile.h new file mode 100644 index 000000000..697967858 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoBitmapFile.h @@ -0,0 +1,351 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +const uint16_t c_BitmapFileId = 0x4d42; // "BM" + +#pragma pack(push, 2) +struct BitmapFileHeader +{ + uint16_t FileId; // only c_BitmapFileId is supported + uint32_t FileSize; + uint16_t Reserved0; + uint16_t Reserved1; + uint32_t PixelAddress; +}; + +struct BitmapInfoHeader +{ + uint32_t Size; + int32_t Width; + int32_t Height; + uint16_t Planes; // only support 1 + uint16_t BitsPerPixel; // only support 24 and 32 + uint32_t Compression; // only support BI_Rgb + uint32_t RawDateSize; // can be zero + int32_t XPpm; + int32_t YPpm; + uint32_t PaletteLength; + uint32_t ImportantColorCount; +}; +#pragma pack(pop) + +enum BmpCompression +{ + BI_Rgb, + BI_Rle8, + BI_Rle4, + BI_Bitfields, + BI_Jpeg, + BI_Png, + BI_AlphaBitfields, + BI_Cmyk = 11, + BI_CmykRle8, + BI_CmykRle4 +}; + +template class NeoBitmapFile +{ +public: + NeoBitmapFile() : + _fileAddressPixels(0), + _width(0), + _height(0), + _sizeRow(0), + _bottomToTop(true), + _bytesPerPixel(0) + { + } + + + ~NeoBitmapFile() + { + _file.close(); + } + + bool Begin(T_FILE_METHOD file) + { + if (_file) + { + _file.close(); + } + + if (!file || !file.seek(0)) + { + goto error; + } + + _file = file; + + BitmapFileHeader bmpHeader; + BitmapInfoHeader bmpInfoHeader; + size_t result; + + result = _file.read((uint8_t*)(&bmpHeader), sizeof(bmpHeader)); + + if (result != sizeof(bmpHeader) || + bmpHeader.FileId != c_BitmapFileId || + bmpHeader.FileSize != _file.size()) + { + goto error; + } + + result = _file.read((uint8_t*)(&bmpInfoHeader), sizeof(bmpInfoHeader)); + + if (result != sizeof(bmpInfoHeader) || + result != bmpInfoHeader.Size || + 1 != bmpInfoHeader.Planes || + BI_Rgb != bmpInfoHeader.Compression) + { + goto error; + } + + if (!(24 == bmpInfoHeader.BitsPerPixel || + 32 == bmpInfoHeader.BitsPerPixel)) + { + goto error; + } + + // save the interesting information + _width = abs(bmpInfoHeader.Width); + _height = abs(bmpInfoHeader.Height); + _fileAddressPixels = bmpHeader.PixelAddress; + // negative height means rows are top to bottom + _bottomToTop = (bmpInfoHeader.Height > 0); + // rows are 32 bit aligned so they may have padding on each row + _sizeRow = (bmpInfoHeader.BitsPerPixel * _width + 31) / 32 * 4; + _bytesPerPixel = bmpInfoHeader.BitsPerPixel / 8; + + return true; + + error: + _fileAddressPixels = 0; + _width = 0; + _height = 0; + _sizeRow = 0; + _bytesPerPixel = 0; + + _file.close(); + return false; + }; + + size_t PixelSize() const + { + return T_COLOR_FEATURE::PixelSize; + }; + + uint16_t PixelCount() const + { + return _width * _height; + }; + + uint16_t Width() const + { + return _width; + }; + + uint16_t Height() const + { + return _height; + }; + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(int16_t x, int16_t y) const + { + if (x < 0 || x >= _width || y < 0 || y >= _height) + { + // Pixel # is out of bounds, this will get converted to a + // color object type initialized to 0 (black) + return 0; + } + + typename T_COLOR_FEATURE::ColorObject color; + if (!seek(x, y) || !readPixel(&color)) + { + return 0; + } + + return color; + }; + + void Blt(NeoBufferContext destBuffer, + uint16_t indexPixel, + int16_t xSrc, + int16_t ySrc, + int16_t wSrc) + { + const uint16_t destPixelCount = destBuffer.PixelCount(); + typename T_COLOR_FEATURE::ColorObject color(0); + xSrc = constrainX(xSrc); + ySrc = constrainY(ySrc); + + if (seek(xSrc, ySrc)) + { + for (int16_t x = 0; x < wSrc && indexPixel < destPixelCount; x++, indexPixel++) + { + if (xSrc < _width) + { + if (readPixel(&color)) + { + xSrc++; + } + } + + T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexPixel, color); + } + } + } + + void Blt(NeoBufferContext destBuffer, + int16_t xDest, + int16_t yDest, + int16_t xSrc, + int16_t ySrc, + int16_t wSrc, + int16_t hSrc, + LayoutMapCallback layoutMap) + { + const uint16_t destPixelCount = destBuffer.PixelCount(); + typename T_COLOR_FEATURE::ColorObject color(0); + + for (int16_t y = 0; y < hSrc; y++) + { + int16_t xFile = constrainX(xSrc); + int16_t yFile = constrainY(ySrc + y); + + if (seek(xFile, yFile)) + { + for (int16_t x = 0; x < wSrc; x++) + { + if (xFile < _width) + { + if (readPixel(&color)) + { + xFile++; + } + } + + uint16_t indexDest = layoutMap(xDest + x, yDest + y); + + if (indexDest < destPixelCount) + { + T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexDest, color); + } + } + } + } + }; + + +private: + T_FILE_METHOD _file; + uint32_t _fileAddressPixels; + uint16_t _width; + uint16_t _height; + uint32_t _sizeRow; + uint8_t _bytesPerPixel; + bool _bottomToTop; + + int16_t constrainX(int16_t x) + { + if (x < 0) + { + x = 0; + } + else if (x >= _width) + { + x = _width - 1; + } + return x; + }; + + int16_t constrainY(int16_t y) + { + if (y < 0) + { + y = 0; + } + else if (y >= _height) + { + y = _height - 1; + } + return y; + }; + + bool seek(int16_t x, int16_t y) + { + if (_bottomToTop) + { + y = (_height - 1) - y; + } + + uint32_t pos = y * _sizeRow + x * _bytesPerPixel; + pos += _fileAddressPixels; + + return _file.seek(pos); + }; + + bool readPixel(RgbColor* color) + { + uint8_t bgr[4]; + int result; + + result = _file.read(bgr, _bytesPerPixel); + + if (result != _bytesPerPixel) + { + *color = 0; + return false; + } + + color->B = bgr[0]; + color->G = bgr[1]; + color->R = bgr[2]; + + return true; + }; + + bool readPixel(RgbwColor* color) + { + uint8_t bgr[4]; + int result; + + bgr[3] = 0; // init white channel as read maybe only 3 bytes + result = _file.read(bgr, _bytesPerPixel); + + if (result != _bytesPerPixel) + { + *color = 0; + return false; + } + + color->B = bgr[0]; + color->G = bgr[1]; + color->R = bgr[2]; + color->W = bgr[3]; + + return true; + }; +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoBuffer.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoBuffer.h new file mode 100644 index 000000000..86176c9b0 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoBuffer.h @@ -0,0 +1,154 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +template class NeoBuffer +{ +public: + NeoBuffer(uint16_t width, + uint16_t height, + PGM_VOID_P pixels) : + _method(width, height, pixels) + { + } + + operator NeoBufferContext() + { + return _method; + } + + uint16_t PixelCount() const + { + return _method.PixelCount(); + }; + + uint16_t Width() const + { + return _method.Width(); + }; + + uint16_t Height() const + { + return _method.Height(); + }; + + void SetPixelColor( + int16_t x, + int16_t y, + typename T_BUFFER_METHOD::ColorObject color) + { + _method.SetPixelColor(pixelIndex(x, y), color); + }; + + typename T_BUFFER_METHOD::ColorObject GetPixelColor( + int16_t x, + int16_t y) const + { + return _method.GetPixelColor(pixelIndex(x, y)); + }; + + void ClearTo(typename T_BUFFER_METHOD::ColorObject color) + { + _method.ClearTo(color); + }; + + void Blt(NeoBufferContext destBuffer, + uint16_t indexPixel) + { + uint16_t destPixelCount = destBuffer.PixelCount(); + // validate indexPixel + if (indexPixel >= destPixelCount) + { + return; + } + + // calc how many we can copy + uint16_t copyCount = destPixelCount - indexPixel; + uint16_t srcPixelCount = PixelCount(); + if (copyCount > srcPixelCount) + { + copyCount = srcPixelCount; + } + + uint8_t* pDest = T_BUFFER_METHOD::ColorFeature::getPixelAddress(destBuffer.Pixels, indexPixel); + _method.CopyPixels(pDest, _method.Pixels(), copyCount); + } + + void Blt(NeoBufferContext destBuffer, + int16_t xDest, + int16_t yDest, + int16_t xSrc, + int16_t ySrc, + int16_t wSrc, + int16_t hSrc, + LayoutMapCallback layoutMap) + { + uint16_t destPixelCount = destBuffer.PixelCount(); + + for (int16_t y = 0; y < hSrc; y++) + { + for (int16_t x = 0; x < wSrc; x++) + { + uint16_t indexDest = layoutMap(xDest + x, yDest + y); + + if (indexDest < destPixelCount) + { + const uint8_t* pSrc = T_BUFFER_METHOD::ColorFeature::getPixelAddress(_method.Pixels(), pixelIndex(xSrc + x, ySrc + y)); + uint8_t* pDest = T_BUFFER_METHOD::ColorFeature::getPixelAddress(destBuffer.Pixels, indexDest); + + _method.CopyPixels(pDest, pSrc, 1); + } + } + } + } + + void Blt(NeoBufferContext destBuffer, + int16_t xDest, + int16_t yDest, + LayoutMapCallback layoutMap) + { + Blt(destBuffer, xDest, yDest, 0, 0, Width(), Height(), layoutMap); + } + +private: + T_BUFFER_METHOD _method; + + uint16_t pixelIndex( + int16_t x, + int16_t y) + { + uint16_t result = PixelIndex_OutOfBounds; + + if (x >= 0 && + x < Width() && + y >= 0 && + y < Height()) + { + result = x + y * Width(); + } + return result; + } +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoBufferContext.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoBufferContext.h new file mode 100644 index 000000000..8b5734496 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoBufferContext.h @@ -0,0 +1,48 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +// This is used to allow a template classes that share common buffer concept to +// be able to pass that common information to functions +// The template classes just need to expose a conversion operator to this type +template struct NeoBufferContext +{ + NeoBufferContext(uint8_t* pixels, + size_t sizePixels) : + Pixels(pixels), + SizePixels(sizePixels) + { + } + + uint16_t PixelCount() const + { + return SizePixels / T_COLOR_FEATURE::PixelSize; + }; + + uint8_t* Pixels; + const size_t SizePixels; + +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoBufferMethods.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoBufferMethods.h new file mode 100644 index 000000000..4bd531ff3 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoBufferMethods.h @@ -0,0 +1,263 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + + +#ifdef ARDUINO_ARCH_AVR + +typedef uint16_t(*LayoutMapCallback)(int16_t x, int16_t y); + +#else + +#undef max +#undef min +#include +typedef std::function LayoutMapCallback; + +#endif + +template class NeoBufferMethod +{ +public: + NeoBufferMethod(uint16_t width, uint16_t height, PGM_VOID_P pixels = NULL) : + _width(width), + _height(height) + { + _pixels = (uint8_t*)malloc(PixelsSize()); + if (pixels) + { + // copy from progmem to initialize + T_COLOR_FEATURE::movePixelsInc_P(_pixels, pixels, PixelCount()); + } + } + + ~NeoBufferMethod() + { + free(_pixels); + } + + operator NeoBufferContext() + { + return NeoBufferContext(Pixels(), PixelsSize()); + } + + uint8_t* Pixels() const + { + return _pixels; + }; + + size_t PixelsSize() const + { + return PixelSize() * PixelCount(); + }; + + size_t PixelSize() const + { + return T_COLOR_FEATURE::PixelSize; + }; + + uint16_t PixelCount() const + { + return _width * _height; + }; + + uint16_t Width() const + { + return _width; + }; + + uint16_t Height() const + { + return _height; + }; + + void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color) + { + if (indexPixel < PixelCount()) + { + T_COLOR_FEATURE::applyPixelColor(_pixels, indexPixel, color); + } + }; + + void SetPixelColor(int16_t x, int16_t y, typename T_COLOR_FEATURE::ColorObject color) + { + if (x < 0 || x >= _width || y < 0 || y >= _height) + { + return; + } + + uint16_t indexPixel = x + y * _width; + T_COLOR_FEATURE::applyPixelColor(_pixels, indexPixel, color); + }; + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(uint16_t indexPixel) const + { + if (indexPixel >= PixelCount()) + { + // Pixel # is out of bounds, this will get converted to a + // color object type initialized to 0 (black) + return 0; + } + + return T_COLOR_FEATURE::retrievePixelColor(_pixels, indexPixel); + }; + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(int16_t x, int16_t y) const + { + if (x < 0 || x >= _width || y < 0 || y >= _height) + { + // Pixel # is out of bounds, this will get converted to a + // color object type initialized to 0 (black) + return 0; + } + + uint16_t indexPixel = x + y * _width; + return T_COLOR_FEATURE::retrievePixelColor(_pixels, indexPixel); + }; + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color) + { + uint8_t temp[T_COLOR_FEATURE::PixelSize]; + + T_COLOR_FEATURE::applyPixelColor(temp, 0, color); + + T_COLOR_FEATURE::replicatePixel(_pixels, temp, PixelCount()); + }; + + void CopyPixels(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + T_COLOR_FEATURE::movePixelsInc(pPixelDest, pPixelSrc, count); + } + + typedef typename T_COLOR_FEATURE::ColorObject ColorObject; + typedef T_COLOR_FEATURE ColorFeature; + +private: + const uint16_t _width; + const uint16_t _height; + uint8_t* _pixels; +}; + +template class NeoBufferProgmemMethod +{ +public: + NeoBufferProgmemMethod(uint16_t width, uint16_t height, PGM_VOID_P pixels) : + _width(width), + _height(height), + _pixels(pixels) + { + } + + operator NeoBufferContext() + { + return NeoBufferContext(Pixels(), PixelsSize()); + } + + uint8_t* Pixels() const + { + return (uint8_t*)_pixels; + }; + + size_t PixelsSize() const + { + return PixelSize() * PixelCount(); + }; + + size_t PixelSize() const + { + return T_COLOR_FEATURE::PixelSize; + }; + + uint16_t PixelCount() const + { + return _width * _height; + }; + + uint16_t Width() const + { + return _width; + }; + + uint16_t Height() const + { + return _height; + }; + + void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color) + { + // PROGMEM is read only, this will do nothing + }; + + void SetPixelColor(uint16_t x, uint16_t y, typename T_COLOR_FEATURE::ColorObject color) + { + // PROGMEM is read only, this will do nothing + }; + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(uint16_t indexPixel) const + { + if (indexPixel >= PixelCount()) + { + // Pixel # is out of bounds, this will get converted to a + // color object type initialized to 0 (black) + return 0; + } + + return T_COLOR_FEATURE::retrievePixelColor_P(_pixels, indexPixel); + }; + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(int16_t x, int16_t y) const + { + if (x < 0 || x >= _width || y < 0 || y >= _height) + { + // Pixel # is out of bounds, this will get converted to a + // color object type initialized to 0 (black) + return 0; + } + + uint16_t indexPixel = x + y * _width; + return T_COLOR_FEATURE::retrievePixelColor_P(_pixels, indexPixel); + }; + + void ClearTo(typename T_COLOR_FEATURE::ColorObject color) + { + // PROGMEM is read only, this will do nothing + }; + + void CopyPixels(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + T_COLOR_FEATURE::movePixelsInc_P(pPixelDest, pPixelSrc, count); + } + + typedef typename T_COLOR_FEATURE::ColorObject ColorObject; + typedef T_COLOR_FEATURE ColorFeature; + +private: + const uint16_t _width; + const uint16_t _height; + PGM_VOID_P _pixels; +}; + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoColorFeatures.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoColorFeatures.h new file mode 100644 index 000000000..9922363eb --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoColorFeatures.h @@ -0,0 +1,389 @@ +/*------------------------------------------------------------------------- +NeoPixelFeatures provides feature classes to describe color order and +color depth for NeoPixelBus template class + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +class Neo3Elements +{ +public: + static const size_t PixelSize = 3; + + static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + static const uint8_t* getPixelAddress(const uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + + static void replicatePixel(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + while (pPixelDest < pEnd) + { + *pPixelDest++ = pPixelSrc[0]; + *pPixelDest++ = pPixelSrc[1]; + *pPixelDest++ = pPixelSrc[2]; + } + } + + static void movePixelsInc(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + while (pPixelDest < pEnd) + { + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + *pPixelDest++ = *pPixelSrc++; + } + } + + static void movePixelsInc_P(uint8_t* pPixelDest, PGM_VOID_P pPixelSrc, uint16_t count) + { + uint8_t* pEnd = pPixelDest + (count * PixelSize); + const uint8_t* pSrc = (const uint8_t*)pPixelSrc; + while (pPixelDest < pEnd) + { + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + *pPixelDest++ = pgm_read_byte(pSrc++); + } + } + + static void movePixelsDec(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint8_t* pDestBack = pPixelDest + (count * PixelSize); + const uint8_t* pSrcBack = pPixelSrc + (count * PixelSize); + while (pDestBack > pPixelDest) + { + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + *--pDestBack = *--pSrcBack; + } + } + + typedef RgbColor ColorObject; +}; + +class Neo4Elements +{ +public: + static const size_t PixelSize = 4; + + static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + static const uint8_t* getPixelAddress(const uint8_t* pPixels, uint16_t indexPixel) + { + return pPixels + indexPixel * PixelSize; + } + + static void replicatePixel(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint32_t* pDest = (uint32_t*)pPixelDest; + const uint32_t* pSrc = (const uint32_t*)pPixelSrc; + + uint32_t* pEnd = pDest + count; + while (pDest < pEnd) + { + *pDest++ = *pSrc; + } + } + + static void movePixelsInc(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint32_t* pDest = (uint32_t*)pPixelDest; + const uint32_t* pSrc = (uint32_t*)pPixelSrc; + uint32_t* pEnd = pDest + count; + while (pDest < pEnd) + { + *pDest++ = *pSrc++; + } + } + + static void movePixelsInc_P(uint8_t* pPixelDest, PGM_VOID_P pPixelSrc, uint16_t count) + { + uint32_t* pDest = (uint32_t*)pPixelDest; + const uint32_t* pSrc = (const uint32_t*)pPixelSrc; + uint32_t* pEnd = pDest + count; + while (pDest < pEnd) + { + *pDest++ = pgm_read_dword(pSrc++); + } + } + + static void movePixelsDec(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count) + { + uint32_t* pDest = (uint32_t*)pPixelDest; + const uint32_t* pSrc = (uint32_t*)pPixelSrc; + uint32_t* pDestBack = pDest + count; + const uint32_t* pSrcBack = pSrc + count; + while (pDestBack > pDest) + { + *--pDestBack = *--pSrcBack; + } + } + + typedef RgbwColor ColorObject; +}; + +class NeoGrbFeature : public Neo3Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = color.G; + *p++ = color.R; + *p = color.B; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.G = *p++; + color.R = *p++; + color.B = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.G = pgm_read_byte(p++); + color.R = pgm_read_byte(p++); + color.B = pgm_read_byte(p); + + return color; + } + +}; + +class NeoGrbwFeature : public Neo4Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = color.G; + *p++ = color.R; + *p++ = color.B; + *p = color.W; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.G = *p++; + color.R = *p++; + color.B = *p++; + color.W = *p; + + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.G = pgm_read_byte(p++); + color.R = pgm_read_byte(p++); + color.B = pgm_read_byte(p++); + color.W = pgm_read_byte(p); + + return color; + } + +}; + +class NeoRgbwFeature : public Neo4Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = color.R; + *p++ = color.G; + *p++ = color.B; + *p = color.W; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.R = *p++; + color.G = *p++; + color.B = *p++; + color.W = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.R = pgm_read_byte(p++); + color.G = pgm_read_byte(p++); + color.B = pgm_read_byte(p++); + color.W = pgm_read_byte(p); + + return color; + } + +}; + +class NeoRgbFeature : public Neo3Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = color.R; + *p++ = color.G; + *p = color.B; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.R = *p++; + color.G = *p++; + color.B = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.R = pgm_read_byte(p++); + color.G = pgm_read_byte(p++); + color.B = pgm_read_byte(p); + + return color; + } + +}; + +class NeoBrgFeature : public Neo3Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = color.B; + *p++ = color.R; + *p = color.G; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.B = *p++; + color.R = *p++; + color.G = *p; + + return color; + } + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.B = pgm_read_byte(p++); + color.R = pgm_read_byte(p++); + color.G = pgm_read_byte(p); + + return color; + } + +}; + +class NeoRbgFeature : public Neo3Elements +{ +public: + static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color) + { + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + *p++ = color.R; + *p++ = color.B; + *p = color.G; + } + + static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel) + { + ColorObject color; + uint8_t* p = getPixelAddress(pPixels, indexPixel); + + color.R = *p++; + color.B = *p++; + color.G = *p; + + return color; + } + + + static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel) + { + ColorObject color; + const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel); + + color.R = pgm_read_byte(p++); + color.B = pgm_read_byte(p++); + color.G = pgm_read_byte(p); + + return color; + } + +}; diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoDib.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoDib.h new file mode 100644 index 000000000..ef69ce6f7 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoDib.h @@ -0,0 +1,161 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +class NeoShaderBase +{ +public: + NeoShaderBase() : + _state(0) + { + } + + bool IsDirty() const + { + return (_state & NEO_DIRTY); + }; + + void Dirty() + { + _state |= NEO_DIRTY; + }; + + void ResetDirty() + { + _state &= ~NEO_DIRTY; + }; + +protected: + uint8_t _state; // internal state +}; + +template class NeoDib +{ +public: + NeoDib(uint16_t countPixels) : + _countPixels(countPixels), + _state(0) + { + _pixels = (T_COLOR_OBJECT*)malloc(PixelsSize()); + ResetDirty(); + } + + ~NeoDib() + { + free((uint8_t*)_pixels); + } + + T_COLOR_OBJECT* Pixels() const + { + return _pixels; + }; + + uint16_t PixelCount() const + { + return _countPixels; + }; + + size_t PixelsSize() const + { + return _countPixels * PixelSize(); + }; + + size_t PixelSize() const + { + return sizeof(T_COLOR_OBJECT); + }; + + void SetPixelColor( + uint16_t indexPixel, + T_COLOR_OBJECT color) + { + if (indexPixel < PixelCount()) + { + _pixels[indexPixel] = color; + Dirty(); + } + }; + + T_COLOR_OBJECT GetPixelColor( + uint16_t indexPixel) const + { + if (indexPixel >= PixelCount()) + { + return 0; + } + return _pixels[indexPixel]; + }; + + void ClearTo(T_COLOR_OBJECT color) + { + for (uint16_t pixel = 0; pixel < PixelCount(); pixel++) + { + _pixels[pixel] = color; + } + Dirty(); + }; + + template void Render(NeoBufferContext destBuffer, T_SHADER& shader) + { + if (IsDirty() || shader.IsDirty()) + { + uint16_t countPixels = destBuffer.PixelCount(); + if (countPixels > _countPixels) + { + countPixels = _countPixels; + } + + for (uint16_t indexPixel = 0; indexPixel < countPixels; indexPixel++) + { + T_COLOR_OBJECT color = shader.Apply(indexPixel, _pixels[indexPixel]); + T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexPixel, color); + } + + shader.ResetDirty(); + ResetDirty(); + } + } + + bool IsDirty() const + { + return (_state & NEO_DIRTY); + }; + + void Dirty() + { + _state |= NEO_DIRTY; + }; + + void ResetDirty() + { + _state &= ~NEO_DIRTY; + }; + +private: + const uint16_t _countPixels; // Number of RGB LEDs in strip + T_COLOR_OBJECT* _pixels; + uint8_t _state; // internal state +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoEase.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoEase.h new file mode 100644 index 000000000..eaa50239f --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoEase.h @@ -0,0 +1,224 @@ +/*------------------------------------------------------------------------- +NeoEase provides animation curve equations for animation support. + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#ifdef ARDUINO_ARCH_AVR + +typedef float(*AnimEaseFunction)(float unitValue); + +#else + +#undef max +#undef min +#include +typedef std::function AnimEaseFunction; + +#endif + +class NeoEase +{ +public: + static float Linear(float unitValue) + { + return unitValue; + } + + static float QuadraticIn(float unitValue) + { + return unitValue * unitValue; + } + + static float QuadraticOut(float unitValue) + { + return (-unitValue * (unitValue - 2.0f)); + } + + static float QuadraticInOut(float unitValue) + { + unitValue *= 2.0f; + if (unitValue < 1.0f) + { + return (0.5f * unitValue * unitValue); + } + else + { + unitValue -= 1.0f; + return (-0.5f * (unitValue * (unitValue - 2.0f) - 1.0f)); + } + } + + static float CubicIn(float unitValue) + { + return (unitValue * unitValue * unitValue); + } + + static float CubicOut(float unitValue) + { + unitValue -= 1.0f; + return (unitValue * unitValue * unitValue + 1); + } + + static float CubicInOut(float unitValue) + { + unitValue *= 2.0f; + if (unitValue < 1.0f) + { + return (0.5f * unitValue * unitValue * unitValue); + } + else + { + unitValue -= 2.0f; + return (0.5f * (unitValue * unitValue * unitValue + 2.0f)); + } + } + + static float QuarticIn(float unitValue) + { + return (unitValue * unitValue * unitValue * unitValue); + } + + static float QuarticOut(float unitValue) + { + unitValue -= 1.0f; + return -(unitValue * unitValue * unitValue * unitValue - 1); + } + + static float QuarticInOut(float unitValue) + { + unitValue *= 2.0f; + if (unitValue < 1.0f) + { + return (0.5f * unitValue * unitValue * unitValue * unitValue); + } + else + { + unitValue -= 2.0f; + return (-0.5f * (unitValue * unitValue * unitValue * unitValue - 2.0f)); + } + } + + static float QuinticIn(float unitValue) + { + return (unitValue * unitValue * unitValue * unitValue * unitValue); + } + + static float QuinticOut(float unitValue) + { + unitValue -= 1.0f; + return (unitValue * unitValue * unitValue * unitValue * unitValue + 1.0f); + } + + static float QuinticInOut(float unitValue) + { + unitValue *= 2.0f; + if (unitValue < 1.0f) + { + return (0.5f * unitValue * unitValue * unitValue * unitValue * unitValue); + } + else + { + unitValue -= 2.0f; + return (0.5f * (unitValue * unitValue * unitValue * unitValue * unitValue + 2.0f)); + } + } + + static float SinusoidalIn(float unitValue) + { + return (-cos(unitValue * HALF_PI) + 1.0f); + } + + static float SinusoidalOut(float unitValue) + { + return (sin(unitValue * HALF_PI)); + } + + static float SinusoidalInOut(float unitValue) + { + return -0.5 * (cos(PI * unitValue) - 1.0f); + } + + static float ExponentialIn(float unitValue) + { + return (pow(2, 10.0f * (unitValue - 1.0f))); + } + + static float ExponentialOut(float unitValue) + { + return (-pow(2, -10.0f * unitValue) + 1.0f); + } + + static float ExponentialInOut(float unitValue) + { + unitValue *= 2.0f; + if (unitValue < 1.0f) + { + return (0.5f * pow(2, 10.0f * (unitValue - 1.0f))); + } + else + { + unitValue -= 1.0f; + return (0.5f * (-pow(2, -10.0f * unitValue) + 2.0f)); + } + } + + static float CircularIn(float unitValue) + { + if (unitValue == 1.0f) + { + return 1.0f; + } + else + { + return (-(sqrt(1.0f - unitValue * unitValue) - 1.0f)); + } + } + + static float CircularOut(float unitValue) + { + unitValue -= 1.0f; + return (sqrt(1.0f - unitValue * unitValue)); + } + + static float CircularInOut(float unitValue) + { + unitValue *= 2.0f; + if (unitValue < 1.0f) + { + return (-0.5f * (sqrt(1.0f - unitValue * unitValue) - 1)); + } + else + { + unitValue -= 2.0f; + return (0.5f * (sqrt(1.0f - unitValue * unitValue) + 1.0f)); + } + } + + static float Gamma(float unitValue) + { + return pow(unitValue, 1.0f / 0.45f); + } +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h new file mode 100644 index 000000000..af11e1a7a --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266DmaMethod.h @@ -0,0 +1,382 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Esp8266. + + +Written by Michael C. Miller. +Thanks to g3gg0.de for porting the initial DMA support which lead to this. +Thanks to github/cnlohr for the original work on DMA support, which opend +all our minds to a better way (located at https://github.com/cnlohr/esp8266ws2812i2s). + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#ifdef ARDUINO_ARCH_ESP8266 + +extern "C" +{ +#include "Arduino.h" +#include "osapi.h" +#include "ets_sys.h" + +#include "i2s_reg.h" +#include "i2s.h" +#include "eagle_soc.h" +#include "esp8266_peri.h" +#include "slc_register.h" + +#include "osapi.h" +#include "ets_sys.h" +#include "user_interface.h" + + void rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id, uint32_t reg_add, uint32_t Msb, uint32_t Lsb, uint32_t indata); +} + +struct slc_queue_item +{ + uint32 blocksize : 12; + uint32 datalen : 12; + uint32 unused : 5; + uint32 sub_sof : 1; + uint32 eof : 1; + uint32 owner : 1; + uint32 buf_ptr; + uint32 next_link_ptr; +}; + +class NeoEsp8266DmaSpeedWs2813 +{ +public: + const static uint32_t I2sClockDivisor = 3; + const static uint32_t I2sBaseClockDivisor = 16; + const static uint32_t ResetTimeUs = 250; +}; + +class NeoEsp8266DmaSpeed800Kbps +{ +public: + const static uint32_t I2sClockDivisor = 3; + const static uint32_t I2sBaseClockDivisor = 16; + const static uint32_t ResetTimeUs = 50; +}; + +class NeoEsp8266DmaSpeed400Kbps +{ +public: + const static uint32_t I2sClockDivisor = 6; + const static uint32_t I2sBaseClockDivisor = 16; + const static uint32_t ResetTimeUs = 50; +}; + +enum NeoDmaState +{ + NeoDmaState_Idle, + NeoDmaState_Pending, + NeoDmaState_Sending, +}; +const uint16_t c_maxDmaBlockSize = 4095; +const uint16_t c_dmaBytesPerPixelBytes = 4; +const uint8_t c_I2sPin = 3; // due to I2S hardware, the pin used is restricted to this + +template class NeoEsp8266DmaMethodBase +{ +public: + NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize) + { + uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize; + + _pixelsSize = pixelCount * elementSize; + _i2sBufferSize = pixelCount * dmaPixelSize; + + _pixels = (uint8_t*)malloc(_pixelsSize); + memset(_pixels, 0x00, _pixelsSize); + + _i2sBuffer = (uint8_t*)malloc(_i2sBufferSize); + memset(_i2sBuffer, 0x00, _i2sBufferSize); + + memset(_i2sZeroes, 0x00, sizeof(_i2sZeroes)); + + _is2BufMaxBlockSize = (c_maxDmaBlockSize / dmaPixelSize) * dmaPixelSize; + + _i2sBufDescCount = (_i2sBufferSize / _is2BufMaxBlockSize) + 1 + 2; // need two more for state/latch blocks + _i2sBufDesc = (slc_queue_item*)malloc(_i2sBufDescCount * sizeof(slc_queue_item)); + + s_this = this; // store this for the ISR + } + + NeoEsp8266DmaMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) : NeoEsp8266DmaMethodBase(pixelCount, elementSize) + { + } + + ~NeoEsp8266DmaMethodBase() + { + StopDma(); + + free(_pixels); + free(_i2sBuffer); + free(_i2sBufDesc); + } + + bool IsReadyToUpdate() const + { + return (_dmaState == NeoDmaState_Idle); + } + + void Initialize() + { + StopDma(); + _dmaState = NeoDmaState_Sending; // start off sending empty buffer + + uint8_t* is2Buffer = _i2sBuffer; + uint32_t is2BufferSize = _i2sBufferSize; + uint16_t indexDesc; + + // prepare main data block decriptors that point into our one static dma buffer + for (indexDesc = 0; indexDesc < (_i2sBufDescCount - 2); indexDesc++) + { + uint32_t blockSize = (is2BufferSize > _is2BufMaxBlockSize) ? _is2BufMaxBlockSize : is2BufferSize; + + _i2sBufDesc[indexDesc].owner = 1; + _i2sBufDesc[indexDesc].eof = 0; // no need to trigger interrupt generally + _i2sBufDesc[indexDesc].sub_sof = 0; + _i2sBufDesc[indexDesc].datalen = blockSize; + _i2sBufDesc[indexDesc].blocksize = blockSize; + _i2sBufDesc[indexDesc].buf_ptr = (uint32_t)is2Buffer; + _i2sBufDesc[indexDesc].unused = 0; + _i2sBufDesc[indexDesc].next_link_ptr = (uint32_t)&(_i2sBufDesc[indexDesc + 1]); + + is2Buffer += blockSize; + is2BufferSize -= blockSize; + } + + // prepare the two state/latch descriptors + for (; indexDesc < _i2sBufDescCount; indexDesc++) + { + _i2sBufDesc[indexDesc].owner = 1; + _i2sBufDesc[indexDesc].eof = 0; // no need to trigger interrupt generally + _i2sBufDesc[indexDesc].sub_sof = 0; + _i2sBufDesc[indexDesc].datalen = sizeof(_i2sZeroes); + _i2sBufDesc[indexDesc].blocksize = sizeof(_i2sZeroes); + _i2sBufDesc[indexDesc].buf_ptr = (uint32_t)_i2sZeroes; + _i2sBufDesc[indexDesc].unused = 0; + _i2sBufDesc[indexDesc].next_link_ptr = (uint32_t)&(_i2sBufDesc[indexDesc + 1]); + } + + // the first state block will trigger the interrupt + _i2sBufDesc[indexDesc - 2].eof = 1; + // the last state block will loop to the first state block by defualt + _i2sBufDesc[indexDesc - 1].next_link_ptr = (uint32_t)&(_i2sBufDesc[indexDesc - 2]); + + // setup the rest of i2s DMA + // + ETS_SLC_INTR_DISABLE(); + SLCC0 |= SLCRXLR | SLCTXLR; + SLCC0 &= ~(SLCRXLR | SLCTXLR); + SLCIC = 0xFFFFFFFF; + + // Configure DMA + SLCC0 &= ~(SLCMM << SLCM); // clear DMA MODE + SLCC0 |= (1 << SLCM); // set DMA MODE to 1 + SLCRXDC |= SLCBINR | SLCBTNR; // enable INFOR_NO_REPLACE and TOKEN_NO_REPLACE + SLCRXDC &= ~(SLCBRXFE | SLCBRXEM | SLCBRXFM); // disable RX_FILL, RX_EOF_MODE and RX_FILL_MODE + + // Feed DMA the 1st buffer desc addr + // To send data to the I2S subsystem, counter-intuitively we use the RXLINK part, not the TXLINK as you might + // expect. The TXLINK part still needs a valid DMA descriptor, even if it's unused: the DMA engine will throw + // an error at us otherwise. Just feed it any random descriptor. + SLCTXL &= ~(SLCTXLAM << SLCTXLA); // clear TX descriptor address + SLCTXL |= (uint32)&(_i2sBufDesc[_i2sBufDescCount-1]) << SLCTXLA; // set TX descriptor address. any random desc is OK, we don't use TX but it needs to be valid + SLCRXL &= ~(SLCRXLAM << SLCRXLA); // clear RX descriptor address + SLCRXL |= (uint32)_i2sBufDesc << SLCRXLA; // set RX descriptor address + + ETS_SLC_INTR_ATTACH(i2s_slc_isr, NULL); + SLCIE = SLCIRXEOF; // Enable only for RX EOF interrupt + + ETS_SLC_INTR_ENABLE(); + + //Start transmission + SLCTXL |= SLCTXLS; + SLCRXL |= SLCRXLS; + + pinMode(c_I2sPin, FUNCTION_1); // I2S0_DATA + + I2S_CLK_ENABLE(); + I2SIC = 0x3F; + I2SIE = 0; + + //Reset I2S + I2SC &= ~(I2SRST); + I2SC |= I2SRST; + I2SC &= ~(I2SRST); + + I2SFC &= ~(I2SDE | (I2STXFMM << I2STXFM) | (I2SRXFMM << I2SRXFM)); // Set RX/TX FIFO_MOD=0 and disable DMA (FIFO only) + I2SFC |= I2SDE; //Enable DMA + I2SCC &= ~((I2STXCMM << I2STXCM) | (I2SRXCMM << I2SRXCM)); // Set RX/TX CHAN_MOD=0 + + // set the rate + uint32_t i2s_clock_div = T_SPEED::I2sClockDivisor & I2SCDM; + uint8_t i2s_bck_div = T_SPEED::I2sBaseClockDivisor & I2SBDM; + + //!trans master, !bits mod, rece slave mod, rece msb shift, right first, msb right + I2SC &= ~(I2STSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD)); + I2SC |= I2SRF | I2SMR | I2SRSM | I2SRMS | (i2s_bck_div << I2SBD) | (i2s_clock_div << I2SCD); + + I2SC |= I2STXS; // Start transmission + } + + void ICACHE_RAM_ATTR Update() + { + // wait for not actively sending data + while (_dmaState != NeoDmaState_Idle) + { + yield(); + } + FillBuffers(); + + // toggle state so the ISR reacts + _dmaState = NeoDmaState_Pending; + } + + uint8_t* getPixels() const + { + return _pixels; + }; + + size_t getPixelsSize() const + { + return _pixelsSize; + } + +private: + static NeoEsp8266DmaMethodBase* s_this; // for the ISR + + size_t _pixelsSize; // Size of '_pixels' buffer + uint8_t* _pixels; // Holds LED color values + + uint32_t _i2sBufferSize; // total size of _i2sBuffer + uint8_t* _i2sBuffer; // holds the DMA buffer that is referenced by _i2sBufDesc + + // normally 24 bytes creates the minimum 50us latch per spec, but + // with the new logic, this latch is used to space between three states + // buffer size = (24 * (speed / 50)) / 3 + uint8_t _i2sZeroes[(24L * (T_SPEED::ResetTimeUs / 50L)) / 3L]; + + slc_queue_item* _i2sBufDesc; // dma block descriptors + uint16_t _i2sBufDescCount; // count of block descriptors in _i2sBufDesc + uint16_t _is2BufMaxBlockSize; // max size based on size of a pixel of a single block + + volatile NeoDmaState _dmaState; + + // This routine is called as soon as the DMA routine has something to tell us. All we + // handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose + // descriptor has the 'EOF' field set to 1. + // in the case of this code, the second to last state descriptor + volatile static void ICACHE_RAM_ATTR i2s_slc_isr(void) + { + uint32_t slc_intr_status = SLCIS; + + SLCIC = 0xFFFFFFFF; + + if (slc_intr_status & SLCIRXEOF) + { + ETS_SLC_INTR_DISABLE(); + + switch (s_this->_dmaState) + { + case NeoDmaState_Idle: + break; + + case NeoDmaState_Pending: + { + slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA; + + // data block has pending data waiting to send, prepare it + // point last state block to top + (finished_item + 1)->next_link_ptr = (uint32_t)(s_this->_i2sBufDesc); + + s_this->_dmaState = NeoDmaState_Sending; + } + break; + + case NeoDmaState_Sending: + { + slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA; + + // the data block had actual data sent + // point last state block to first state block thus + // just looping and not sending the data blocks + (finished_item + 1)->next_link_ptr = (uint32_t)(finished_item); + + s_this->_dmaState = NeoDmaState_Idle; + } + break; + } + + + ETS_SLC_INTR_ENABLE(); + } + } + + void FillBuffers() + { + const uint16_t bitpatterns[16] = + { + 0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110, + 0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110, + 0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110, + 0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110, + }; + + uint16_t* pDma = (uint16_t*)_i2sBuffer; + uint8_t* pPixelsEnd = _pixels + _pixelsSize; + for (uint8_t* pPixel = _pixels; pPixel < pPixelsEnd; pPixel++) + { + *(pDma++) = bitpatterns[((*pPixel) & 0x0f)]; + *(pDma++) = bitpatterns[((*pPixel) >> 4) & 0x0f]; + } + } + + void StopDma() + { + ETS_SLC_INTR_DISABLE(); + SLCIC = 0xFFFFFFFF; + SLCIE = 0; + SLCTXL &= ~(SLCTXLAM << SLCTXLA); // clear TX descriptor address + SLCRXL &= ~(SLCRXLAM << SLCRXLA); // clear RX descriptor address + + pinMode(c_I2sPin, INPUT); + } +}; + +template +NeoEsp8266DmaMethodBase* NeoEsp8266DmaMethodBase::s_this; + +typedef NeoEsp8266DmaMethodBase NeoEsp8266DmaWs2813Method; +typedef NeoEsp8266DmaMethodBase NeoEsp8266Dma800KbpsMethod; +typedef NeoEsp8266DmaMethodBase NeoEsp8266Dma400KbpsMethod; + +// Dma method is the default method for Esp8266 +typedef NeoEsp8266DmaWs2813Method NeoWs2813Method; +typedef NeoEsp8266Dma800KbpsMethod Neo800KbpsMethod; +typedef NeoEsp8266Dma400KbpsMethod Neo400KbpsMethod; + +#endif \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.cpp b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.cpp new file mode 100644 index 000000000..7bfc3e0d2 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.cpp @@ -0,0 +1,216 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Esp8266 UART hardware + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#ifdef ARDUINO_ARCH_ESP8266 +#include "NeoEsp8266UartMethod.h" +#include +extern "C" +{ + #include + #include + #include + #include +} + +#define UART1 1 +#define UART1_INV_MASK (0x3f << 19) + +// Gets the number of bytes waiting in the TX FIFO of UART1 +static inline uint8_t getUartTxFifoLength() +{ + return (U1S >> USTXC) & 0xff; +} + +// Append a byte to the TX FIFO of UART1 +// You must ensure the TX FIFO isn't full +static inline void enqueue(uint8_t byte) +{ + U1F = byte; +} + +static const uint8_t* esp8266_uart1_async_buf; +static const uint8_t* esp8266_uart1_async_buf_end; + +NeoEsp8266Uart::NeoEsp8266Uart(uint16_t pixelCount, size_t elementSize) +{ + _sizePixels = pixelCount * elementSize; + _pixels = (uint8_t*)malloc(_sizePixels); + memset(_pixels, 0x00, _sizePixels); +} + +NeoEsp8266Uart::~NeoEsp8266Uart() +{ + // Wait until the TX fifo is empty. This way we avoid broken frames + // when destroying & creating a NeoPixelBus to change its length. + while (getUartTxFifoLength() > 0) + { + yield(); + } + + free(_pixels); +} + +void NeoEsp8266Uart::InitializeUart(uint32_t uartBaud) +{ + // Configure the serial line with 1 start bit (0), 6 data bits and 1 stop bit (1) + Serial1.begin(uartBaud, SERIAL_6N1, SERIAL_TX_ONLY); + + // Invert the TX voltage associated with logic level so: + // - A logic level 0 will generate a Vcc signal + // - A logic level 1 will generate a Gnd signal + CLEAR_PERI_REG_MASK(UART_CONF0(UART1), UART1_INV_MASK); + SET_PERI_REG_MASK(UART_CONF0(UART1), (BIT(22))); +} + +void NeoEsp8266Uart::UpdateUart() +{ + // Since the UART can finish sending queued bytes in the FIFO in + // the background, instead of waiting for the FIFO to flush + // we annotate the start time of the frame so we can calculate + // when it will finish. + _startTime = micros(); + + // Then keep filling the FIFO until done + const uint8_t* ptr = _pixels; + const uint8_t* end = ptr + _sizePixels; + while (ptr != end) + { + ptr = FillUartFifo(ptr, end); + } +} + +const uint8_t* ICACHE_RAM_ATTR NeoEsp8266Uart::FillUartFifo(const uint8_t* pixels, const uint8_t* end) +{ + // Remember: UARTs send less significant bit (LSB) first so + // pushing ABCDEF byte will generate a 0FEDCBA1 signal, + // including a LOW(0) start & a HIGH(1) stop bits. + // Also, we have configured UART to invert logic levels, so: + const uint8_t _uartData[4] = { + 0b110111, // On wire: 1 000 100 0 [Neopixel reads 00] + 0b000111, // On wire: 1 000 111 0 [Neopixel reads 01] + 0b110100, // On wire: 1 110 100 0 [Neopixel reads 10] + 0b000100, // On wire: 1 110 111 0 [NeoPixel reads 11] + }; + uint8_t avail = (UART_TX_FIFO_SIZE - getUartTxFifoLength()) / 4; + if (end - pixels > avail) + { + end = pixels + avail; + } + while (pixels < end) + { + uint8_t subpix = *pixels++; + enqueue(_uartData[(subpix >> 6) & 0x3]); + enqueue(_uartData[(subpix >> 4) & 0x3]); + enqueue(_uartData[(subpix >> 2) & 0x3]); + enqueue(_uartData[ subpix & 0x3]); + } + return pixels; +} + +NeoEsp8266AsyncUart::NeoEsp8266AsyncUart(uint16_t pixelCount, size_t elementSize) + : NeoEsp8266Uart(pixelCount, elementSize) +{ + _asyncPixels = (uint8_t*)malloc(_sizePixels); +} + +NeoEsp8266AsyncUart::~NeoEsp8266AsyncUart() +{ + // Remember: the UART interrupt can be sending data from _asyncPixels in the background + while (esp8266_uart1_async_buf != esp8266_uart1_async_buf_end) + { + yield(); + } + free(_asyncPixels); +} + +void ICACHE_RAM_ATTR NeoEsp8266AsyncUart::InitializeUart(uint32_t uartBaud) +{ + NeoEsp8266Uart::InitializeUart(uartBaud); + + // Disable all interrupts + ETS_UART_INTR_DISABLE(); + + // Clear the RX & TX FIFOS + SET_PERI_REG_MASK(UART_CONF0(UART1), UART_RXFIFO_RST | UART_TXFIFO_RST); + CLEAR_PERI_REG_MASK(UART_CONF0(UART1), UART_RXFIFO_RST | UART_TXFIFO_RST); + + // Set the interrupt handler + ETS_UART_INTR_ATTACH(IntrHandler, NULL); + + // Set tx fifo trigger. 80 bytes gives us 200 microsecs to refill the FIFO + WRITE_PERI_REG(UART_CONF1(UART1), 80 << UART_TXFIFO_EMPTY_THRHD_S); + + // Disable RX & TX interrupts. It is enabled by uart.c in the SDK + CLEAR_PERI_REG_MASK(UART_INT_ENA(UART1), UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA); + + // Clear all pending interrupts in UART1 + WRITE_PERI_REG(UART_INT_CLR(UART1), 0xffff); + + // Reenable interrupts + ETS_UART_INTR_ENABLE(); +} + +void NeoEsp8266AsyncUart::UpdateUart() +{ + // Instruct ESP8266 hardware uart1 to send the pixels asynchronously + esp8266_uart1_async_buf = _pixels; + esp8266_uart1_async_buf_end = _pixels + _sizePixels; + SET_PERI_REG_MASK(UART_INT_ENA(1), UART_TXFIFO_EMPTY_INT_ENA); + + // Annotate when we started to send bytes, so we can calculate when we are ready to send again + _startTime = micros(); + + // Copy the pixels to the idle buffer and swap them + memcpy(_asyncPixels, _pixels, _sizePixels); + std::swap(_asyncPixels, _pixels); +} + +void ICACHE_RAM_ATTR NeoEsp8266AsyncUart::IntrHandler(void* param) +{ + // Interrupt handler is shared between UART0 & UART1 + if (READ_PERI_REG(UART_INT_ST(UART1))) //any UART1 stuff + { + // Fill the FIFO with new data + esp8266_uart1_async_buf = FillUartFifo(esp8266_uart1_async_buf, esp8266_uart1_async_buf_end); + // Disable TX interrupt when done + if (esp8266_uart1_async_buf == esp8266_uart1_async_buf_end) + { + CLEAR_PERI_REG_MASK(UART_INT_ENA(UART1), UART_TXFIFO_EMPTY_INT_ENA); + } + // Clear all interrupts flags (just in case) + WRITE_PERI_REG(UART_INT_CLR(UART1), 0xffff); + } + + if (READ_PERI_REG(UART_INT_ST(UART0))) + { + // TODO: gdbstub uses the interrupt of UART0, but there is no way to call its + // interrupt handler gdbstub_uart_hdlr since it's static. + WRITE_PERI_REG(UART_INT_CLR(UART0), 0xffff); + } +} + +#endif + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.h new file mode 100644 index 000000000..a92d56631 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoEsp8266UartMethod.h @@ -0,0 +1,178 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Esp8266 UART hardware + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#ifdef ARDUINO_ARCH_ESP8266 +#include + +// NeoEsp8266Uart contains all the low level details that doesn't +// depend on the transmission speed, and therefore, it isn't a template +class NeoEsp8266Uart +{ +protected: + NeoEsp8266Uart(uint16_t pixelCount, size_t elementSize); + + ~NeoEsp8266Uart(); + + void InitializeUart(uint32_t uartBaud); + + void UpdateUart(); + + static const uint8_t* ICACHE_RAM_ATTR FillUartFifo(const uint8_t* pixels, const uint8_t* end); + + size_t _sizePixels; // Size of '_pixels' buffer below + uint8_t* _pixels; // Holds LED color values + uint32_t _startTime; // Microsecond count when last update started +}; + +// NeoEsp8266AsyncUart handles all transmission asynchronously using interrupts +// +// This UART controller uses two buffers that are swapped in every call to +// NeoPixelBus.Show(). One buffer contains the data that is being sent +// asynchronosly and another buffer contains the data that will be send +// in the next call to NeoPixelBus.Show(). +// +// Therefore, the result of NeoPixelBus.Pixels() is invalidated after +// every call to NeoPixelBus.Show() and must not be cached. +class NeoEsp8266AsyncUart: public NeoEsp8266Uart +{ +protected: + NeoEsp8266AsyncUart(uint16_t pixelCount, size_t elementSize); + + ~NeoEsp8266AsyncUart(); + + void InitializeUart(uint32_t uartBaud); + + void UpdateUart(); + +private: + static void ICACHE_RAM_ATTR IntrHandler(void* param); + + uint8_t* _asyncPixels; // Holds a copy of LED color values taken when UpdateUart began +}; + +// NeoEsp8266UartSpeedWs2813 contains the timing constants used to get NeoPixelBus running with the Ws2813 +class NeoEsp8266UartSpeedWs2813 +{ +public: + static const uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed + static const uint32_t UartBaud = 3200000; // 800mhz, 4 serial bytes per NeoByte + static const uint32_t ResetTimeUs = 250; // us between data send bursts to reset for next update +}; + +// NeoEsp8266UartSpeed800Kbps contains the timing constant used to get NeoPixelBus running at 800Khz +class NeoEsp8266UartSpeed800Kbps +{ +public: + static const uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed + static const uint32_t UartBaud = 3200000; // 800mhz, 4 serial bytes per NeoByte + static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update +}; + +// NeoEsp8266UartSpeed800Kbps contains the timing constant used to get NeoPixelBus running at 400Khz +class NeoEsp8266UartSpeed400Kbps +{ +public: + static const uint32_t ByteSendTimeUs = 20; // us it takes to send a single pixel element at 400khz speed + static const uint32_t UartBaud = 1600000; // 400mhz, 4 serial bytes per NeoByte + static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update +}; + +// NeoEsp8266UartMethodBase is a light shell arround NeoEsp8266Uart or NeoEsp8266AsyncUart that +// implements the methods needed to operate as a NeoPixelBus method. +template +class NeoEsp8266UartMethodBase: public T_BASE +{ +public: + NeoEsp8266UartMethodBase(uint16_t pixelCount, size_t elementSize) + : T_BASE(pixelCount, elementSize) + { + } + NeoEsp8266UartMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) + : T_BASE(pixelCount, elementSize) + { + } + + bool IsReadyToUpdate() const + { + uint32_t delta = micros() - this->_startTime; + return delta >= getPixelTime() + T_SPEED::ResetTimeUs; + } + + void Initialize() + { + this->InitializeUart(T_SPEED::UartBaud); + + // Inverting logic levels can generate a phantom bit in the led strip bus + // We need to delay 50+ microseconds the output stream to force a data + // latch and discard this bit. Otherwise, that bit would be prepended to + // the first frame corrupting it. + this->_startTime = micros() - getPixelTime(); + } + + void Update() + { + // Data latch = 50+ microsecond pause in the output stream. Rather than + // put a delay at the end of the function, the ending time is noted and + // the function will simply hold off (if needed) on issuing the + // subsequent round of data until the latch time has elapsed. This + // allows the mainline code to start generating the next frame of data + // rather than stalling for the latch. + while (!this->IsReadyToUpdate()) + { + yield(); + } + this->UpdateUart(); + } + + uint8_t* getPixels() const + { + return this->_pixels; + }; + + size_t getPixelsSize() const + { + return this->_sizePixels; + }; + +private: + uint32_t getPixelTime() const + { + return (T_SPEED::ByteSendTimeUs * this->_sizePixels); + }; +}; + +typedef NeoEsp8266UartMethodBase NeoEsp8266UartWs2813Method; +typedef NeoEsp8266UartMethodBase NeoEsp8266Uart800KbpsMethod; +typedef NeoEsp8266UartMethodBase NeoEsp8266Uart400KbpsMethod; + +typedef NeoEsp8266UartMethodBase NeoEsp8266AsyncUartWs2813Method; +typedef NeoEsp8266UartMethodBase NeoEsp8266AsyncUart800KbpsMethod; +typedef NeoEsp8266UartMethodBase NeoEsp8266AsyncUart400KbpsMethod; + +#endif + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoEspBitBangMethod.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoEspBitBangMethod.h new file mode 100644 index 000000000..499f1c3da --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoEspBitBangMethod.h @@ -0,0 +1,166 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Esp8266 and Esp32 + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) + +// ESP32 doesn't define ICACHE_RAM_ATTR +#ifndef ICACHE_RAM_ATTR +#define ICACHE_RAM_ATTR IRAM_ATTR +#endif + +// for esp8266, due to linker overriding the ICACHE_RAM_ATTR for cpp files, these methods are +// moved into a C file so the attribute will be applied correctly +// >> this may have been fixed and is no longer a requirement << +extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin); +extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin); + +class NeoEspBitBangSpeedWs2813 +{ +public: + static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin) + { + bitbang_send_pixels_800(pixels, end, pin); + } + static const uint32_t ResetTimeUs = 250; +}; + +class NeoEspBitBangSpeed800Kbps +{ +public: + static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin) + { + bitbang_send_pixels_800(pixels, end, pin); + } + static const uint32_t ResetTimeUs = 50; +}; + +class NeoEspBitBangSpeed400Kbps +{ +public: + static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin) + { + bitbang_send_pixels_400(pixels, end, pin); + } + static const uint32_t ResetTimeUs = 50; +}; + +template class NeoEspBitBangMethodBase +{ +public: + NeoEspBitBangMethodBase(uint8_t pin, uint16_t pixelCount, size_t elementSize) : + _pin(pin) + { + pinMode(pin, OUTPUT); + + _sizePixels = pixelCount * elementSize; + _pixels = (uint8_t*)malloc(_sizePixels); + memset(_pixels, 0, _sizePixels); + } + + ~NeoEspBitBangMethodBase() + { + pinMode(_pin, INPUT); + + free(_pixels); + } + + bool IsReadyToUpdate() const + { + uint32_t delta = micros() - _endTime; + + return (delta >= T_SPEED::ResetTimeUs); + } + + void Initialize() + { + digitalWrite(_pin, LOW); + + _endTime = micros(); + } + + void Update() + { + // Data latch = 50+ microsecond pause in the output stream. Rather than + // put a delay at the end of the function, the ending time is noted and + // the function will simply hold off (if needed) on issuing the + // subsequent round of data until the latch time has elapsed. This + // allows the mainline code to start generating the next frame of data + // rather than stalling for the latch. + while (!IsReadyToUpdate()) + { + yield(); // allows for system yield if needed + } + + noInterrupts(); // Need 100% focus on instruction timing + + T_SPEED::send_pixels(_pixels, _pixels + _sizePixels, _pin); + + interrupts(); + + // save EOD time for latch on next call + _endTime = micros(); + } + + uint8_t* getPixels() const + { + return _pixels; + }; + + size_t getPixelsSize() const + { + return _sizePixels; + }; + +private: + uint32_t _endTime; // Latch timing reference + size_t _sizePixels; // Size of '_pixels' buffer below + uint8_t* _pixels; // Holds LED color values + uint8_t _pin; // output pin number +}; + + +#if defined(ARDUINO_ARCH_ESP32) + +typedef NeoEspBitBangMethodBase NeoEsp32BitBangWs2813Method; +typedef NeoEspBitBangMethodBase NeoEsp32BitBang800KbpsMethod; +typedef NeoEspBitBangMethodBase NeoEsp32BitBang400KbpsMethod; + +// Bitbang method is the default method for Esp32 +typedef NeoEsp32BitBangWs2813Method NeoWs2813Method; +typedef NeoEsp32BitBang800KbpsMethod Neo800KbpsMethod; +typedef NeoEsp32BitBang400KbpsMethod Neo400KbpsMethod; + +#else + +typedef NeoEspBitBangMethodBase NeoEsp8266BitBangWs2813Method; +typedef NeoEspBitBangMethodBase NeoEsp8266BitBang800KbpsMethod; +typedef NeoEspBitBangMethodBase NeoEsp8266BitBang400KbpsMethod; + +#endif + +#endif \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.cpp b/lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.cpp new file mode 100644 index 000000000..f33cbfbd9 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.cpp @@ -0,0 +1,50 @@ +/*------------------------------------------------------------------------- +NeoPixelGamma class is used to correct RGB colors for human eye gamma levels + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include +#include "RgbColor.h" +#include "RgbwColor.h" +#include "NeoEase.h" +#include "NeoGamma.h" + +const uint8_t NeoGammaTableMethod::_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, + 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, + 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, + 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, + 29, 30, 30, 31, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, + 41, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, + 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 86, 87, 88, 89, + 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, + 112, 113, 115, 116, 118, 119, 121, 122, 123, 125, 126, 128, 130, 131, 133, 134, + 136, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 155, 157, 159, 160, + 162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 187, 189, + 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, + 223, 225, 227, 229, 231, 233, 235, 238, 240, 242, 244, 246, 248, 251, 253, 255 +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.h new file mode 100644 index 000000000..9b94e2419 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoGamma.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------- +NeoPixelGamma class is used to correct RGB colors for human eye gamma levels + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +// NeoGammaEquationMethod uses no memory but is slower than NeoGammaTableMethod +class NeoGammaEquationMethod +{ +public: + static uint8_t Correct(uint8_t value) + { + return static_cast(255.0f * NeoEase::Gamma(value / 255.0f) + 0.5f); + } +}; + +// NeoGammaTableMethod uses 256 bytes of memory, but is significantly faster +class NeoGammaTableMethod +{ +public: + static uint8_t Correct(uint8_t value) + { + return _table[value]; + } + +private: + static const uint8_t _table[256]; +}; + + +// use one of the method classes above as a converter for this template class +template class NeoGamma +{ +public: + RgbColor Correct(const RgbColor& original) + { + return RgbColor(T_METHOD::Correct(original.R), + T_METHOD::Correct(original.G), + T_METHOD::Correct(original.B)); + } + + RgbwColor Correct(const RgbwColor& original) + { + return RgbwColor(T_METHOD::Correct(original.R), + T_METHOD::Correct(original.G), + T_METHOD::Correct(original.B), + T_METHOD::Correct(original.W) ); + } +}; + + + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoHueBlend.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoHueBlend.h new file mode 100644 index 000000000..d77a58fb1 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoHueBlend.h @@ -0,0 +1,118 @@ +/*------------------------------------------------------------------------- +NeoHueBlend provides method objects that can be directly consumed by +blend template functions in HslColor and HsbColor + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +class NeoHueBlendBase +{ +protected: + static float FixWrap(float value) + { + if (value < 0.0f) + { + value += 1.0f; + } + else if (value > 1.0f) + { + value -= 1.0f; + } + return value; + } +}; + +class NeoHueBlendShortestDistance : NeoHueBlendBase +{ +public: + static float HueBlend(float left, float right, float progress) + { + float delta = right - left; + float base = left; + if (delta > 0.5f) + { + base = right; + delta = 1.0f - delta; + progress = 1.0f - progress; + } + else if (delta < -0.5f) + { + delta = 1.0f + delta; + } + return FixWrap(base + (delta) * progress); + }; +}; + +class NeoHueBlendLongestDistance : NeoHueBlendBase +{ +public: + static float HueBlend(float left, float right, float progress) + { + float delta = right - left; + float base = left; + if (delta < 0.5f && delta >= 0.0f) + { + base = right; + delta = 1.0f - delta; + progress = 1.0f - progress; + } + else if (delta > -0.5f && delta < 0.0f) + { + delta = 1.0f + delta; + } + return FixWrap(base + delta * progress); + }; +}; + +class NeoHueBlendClockwiseDirection : NeoHueBlendBase +{ +public: + static float HueBlend(float left, float right, float progress) + { + float delta = right - left; + float base = left; + if (delta < 0.0f) + { + delta = 1.0f + delta; + } + + return FixWrap(base + delta * progress); + }; +}; + +class NeoHueBlendCounterClockwiseDirection : NeoHueBlendBase +{ +public: + static float HueBlend(float left, float right, float progress) + { + float delta = right - left; + float base = left; + if (delta > 0.0f) + { + delta = delta - 1.0f; + } + + return FixWrap(base + delta * progress); + }; +}; diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoMosaic.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoMosaic.h new file mode 100644 index 000000000..551bd5377 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoMosaic.h @@ -0,0 +1,191 @@ +#pragma once + +/*------------------------------------------------------------------------- +Mosiac provides a mapping feature of a 2d cordinate to linear 1d cordinate +It is used to map tiles of matricies of NeoPixels to a index on the NeoPixelBus +where the the matricies use a set of prefered topology and the tiles of +those matricies use the RowMajorAlternating layout + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + + +//----------------------------------------------------------------------------- +// class NeoMosaic +// Complex Tile layout class that reduces distance of the interconnects between +// the tiles by using different rotations of the layout at specific locations +// +// T_LAYOUT = the layout used for matrix panel (rotation is ignored) +// +// NOTE: The tiles in the mosaic are always laid out using RowMajorAlternating +// +//----------------------------------------------------------------------------- + +template class NeoMosaic +{ +public: + NeoMosaic(uint16_t topoWidth, uint16_t topoHeight, + uint16_t mosaicWidth, uint16_t mosaicHeight) : + _topoWidth(topoWidth), + _topoHeight(topoHeight), + _mosaicWidth(mosaicWidth), + _mosaicHeight(mosaicHeight) + { + } + + uint16_t Map(int16_t x, int16_t y) const + { + uint16_t totalWidth = getWidth(); + uint16_t totalHeight = getHeight(); + + if (x >= totalWidth) + { + x = totalWidth - 1; + } + else if (x < 0) + { + x = 0; + } + + if (y >= totalHeight) + { + y = totalHeight - 1; + } + else if (y < 0) + { + y = 0; + } + + uint16_t localIndex; + uint16_t tileOffset; + + calculate(x, y, &localIndex, &tileOffset); + + return localIndex + tileOffset; + } + + uint16_t MapProbe(int16_t x, int16_t y) const + { + uint16_t totalWidth = getWidth(); + uint16_t totalHeight = getHeight(); + + if (x < 0 || x >= totalWidth || y < 0 || y >= totalHeight) + { + return totalWidth * totalHeight; // count, out of bounds + } + + uint16_t localIndex; + uint16_t tileOffset; + + calculate(x, y, &localIndex, &tileOffset); + + return localIndex + tileOffset; + } + + NeoTopologyHint TopologyHint(int16_t x, int16_t y) const + { + uint16_t totalWidth = getWidth(); + uint16_t totalHeight = getHeight(); + + if (x < 0 || x >= totalWidth || y < 0 || y >= totalHeight) + { + return NeoTopologyHint_OutOfBounds; + } + + uint16_t localIndex; + uint16_t tileOffset; + NeoTopologyHint result; + + calculate(x, y, &localIndex, &tileOffset); + + if (localIndex == 0) + { + result = NeoTopologyHint_FirstOnPanel; + } + else if (localIndex == (_topoWidth * _topoHeight - 1)) + { + result = NeoTopologyHint_LastOnPanel; + } + else + { + result = NeoTopologyHint_InPanel; + } + + return result; + } + + uint16_t getWidth() const + { + return _topoWidth * _mosaicWidth; + } + + uint16_t getHeight() const + { + return _topoHeight * _mosaicHeight; + } + +private: + const uint16_t _topoWidth; + const uint16_t _topoHeight; + const uint16_t _mosaicWidth; + const uint16_t _mosaicHeight; + + void calculate(uint16_t x, uint16_t y, uint16_t* pLocalIndex, uint16_t* pTileOffset) const + { + uint16_t tileX = x / _topoWidth; + uint16_t topoX = x % _topoWidth; + + uint16_t tileY = y / _topoHeight; + uint16_t topoY = y % _topoHeight; + + *pTileOffset = RowMajorAlternatingLayout::Map(_mosaicWidth, + _mosaicHeight, + tileX, + tileY) * _topoWidth * _topoHeight; + + if (tileX & 0x0001) + { + // odd columns + if (tileY & 0x0001) + { + *pLocalIndex = T_LAYOUT::OddRowOddColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY); + } + else + { + *pLocalIndex = T_LAYOUT::EvenRowOddColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY); + } + } + else + { + // even columns + if (tileY & 0x0001) + { + *pLocalIndex = T_LAYOUT::OddRowEvenColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY); + } + else + { + *pLocalIndex = T_LAYOUT::EvenRowEvenColumnLayout::Map(_topoWidth, _topoHeight, topoX, topoY); + } + } + } +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAnimator.cpp b/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAnimator.cpp new file mode 100644 index 000000000..db51a5d4a --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAnimator.cpp @@ -0,0 +1,166 @@ +/*------------------------------------------------------------------------- +NeoPixelAnimator provides animation timing support. + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "NeoPixelAnimator.h" + +NeoPixelAnimator::NeoPixelAnimator(uint16_t countAnimations, uint16_t timeScale) : + _countAnimations(countAnimations), + _animationLastTick(0), + _activeAnimations(0), + _isRunning(true) +{ + setTimeScale(timeScale); + _animations = new AnimationContext[_countAnimations]; +} + +NeoPixelAnimator::~NeoPixelAnimator() +{ + delete[] _animations; +} + +bool NeoPixelAnimator::NextAvailableAnimation(uint16_t* indexAvailable, uint16_t indexStart) +{ + if (indexStart >= _countAnimations) + { + // last one + indexStart = _countAnimations - 1; + } + + uint16_t next = indexStart; + + do + { + if (!IsAnimationActive(next)) + { + if (indexAvailable) + { + *indexAvailable = next; + } + return true; + } + next = (next + 1) % _countAnimations; + } while (next != indexStart); + return false; +} + +void NeoPixelAnimator::StartAnimation(uint16_t indexAnimation, + uint16_t duration, + AnimUpdateCallback animUpdate) +{ + if (indexAnimation >= _countAnimations || animUpdate == NULL) + { + return; + } + + if (_activeAnimations == 0) + { + _animationLastTick = millis(); + } + + StopAnimation(indexAnimation); + + // all animations must have at least non zero duration, otherwise + // they are considered stopped + if (duration == 0) + { + duration = 1; + } + + _animations[indexAnimation].StartAnimation(duration, animUpdate); + + _activeAnimations++; +} + +void NeoPixelAnimator::StopAnimation(uint16_t indexAnimation) +{ + if (indexAnimation >= _countAnimations) + { + return; + } + + if (IsAnimationActive(indexAnimation)) + { + _activeAnimations--; + _animations[indexAnimation].StopAnimation(); + } +} + +void NeoPixelAnimator::StopAll() +{ + for (uint16_t indexAnimation = 0; indexAnimation < _countAnimations; ++indexAnimation) + { + _animations[indexAnimation].StopAnimation(); + } + _activeAnimations = 0; +} + + +void NeoPixelAnimator::UpdateAnimations() +{ + if (_isRunning) + { + uint32_t currentTick = millis(); + uint32_t delta = currentTick - _animationLastTick; + + if (delta >= _timeScale) + { + AnimationContext* pAnim; + + delta /= _timeScale; // scale delta into animation time + + for (uint16_t iAnim = 0; iAnim < _countAnimations; iAnim++) + { + pAnim = &_animations[iAnim]; + AnimUpdateCallback fnUpdate = pAnim->_fnCallback; + AnimationParam param; + + param.index = iAnim; + + if (pAnim->_remaining > delta) + { + param.state = (pAnim->_remaining == pAnim->_duration) ? AnimationState_Started : AnimationState_Progress; + param.progress = (float)(pAnim->_duration - pAnim->_remaining) / (float)pAnim->_duration; + + fnUpdate(param); + + pAnim->_remaining -= delta; + } + else if (pAnim->_remaining > 0) + { + param.state = AnimationState_Completed; + param.progress = 1.0f; + + _activeAnimations--; + pAnim->StopAnimation(); + + fnUpdate(param); + } + } + + _animationLastTick = currentTick; + } + } +} diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAvr.c b/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAvr.c new file mode 100644 index 000000000..3d057e27a --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelAvr.c @@ -0,0 +1,648 @@ +/*------------------------------------------------------------------------- +Arduino library to control a wide variety of WS2811- and WS2812-based RGB +LED devices such as Adafruit FLORA RGB Smart Pixels and NeoPixel strips. +Currently handles 400 and 800 KHz bitstreams on 8, 12 and 16 MHz ATmega +MCUs, with LEDs wired for various color orders. 8 MHz MCUs provide +output on PORTB and PORTD, while 16 MHz chips can handle most output pins +(possible exception with upper PORT registers on the Arduino Mega). + +Written by Phil Burgess / Paint Your Dragon for Adafruit Industries, +contributions by PJRC, Michael Miller and other members of the open +source community. + +Adafruit invests time and resources providing this open source code, +please support Adafruit and open-source hardware by purchasing products +from Adafruit! + +------------------------------------------------------------------------- +The contents of this file were taken from the Adafruit NeoPixel library +and modified only to fit within individual calling functions. + +NeoPixel is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixel is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +// must also check for arm due to Teensy incorrectly having ARDUINO_ARCH_AVR set +#if defined(ARDUINO_ARCH_AVR) && !defined(__arm__) + +#include + +// Hand-tuned assembly code issues data to the LED drivers at a specific +// rate. There's separate code for different CPU speeds (8, 12, 16 MHz) +// for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The +// datastream timing for the LED drivers allows a little wiggle room each +// way (listed in the datasheets), so the conditions for compiling each +// case are set up for a range of frequencies rather than just the exact +// 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on +// devices (e.g. 16.5 MHz DigiSpark). The ranges were arrived at based +// on the datasheet figures and have not been extensively tested outside +// the canonical 8/12/16 MHz speeds; there's no guarantee these will work +// close to the extremes (or possibly they could be pushed further). +// Keep in mind only one CPU speed case actually gets compiled; the +// resulting program isn't as massive as it might look from source here. + +#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL) // 8Mhz CPU + +#ifdef PORTD // PORTD isn't present on ATtiny85, etc. +void send_pixels_8mhz_800_PortD(uint8_t* pixels, size_t sizePixels, uint8_t pinMask) +{ + volatile size_t i = sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + volatile uint8_t n1; + volatile n2 = 0; // First, next bits out + + // Squeezing an 800 KHz stream out of an 8 MHz chip requires code + // specific to each PORT register. At present this is only written + // to work with pins on PORTD or PORTB, the most likely use case -- + // this covers all the pins on the Adafruit Flora and the bulk of + // digital pins on the Arduino Pro 8 MHz (keep in mind, this code + // doesn't even get compiled for 16 MHz boards like the Uno, Mega, + // Leonardo, etc., so don't bother extending this out of hand). + // Additional PORTs could be added if you really need them, just + // duplicate the else and loop and change the PORT. Each add'l + // PORT will require about 150(ish) bytes of program space. + + // 10 instruction clocks per bit: HHxxxxxLLL + // OUT instructions: ^ ^ ^ (T=0,2,7) + + hi = PORTD | pinMask; + lo = PORTD & ~pinMask; + n1 = lo; + + if (b & 0x80) + { + n1 = hi; + } + + // Dirty trick: RJMPs proceeding to the next instruction are used + // to delay two clock cycles in one instruction word (rather than + // using two NOPs). This was necessary in order to squeeze the + // loop down to exactly 64 words -- the maximum possible for a + // relative branch. + + asm volatile( + "headD:" "\n\t" // Clk Pseudocode + // Bit 7: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 6" "\n\t" // 1-2 if(b & 0x40) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 6: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 5" "\n\t" // 1-2 if(b & 0x20) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 5: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 4" "\n\t" // 1-2 if(b & 0x10) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 4: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 3" "\n\t" // 1-2 if(b & 0x08) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 3: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 2" "\n\t" // 1-2 if(b & 0x04) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 2: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 1" "\n\t" // 1-2 if(b & 0x02) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "rjmp .+0" "\n\t" // 2 nop nop + // Bit 1: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n2] , %[lo]" "\n\t" // 1 n2 = lo + "out %[port] , %[n1]" "\n\t" // 1 PORT = n1 + "rjmp .+0" "\n\t" // 2 nop nop + "sbrc %[byte] , 0" "\n\t" // 1-2 if(b & 0x01) + "mov %[n2] , %[hi]" "\n\t" // 0-1 n2 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "sbiw %[count], 1" "\n\t" // 2 i-- (don't act on Z flag yet) + // Bit 0: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi + "mov %[n1] , %[lo]" "\n\t" // 1 n1 = lo + "out %[port] , %[n2]" "\n\t" // 1 PORT = n2 + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) + "mov %[n1] , %[hi]" "\n\t" // 0-1 n1 = hi + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo + "brne headD" "\n" // 2 while(i) (Z flag set above) + : [byte] "+r" (b), + [n1] "+r" (n1), + [n2] "+r" (n2), + [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTD)), + [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo) ); +} +#endif + +void send_pixels_8mhz_800_PortB(uint8_t* pixels, size_t sizePixels, uint8_t pinMask) +{ + volatile size_t i = sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + volatile uint8_t n1; + volatile n2 = 0; // First, next bits out + + // Same as above, just switched to PORTB and stripped of comments. + hi = PORTB | pinMask; + lo = PORTB & ~pinMask; + n1 = lo; + if (b & 0x80) + { + n1 = hi; + } + + asm volatile( + "headB:" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 6" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 5" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 4" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 3" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 2" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 1" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "rjmp .+0" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n2] , %[lo]" "\n\t" + "out %[port] , %[n1]" "\n\t" + "rjmp .+0" "\n\t" + "sbrc %[byte] , 0" "\n\t" + "mov %[n2] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "sbiw %[count], 1" "\n\t" + "out %[port] , %[hi]" "\n\t" + "mov %[n1] , %[lo]" "\n\t" + "out %[port] , %[n2]" "\n\t" + "ld %[byte] , %a[ptr]+" "\n\t" + "sbrc %[byte] , 7" "\n\t" + "mov %[n1] , %[hi]" "\n\t" + "out %[port] , %[lo]" "\n\t" + "brne headB" "\n" + : [byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi), + [lo] "r" (lo)); +} + +void send_pixels_8mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask) +{ + volatile size_t i = sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + // Timing is more relaxed; unrolling the inner loop for each bit is + // not necessary. Still using the peculiar RJMPs as 2X NOPs, not out + // of need but just to trim the code size down a little. + // This 400-KHz-datastream-on-8-MHz-CPU code is not quite identical + // to the 800-on-16 code later -- the hi/lo timing between WS2811 and + // WS2812 is not simply a 2:1 scale! + + // 20 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL + // ST instructions: ^ ^ ^ (T=0,4,10) + + volatile uint8_t next, bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head20:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 6) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7) + "dec %[bit]" "\n\t" // 1 bit-- (T = 8) + "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12) + "rjmp .+0" "\n\t" // 2 nop nop (T = 14) + "rjmp .+0" "\n\t" // 2 nop nop (T = 16) + "rjmp .+0" "\n\t" // 2 nop nop (T = 18) + "rjmp head20" "\n\t" // 2 -> head20 (next bit out) + "nextbyte20:" "\n\t" // (T = 10) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 12) + "nop" "\n\t" // 1 nop (T = 13) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 14) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 16) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18) + "brne head20" "\n" // 2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [hi] "r" (hi), + [lo] "r" (lo), + [ptr] "e" (ptr)); +} + +#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL) // 12Mhz CPU + +#ifdef PORTD // PORTD isn't present on ATtiny85, etc. +void send_pixels_12mhz_800_PortD(uint8_t* pixels, size_t sizePixels, uint8_t pinMask) +{ + volatile size_t i = sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + // In the 12 MHz case, an optimized 800 KHz datastream (no dead time + // between bytes) requires a PORT-specific loop similar to the 8 MHz + // code (but a little more relaxed in this case). + + // 15 instruction clocks per bit: HHHHxxxxxxLLLLL + // OUT instructions: ^ ^ ^ (T=0,4,10) + + volatile uint8_t next; + + hi = PORTD | pinMask; + lo = PORTD & ~pinMask; + next = lo; + if (b & 0x80) next = hi; + + // Don't "optimize" the OUT calls into the bitTime subroutine; + // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs! + asm volatile( + "headD:" "\n\t" // (T = 0) + "out %[port], %[hi]" "\n\t" // (T = 1) + "rcall bitTimeD" "\n\t" // Bit 7 (T = 15) + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 6 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 5 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 4 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 3 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 2 + "out %[port], %[hi]" "\n\t" + "rcall bitTimeD" "\n\t" // Bit 1 + // Bit 0: + "out %[port] , %[hi]" "\n\t" // 1 PORT = hi (T = 1) + "rjmp .+0" "\n\t" // 2 nop nop (T = 3) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 5) + "out %[port] , %[next]" "\n\t" // 1 PORT = next (T = 6) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 7) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 0x80) (T = 8) + "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 9) + "nop" "\n\t" // 1 (T = 10) + "out %[port] , %[lo]" "\n\t" // 1 PORT = lo (T = 11) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 13) + "brne headD" "\n\t" // 2 if(i != 0) -> (next byte) + "rjmp doneD" "\n\t" + "bitTimeD:" "\n\t" // nop nop nop (T = 4) + "out %[port], %[next]" "\n\t" // 1 PORT = next (T = 5) + "mov %[next], %[lo]" "\n\t" // 1 next = lo (T = 6) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 7) + "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 0x80) (T = 8) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 9) + "nop" "\n\t" // 1 (T = 10) + "out %[port], %[lo]" "\n\t" // 1 PORT = lo (T = 11) + "ret" "\n\t" // 4 nop nop nop nop (T = 15) + "doneD:" "\n" + : [byte] "+r" (b), + [next] "+r" (next), + [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTD)), + [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo)); +} +#endif + +void send_pixels_12mhz_800_PortB(uint8_t* pixels, size_t sizePixels, uint8_t pinMask) +{ + volatile uint16_t i = (uint16_t)sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + volatile uint8_t next; + + hi = PORTB | pinMask; + lo = PORTB & ~pinMask; + next = lo; + if (b & 0x80) + { + next = hi; + } + + // Same as above, just set for PORTB & stripped of comments + asm volatile( + "headB:" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port], %[hi]" "\n\t" + "rcall bitTimeB" "\n\t" + "out %[port] , %[hi]" "\n\t" + "rjmp .+0" "\n\t" + "ld %[byte] , %a[ptr]+" "\n\t" + "out %[port] , %[next]" "\n\t" + "mov %[next] , %[lo]" "\n\t" + "sbrc %[byte] , 7" "\n\t" + "mov %[next] , %[hi]" "\n\t" + "nop" "\n\t" + "out %[port] , %[lo]" "\n\t" + "sbiw %[count], 1" "\n\t" + "brne headB" "\n\t" + "rjmp doneB" "\n\t" + "bitTimeB:" "\n\t" + "out %[port], %[next]" "\n\t" + "mov %[next], %[lo]" "\n\t" + "rol %[byte]" "\n\t" + "sbrc %[byte], 7" "\n\t" + "mov %[next], %[hi]" "\n\t" + "nop" "\n\t" + "out %[port], %[lo]" "\n\t" + "ret" "\n\t" + "doneB:" "\n" + : [byte] "+r" (b), [next] "+r" (next), [count] "+w" (i) + : [port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi), + [lo] "r" (lo)); +} + +void send_pixels_12mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask) +{ + volatile uint16_t i = (uint16_t)sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + // 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL + // ST instructions: ^ ^ ^ (T=0,6,15) + + volatile uint8_t next, bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head30:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "rjmp .+0" "\n\t" // 2 nop nop (T = 6) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 8) + "rjmp .+0" "\n\t" // 2 nop nop (T = 10) + "rjmp .+0" "\n\t" // 2 nop nop (T = 12) + "rjmp .+0" "\n\t" // 2 nop nop (T = 14) + "nop" "\n\t" // 1 nop (T = 15) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 17) + "rjmp .+0" "\n\t" // 2 nop nop (T = 19) + "dec %[bit]" "\n\t" // 1 bit-- (T = 20) + "breq nextbyte30" "\n\t" // 1-2 if(bit == 0) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 22) + "rjmp .+0" "\n\t" // 2 nop nop (T = 24) + "rjmp .+0" "\n\t" // 2 nop nop (T = 26) + "rjmp .+0" "\n\t" // 2 nop nop (T = 28) + "rjmp head30" "\n\t" // 2 -> head30 (next bit out) + "nextbyte30:" "\n\t" // (T = 22) + "nop" "\n\t" // 1 nop (T = 23) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 24) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 26) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 28) + "brne head30" "\n" // 1-2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [hi] "r" (hi), + [lo] "r" (lo), + [ptr] "e" (ptr)); +} + +#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L) // 16Mhz CPU + +void send_pixels_16mhz_800(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask) +{ + volatile uint16_t i = (uint16_t)sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + // WS2811 and WS2812 have different hi/lo duty cycles; this is + // similar but NOT an exact copy of the prior 400-on-8 code. + + // 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL + // ST instructions: ^ ^ ^ (T=0,5,13) + + volatile uint8_t next; + volatile uint8_t bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head20:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte], 7" "\n\t" // 1-2 if(b & 128) + "mov %[next], %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "dec %[bit]" "\n\t" // 1 bit-- (T = 5) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 7) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 8) + "breq nextbyte20" "\n\t" // 1-2 if(bit == 0) (from dec above) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 10) + "rjmp .+0" "\n\t" // 2 nop nop (T = 12) + "nop" "\n\t" // 1 nop (T = 13) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15) + "nop" "\n\t" // 1 nop (T = 16) + "rjmp .+0" "\n\t" // 2 nop nop (T = 18) + "rjmp head20" "\n\t" // 2 -> head20 (next bit out) + "nextbyte20:" "\n\t" // (T = 10) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 11) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 13) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 15) + "nop" "\n\t" // 1 nop (T = 16) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 18) + "brne head20" "\n" // 2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo)); +} + +void send_pixels_16mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask) +{ + volatile size_t i = sizePixels; // Loop counter + volatile uint8_t* ptr = pixels; // Pointer to next byte + volatile uint8_t b = *ptr++; // Current byte value + volatile uint8_t hi; // PORT w/output bit set high + volatile uint8_t lo; // PORT w/output bit set low + + // The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version. + + // 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL + // ST instructions: ^ ^ ^ (T=0,8,20) + + volatile uint8_t next, bit; + + hi = *port | pinMask; + lo = *port & ~pinMask; + next = lo; + bit = 8; + + asm volatile( + "head40:" "\n\t" // Clk Pseudocode (T = 0) + "st %a[port], %[hi]" "\n\t" // 2 PORT = hi (T = 2) + "sbrc %[byte] , 7" "\n\t" // 1-2 if(b & 128) + "mov %[next] , %[hi]" "\n\t" // 0-1 next = hi (T = 4) + "rjmp .+0" "\n\t" // 2 nop nop (T = 6) + "rjmp .+0" "\n\t" // 2 nop nop (T = 8) + "st %a[port], %[next]" "\n\t" // 2 PORT = next (T = 10) + "rjmp .+0" "\n\t" // 2 nop nop (T = 12) + "rjmp .+0" "\n\t" // 2 nop nop (T = 14) + "rjmp .+0" "\n\t" // 2 nop nop (T = 16) + "rjmp .+0" "\n\t" // 2 nop nop (T = 18) + "rjmp .+0" "\n\t" // 2 nop nop (T = 20) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 22) + "nop" "\n\t" // 1 nop (T = 23) + "mov %[next] , %[lo]" "\n\t" // 1 next = lo (T = 24) + "dec %[bit]" "\n\t" // 1 bit-- (T = 25) + "breq nextbyte40" "\n\t" // 1-2 if(bit == 0) + "rol %[byte]" "\n\t" // 1 b <<= 1 (T = 27) + "nop" "\n\t" // 1 nop (T = 28) + "rjmp .+0" "\n\t" // 2 nop nop (T = 30) + "rjmp .+0" "\n\t" // 2 nop nop (T = 32) + "rjmp .+0" "\n\t" // 2 nop nop (T = 34) + "rjmp .+0" "\n\t" // 2 nop nop (T = 36) + "rjmp .+0" "\n\t" // 2 nop nop (T = 38) + "rjmp head40" "\n\t" // 2 -> head40 (next bit out) + "nextbyte40:" "\n\t" // (T = 27) + "ldi %[bit] , 8" "\n\t" // 1 bit = 8 (T = 28) + "ld %[byte] , %a[ptr]+" "\n\t" // 2 b = *ptr++ (T = 30) + "rjmp .+0" "\n\t" // 2 nop nop (T = 32) + "st %a[port], %[lo]" "\n\t" // 2 PORT = lo (T = 34) + "rjmp .+0" "\n\t" // 2 nop nop (T = 36) + "sbiw %[count], 1" "\n\t" // 2 i-- (T = 38) + "brne head40" "\n" // 1-2 if(i != 0) -> (next byte) + : [port] "+e" (port), + [byte] "+r" (b), + [bit] "+r" (bit), + [next] "+r" (next), + [count] "+w" (i) + : [ptr] "e" (ptr), + [hi] "r" (hi), + [lo] "r" (lo)); +} + +#else +#error "CPU SPEED NOT SUPPORTED" +#endif + +#endif \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelEsp.c b/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelEsp.c new file mode 100644 index 000000000..52415ff42 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoPixelEsp.c @@ -0,0 +1,151 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper functions for Esp8266 and Esp32. + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) + +#include +#if defined(ARDUINO_ARCH_ESP8266) +#include +#endif + +// ESP32 doesn't define ICACHE_RAM_ATTR +#ifndef ICACHE_RAM_ATTR +#define ICACHE_RAM_ATTR IRAM_ATTR +#endif + +inline uint32_t _getCycleCount() +{ + uint32_t ccount; + __asm__ __volatile__("rsr %0,ccount":"=a" (ccount)); + return ccount; +} + +#define CYCLES_800_T0H (F_CPU / 2500000) // 0.4us +#define CYCLES_800_T1H (F_CPU / 1250000) // 0.8us +#define CYCLES_800 (F_CPU / 800000) // 1.25us per bit +#define CYCLES_400_T0H (F_CPU / 2000000) +#define CYCLES_400_T1H (F_CPU / 833333) +#define CYCLES_400 (F_CPU / 400000) + +void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin) +{ + const uint32_t pinRegister = _BV(pin); + uint8_t mask; + uint8_t subpix; + uint32_t cyclesStart; + + // trigger emediately + cyclesStart = _getCycleCount() - CYCLES_800; + do + { + subpix = *pixels++; + for (mask = 0x80; mask != 0; mask >>= 1) + { + // do the checks here while we are waiting on time to pass + uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_800_T1H : CYCLES_800_T0H; + uint32_t cyclesNext = cyclesStart; + + // after we have done as much work as needed for this next bit + // now wait for the HIGH + do + { + // cache and use this count so we don't incur another + // instruction before we turn the bit high + cyclesStart = _getCycleCount(); + } while ((cyclesStart - cyclesNext) < CYCLES_800); + + // set high +#if defined(ARDUINO_ARCH_ESP32) + GPIO.out_w1ts = pinRegister; +#else + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister); +#endif + + // wait for the LOW + do + { + cyclesNext = _getCycleCount(); + } while ((cyclesNext - cyclesStart) < cyclesBit); + + // set low +#if defined(ARDUINO_ARCH_ESP32) + GPIO.out_w1tc = pinRegister; +#else + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); +#endif + } + } while (pixels < end); +} + +void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin) +{ + const uint32_t pinRegister = _BV(pin); + uint8_t mask; + uint8_t subpix; + uint32_t cyclesStart; + + // trigger emediately + cyclesStart = _getCycleCount() - CYCLES_400; + do + { + subpix = *pixels++; + for (mask = 0x80; mask; mask >>= 1) + { + uint32_t cyclesBit = ((subpix & mask)) ? CYCLES_400_T1H : CYCLES_400_T0H; + uint32_t cyclesNext = cyclesStart; + + // after we have done as much work as needed for this next bit + // now wait for the HIGH + do + { + // cache and use this count so we don't incur another + // instruction before we turn the bit high + cyclesStart = _getCycleCount(); + } while ((cyclesStart - cyclesNext) < CYCLES_400); + +#if defined(ARDUINO_ARCH_ESP32) + GPIO.out_w1ts = pinRegister; +#else + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinRegister); +#endif + + // wait for the LOW + do + { + cyclesNext = _getCycleCount(); + } while ((cyclesNext - cyclesStart) < cyclesBit); + + // set low +#if defined(ARDUINO_ARCH_ESP32) + GPIO.out_w1tc = pinRegister; +#else + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinRegister); +#endif + } + } while (pixels < end); +} + +#endif diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoRingTopology.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoRingTopology.h new file mode 100644 index 000000000..8e152f8c5 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoRingTopology.h @@ -0,0 +1,89 @@ +#pragma once + +/*------------------------------------------------------------------------- +NeoRingTopology provides a mapping feature of a 2d polar cordinate to a +linear 1d cordinate. +It is used to map a series of concentric rings of NeoPixels to a index on +the NeoPixelBus. + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +template class NeoRingTopology : protected T_LAYOUT +{ +public: + NeoRingTopology() + { + } + + uint16_t Map(uint8_t ring, uint16_t pixel) const + { + if (pixel >= getPixelCountAtRing(ring)) + { + return 0; // invalid ring and/or pixel argument, always return a valid value, the first one + } + + return _map(ring, pixel); + } + + uint16_t MapProbe(uint8_t ring, uint16_t pixel) const + { + if (pixel >= getPixelCountAtRing(ring)) + { + return getPixelCount(); // total count, out of bounds + } + + return _map(ring, pixel); + } + + uint8_t getCountOfRings() const + { + return _ringCount() - 1; // minus one as the Rings includes the extra value + } + + uint16_t getPixelCountAtRing(uint8_t ring) const + { + if (ring >= getCountOfRings()) + { + return 0; // invalid, no pixels + } + + return T_LAYOUT::Rings[ring + 1] - T_LAYOUT::Rings[ring]; // using the extra value for count calc + } + + uint16_t getPixelCount() const + { + return T_LAYOUT::Rings[_ringCount() - 1]; // the last entry is the total count + } + +private: + uint16_t _map(uint8_t ring, uint16_t pixel) const + { + return T_LAYOUT::Rings[ring] + pixel; + } + + uint8_t _ringCount() const + { + return sizeof(T_LAYOUT::Rings) / sizeof(T_LAYOUT::Rings[0]); + } +}; diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoSpriteSheet.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoSpriteSheet.h new file mode 100644 index 000000000..a0f277eb9 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoSpriteSheet.h @@ -0,0 +1,163 @@ +/*------------------------------------------------------------------------- +NeoPixel library + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + + +template class NeoVerticalSpriteSheet +{ +public: + NeoVerticalSpriteSheet(uint16_t width, + uint16_t height, + uint16_t spriteHeight, + PGM_VOID_P pixels) : + _method(width, height, pixels), + _spriteHeight(spriteHeight), + _spriteCount(height / spriteHeight) + { + } + + operator NeoBufferContext() + { + return _method; + } + + uint16_t SpriteWidth() const + { + return _method.Width(); + }; + + uint16_t SpriteHeight() const + { + return _spriteHeight; + }; + + uint16_t SpriteCount() const + { + return _spriteCount; + } + + void SetPixelColor(uint16_t indexSprite, + int16_t x, + int16_t y, + typename T_BUFFER_METHOD::ColorObject color) + { + _method.SetPixelColor(pixelIndex(indexSprite, x, y), color); + }; + + typename T_BUFFER_METHOD::ColorObject GetPixelColor(uint16_t indexSprite, + int16_t x, + int16_t y) const + { + return _method.GetPixelColor(pixelIndex(indexSprite, x, y)); + }; + + void ClearTo(typename T_BUFFER_METHOD::ColorObject color) + { + _method.ClearTo(color); + }; + + void Blt(NeoBufferContext destBuffer, + uint16_t indexPixel, + uint16_t indexSprite) + { + uint16_t destPixelCount = destBuffer.PixelCount(); + // validate indexPixel + if (indexPixel >= destPixelCount) + { + return; + } + + // validate indexSprite + if (indexSprite >= _spriteCount) + { + return; + } + // calc how many we can copy + uint16_t copyCount = destPixelCount - indexPixel; + + if (copyCount > SpriteWidth()) + { + copyCount = SpriteWidth(); + } + + uint8_t* pDest = T_BUFFER_METHOD::ColorFeature::getPixelAddress(destBuffer.Pixels, indexPixel); + const uint8_t* pSrc = T_BUFFER_METHOD::ColorFeature::getPixelAddress(_method.Pixels(), pixelIndex(indexSprite, 0, 0)); + _method.CopyPixels(pDest, pSrc, copyCount); + } + + void Blt(NeoBufferContext destBuffer, + int16_t x, + int16_t y, + uint16_t indexSprite, + LayoutMapCallback layoutMap) + { + if (indexSprite >= _spriteCount) + { + return; + } + uint16_t destPixelCount = destBuffer.PixelCount(); + + for (int16_t srcY = 0; srcY < SpriteHeight(); srcY++) + { + for (int16_t srcX = 0; srcX < SpriteWidth(); srcX++) + { + uint16_t indexDest = layoutMap(srcX + x, srcY + y); + + if (indexDest < destPixelCount) + { + const uint8_t* pSrc = T_BUFFER_METHOD::ColorFeature::getPixelAddress(_method.Pixels(), pixelIndex(indexSprite, srcX, srcY)); + uint8_t* pDest = T_BUFFER_METHOD::ColorFeature::getPixelAddress(destBuffer.Pixels, indexDest); + + _method.CopyPixels(pDest, pSrc, 1); + } + } + } + + } + +private: + T_BUFFER_METHOD _method; + + const uint16_t _spriteHeight; + const uint16_t _spriteCount; + + uint16_t pixelIndex(uint16_t indexSprite, + int16_t x, + int16_t y) + { + uint16_t result = PixelIndex_OutOfBounds; + + if (indexSprite < _spriteCount && + x >= 0 && + x < SpriteWidth() && + y >= 0 && + y < SpriteHeight()) + { + result = x + y * SpriteWidth() + indexSprite * _spriteHeight * SpriteWidth(); + } + return result; + } +}; \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoTiles.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoTiles.h new file mode 100644 index 000000000..2c0ca8338 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoTiles.h @@ -0,0 +1,158 @@ +#pragma once + +/*------------------------------------------------------------------------- +NeoTiles provides a mapping feature of a 2d cordinate to linear 1d cordinate +It is used to map tiles of matricies of NeoPixels to a index on the NeoPixelBus +where the the matricies use one topology and the tiles of those matricies can +use another + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +//----------------------------------------------------------------------------- +// class NeoTiles +// Simple template Tile layout class +// T_MATRIX_LAYOUT = the layout used on the pixel matrix panel (a tile) +// T_TILE_LAYOUT = the layout used for the tiles. +// +//----------------------------------------------------------------------------- +template class NeoTiles +{ +public: + NeoTiles(uint16_t topoWidth, uint16_t topoHeight, + uint16_t tilesWidth, uint16_t tilesHeight) : + _topo(topoWidth, topoHeight), + _width(tilesWidth), + _height(tilesHeight) + { + } + + uint16_t Map(int16_t x, int16_t y) const + { + uint16_t totalWidth = getWidth(); + uint16_t totalHeight = getHeight(); + + if (x >= totalWidth) + { + x = totalWidth - 1; + } + else if (x < 0) + { + x = 0; + } + + if (y >= totalHeight) + { + y = totalHeight - 1; + } + else if (y < 0) + { + y = 0; + } + + uint16_t localIndex; + uint16_t tileOffset; + + calculate(x, y, &localIndex, &tileOffset); + + return localIndex + tileOffset; + } + + uint16_t MapProbe(int16_t x, int16_t y) const + { + uint16_t totalWidth = getWidth(); + uint16_t totalHeight = getHeight(); + + if (x < 0 || x >= totalWidth || y < 0 || y >= totalHeight) + { + return totalWidth * totalHeight; // count, out of bounds + } + + uint16_t localIndex; + uint16_t tileOffset; + + calculate(x, y, &localIndex, &tileOffset); + + return localIndex + tileOffset; + } + + NeoTopologyHint TopologyHint(int16_t x, int16_t y) const + { + uint16_t totalWidth = getWidth(); + uint16_t totalHeight = getHeight(); + + if (x < 0 || x >= totalWidth || y < 0 || y >= totalHeight) + { + return NeoTopologyHint_OutOfBounds; + } + + uint16_t localIndex; + uint16_t tileOffset; + NeoTopologyHint result; + + calculate(x, y, &localIndex, &tileOffset); + + if (localIndex == 0) + { + result = NeoTopologyHint_FirstOnPanel; + } + else if (localIndex == (_topo.getWidth() * _topo.getHeight() - 1)) + { + result = NeoTopologyHint_LastOnPanel; + } + else + { + result = NeoTopologyHint_InPanel; + } + + return result; + } + + uint16_t getWidth() const + { + return _width * _topo.getWidth(); + } + + uint16_t getHeight() const + { + return _height * _topo.getHeight(); + } + +private: + const NeoTopology _topo; + const uint16_t _width; + const uint16_t _height; + + void calculate(uint16_t x, uint16_t y, uint16_t* pLocalIndex, uint16_t* pTileOffset) const + { + uint16_t tileX = x / _topo.getWidth(); + uint16_t topoX = x % _topo.getWidth(); + + uint16_t tileY = y / _topo.getHeight(); + uint16_t topoY = y % _topo.getHeight(); + + *pTileOffset = T_TILE_LAYOUT::Map(_width, _height, tileX, tileY) * _topo.getWidth() * _topo.getHeight(); + *pLocalIndex = _topo.Map(topoX, topoY); + } +}; + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/NeoTopology.h b/lib/NeoPixelBus-2.2.9/src/internal/NeoTopology.h new file mode 100644 index 000000000..224c1dbdf --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/NeoTopology.h @@ -0,0 +1,91 @@ +#pragma once + +/*------------------------------------------------------------------------- +NeoTopology provides a mapping feature of a 2d cordinate to linear 1d cordinate +It is used to map a matrix of NeoPixels to a index on the NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +enum NeoTopologyHint +{ + NeoTopologyHint_FirstOnPanel, + NeoTopologyHint_InPanel, + NeoTopologyHint_LastOnPanel, + NeoTopologyHint_OutOfBounds +}; + +template class NeoTopology +{ +public: + NeoTopology(uint16_t width, uint16_t height) : + _width(width), + _height(height) + { + + } + + uint16_t Map(int16_t x, int16_t y) const + { + if (x >= _width) + { + x = _width - 1; + } + else if (x < 0) + { + x = 0; + } + if (y >= _height) + { + y = _height - 1; + } + else if (y < 0) + { + y = 0; + } + return T_LAYOUT::Map(_width, _height, x, y); + } + + uint16_t MapProbe(int16_t x, int16_t y) const + { + if (x < 0 || x >= _width || y < 0 || y >= _height) + { + return _width * _height; // count, out of bounds + } + return T_LAYOUT::Map(_width, _height, x, y); + } + + uint16_t getWidth() const + { + return _width; + } + + uint16_t getHeight() const + { + return _height; + } + +private: + const uint16_t _width; + const uint16_t _height; +}; diff --git a/lib/NeoPixelBus-2.2.9/src/internal/RgbColor.cpp b/lib/NeoPixelBus-2.2.9/src/internal/RgbColor.cpp new file mode 100644 index 000000000..29ae4343b --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/RgbColor.cpp @@ -0,0 +1,249 @@ +/*------------------------------------------------------------------------- +RgbColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "RgbColor.h" +#include "HslColor.h" +#include "HsbColor.h" +#include "HtmlColor.h" + +static float _CalcColor(float p, float q, float t) +{ + if (t < 0.0f) + t += 1.0f; + if (t > 1.0f) + t -= 1.0f; + + if (t < 1.0f / 6.0f) + return p + (q - p) * 6.0f * t; + + if (t < 0.5f) + return q; + + if (t < 2.0f / 3.0f) + return p + ((q - p) * (2.0f / 3.0f - t) * 6.0f); + + return p; +} + +RgbColor::RgbColor(const HtmlColor& color) +{ + uint32_t temp = color.Color; + + B = (temp & 0xff); + temp = temp >> 8; + G = (temp & 0xff); + temp = temp >> 8; + R = (temp & 0xff); +}; + +RgbColor::RgbColor(const HslColor& color) +{ + float r; + float g; + float b; + + float h = color.H; + float s = color.S; + float l = color.L; + + + if (color.S == 0.0f || color.L == 0.0f) + { + r = g = b = l; // achromatic or black + } + else + { + float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s); + float p = 2.0f * l - q; + r = _CalcColor(p, q, h + 1.0f / 3.0f); + g = _CalcColor(p, q, h); + b = _CalcColor(p, q, h - 1.0f / 3.0f); + } + + R = (uint8_t)(r * 255.0f); + G = (uint8_t)(g * 255.0f); + B = (uint8_t)(b * 255.0f); +} + +RgbColor::RgbColor(const HsbColor& color) +{ + float r; + float g; + float b; + + float h = color.H; + float s = color.S; + float v = color.B; + + if (color.S == 0.0f) + { + r = g = b = v; // achromatic or black + } + else + { + if (h < 0.0f) + { + h += 1.0f; + } + else if (h >= 1.0f) + { + h -= 1.0f; + } + h *= 6.0f; + int i = (int)h; + float f = h - i; + float q = v * (1.0f - s * f); + float p = v * (1.0f - s); + float t = v * (1.0f - s * (1.0f - f)); + switch (i) + { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + default: + r = v; + g = p; + b = q; + break; + } + } + + R = (uint8_t)(r * 255.0f); + G = (uint8_t)(g * 255.0f); + B = (uint8_t)(b * 255.0f); +} + +uint8_t RgbColor::CalculateBrightness() const +{ + return (uint8_t)(((uint16_t)R + (uint16_t)G + (uint16_t)B) / 3); +} + +void RgbColor::Darken(uint8_t delta) +{ + if (R > delta) + { + R -= delta; + } + else + { + R = 0; + } + + if (G > delta) + { + G -= delta; + } + else + { + G = 0; + } + + if (B > delta) + { + B -= delta; + } + else + { + B = 0; + } +} + +void RgbColor::Lighten(uint8_t delta) +{ + if (R < 255 - delta) + { + R += delta; + } + else + { + R = 255; + } + + if (G < 255 - delta) + { + G += delta; + } + else + { + G = 255; + } + + if (B < 255 - delta) + { + B += delta; + } + else + { + B = 255; + } +} + +RgbColor RgbColor::LinearBlend(const RgbColor& left, const RgbColor& right, float progress) +{ + return RgbColor( left.R + ((right.R - left.R) * progress), + left.G + ((right.G - left.G) * progress), + left.B + ((right.B - left.B) * progress)); +} + +RgbColor RgbColor::BilinearBlend(const RgbColor& c00, + const RgbColor& c01, + const RgbColor& c10, + const RgbColor& c11, + float x, + float y) +{ + float v00 = (1.0f - x) * (1.0f - y); + float v10 = x * (1.0f - y); + float v01 = (1.0f - x) * y; + float v11 = x * y; + + return RgbColor( + c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11, + c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11, + c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11); +} \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/RgbColor.h b/lib/NeoPixelBus-2.2.9/src/internal/RgbColor.h new file mode 100644 index 000000000..516112319 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/RgbColor.h @@ -0,0 +1,148 @@ +/*------------------------------------------------------------------------- +RgbColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +#include + +struct HslColor; +struct HsbColor; +struct HtmlColor; + +// ------------------------------------------------------------------------ +// RgbColor represents a color object that is represented by Red, Green, Blue +// component values. It contains helpful color routines to manipulate the +// color. +// ------------------------------------------------------------------------ +struct RgbColor +{ + // ------------------------------------------------------------------------ + // Construct a RgbColor using R, G, B values (0-255) + // ------------------------------------------------------------------------ + RgbColor(uint8_t r, uint8_t g, uint8_t b) : + R(r), G(g), B(b) + { + }; + + // ------------------------------------------------------------------------ + // Construct a RgbColor using a single brightness value (0-255) + // This works well for creating gray tone colors + // (0) = black, (255) = white, (128) = gray + // ------------------------------------------------------------------------ + RgbColor(uint8_t brightness) : + R(brightness), G(brightness), B(brightness) + { + }; + + // ------------------------------------------------------------------------ + // Construct a RgbColor using HtmlColor + // ------------------------------------------------------------------------ + RgbColor(const HtmlColor& color); + + // ------------------------------------------------------------------------ + // Construct a RgbColor using HslColor + // ------------------------------------------------------------------------ + RgbColor(const HslColor& color); + + // ------------------------------------------------------------------------ + // Construct a RgbColor using HsbColor + // ------------------------------------------------------------------------ + RgbColor(const HsbColor& color); + + // ------------------------------------------------------------------------ + // Construct a RgbColor that will have its values set in latter operations + // CAUTION: The R,G,B members are not initialized and may not be consistent + // ------------------------------------------------------------------------ + RgbColor() + { + }; + + // ------------------------------------------------------------------------ + // Comparison operators + // ------------------------------------------------------------------------ + bool operator==(const RgbColor& other) const + { + return (R == other.R && G == other.G && B == other.B); + }; + + bool operator!=(const RgbColor& other) const + { + return !(*this == other); + }; + + // ------------------------------------------------------------------------ + // CalculateBrightness will calculate the overall brightness + // NOTE: This is a simple linear brightness + // ------------------------------------------------------------------------ + uint8_t CalculateBrightness() const; + + // ------------------------------------------------------------------------ + // Darken will adjust the color by the given delta toward black + // NOTE: This is a simple linear change + // delta - (0-255) the amount to dim the color + // ------------------------------------------------------------------------ + void Darken(uint8_t delta); + + // ------------------------------------------------------------------------ + // Lighten will adjust the color by the given delta toward white + // NOTE: This is a simple linear change + // delta - (0-255) the amount to lighten the color + // ------------------------------------------------------------------------ + void Lighten(uint8_t delta); + + // ------------------------------------------------------------------------ + // LinearBlend between two colors by the amount defined by progress variable + // left - the color to start the blend at + // right - the color to end the blend at + // progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right + // and a value between will blend the color weighted linearly between them + // ------------------------------------------------------------------------ + static RgbColor LinearBlend(const RgbColor& left, const RgbColor& right, float progress); + + // ------------------------------------------------------------------------ + // BilinearBlend between four colors by the amount defined by 2d variable + // c00 - upper left quadrant color + // c01 - upper right quadrant color + // c10 - lower left quadrant color + // c11 - lower right quadrant color + // x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space + // y - unit value (0.0 - 1.0) that defines the blend progress in vertical space + // ------------------------------------------------------------------------ + static RgbColor BilinearBlend(const RgbColor& c00, + const RgbColor& c01, + const RgbColor& c10, + const RgbColor& c11, + float x, + float y); + + // ------------------------------------------------------------------------ + // Red, Green, Blue color members (0-255) where + // (0,0,0) is black and (255,255,255) is white + // ------------------------------------------------------------------------ + uint8_t R; + uint8_t G; + uint8_t B; +}; + diff --git a/lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.cpp b/lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.cpp new file mode 100644 index 000000000..062834d03 --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.cpp @@ -0,0 +1,178 @@ +/*------------------------------------------------------------------------- +RgbwColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#include "RgbColor.h" +#include "HslColor.h" +#include "HsbColor.h" +#include "RgbwColor.h" +#include "HtmlColor.h" + +RgbwColor::RgbwColor(const HtmlColor& color) +{ + uint32_t temp = color.Color; + B = (temp & 0xff); + temp = temp >> 8; + G = (temp & 0xff); + temp = temp >> 8; + R = (temp & 0xff); + temp = temp >> 8; + W = (temp & 0xff); +}; + +RgbwColor::RgbwColor(const HslColor& color) +{ + RgbColor rgbColor(color); + *this = rgbColor; +} + +RgbwColor::RgbwColor(const HsbColor& color) +{ + RgbColor rgbColor(color); + *this = rgbColor; +} + +uint8_t RgbwColor::CalculateBrightness() const +{ + uint8_t colorB = (uint8_t)(((uint16_t)R + (uint16_t)G + (uint16_t)B) / 3); + if (W > colorB) + { + return W; + } + else + { + return colorB; + } +} + +void RgbwColor::Darken(uint8_t delta) +{ + if (R > delta) + { + R -= delta; + } + else + { + R = 0; + } + + if (G > delta) + { + G -= delta; + } + else + { + G = 0; + } + + if (B > delta) + { + B -= delta; + } + else + { + B = 0; + } + + if (W > delta) + { + W -= delta; + } + else + { + W = 0; + } +} + +void RgbwColor::Lighten(uint8_t delta) +{ + if (IsColorLess()) + { + if (W < 255 - delta) + { + W += delta; + } + else + { + W = 255; + } + } + else + { + if (R < 255 - delta) + { + R += delta; + } + else + { + R = 255; + } + + if (G < 255 - delta) + { + G += delta; + } + else + { + G = 255; + } + + if (B < 255 - delta) + { + B += delta; + } + else + { + B = 255; + } + } +} + +RgbwColor RgbwColor::LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress) +{ + return RgbwColor( left.R + ((right.R - left.R) * progress), + left.G + ((right.G - left.G) * progress), + left.B + ((right.B - left.B) * progress), + left.W + ((right.W - left.W) * progress) ); +} + +RgbwColor RgbwColor::BilinearBlend(const RgbwColor& c00, + const RgbwColor& c01, + const RgbwColor& c10, + const RgbwColor& c11, + float x, + float y) +{ + float v00 = (1.0f - x) * (1.0f - y); + float v10 = x * (1.0f - y); + float v01 = (1.0f - x) * y; + float v11 = x * y; + + return RgbwColor( + c00.R * v00 + c10.R * v10 + c01.R * v01 + c11.R * v11, + c00.G * v00 + c10.G * v10 + c01.G * v01 + c11.G * v11, + c00.B * v00 + c10.B * v10 + c01.B * v01 + c11.B * v11, + c00.W * v00 + c10.W * v10 + c01.W * v01 + c11.W * v11 ); +} \ No newline at end of file diff --git a/lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.h b/lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.h new file mode 100644 index 000000000..38f25302b --- /dev/null +++ b/lib/NeoPixelBus-2.2.9/src/internal/RgbwColor.h @@ -0,0 +1,178 @@ +/*------------------------------------------------------------------------- +RgbwColor provides a color object that can be directly consumed by NeoPixelBus + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ +#pragma once + +#include + +struct RgbColor; +struct HslColor; +struct HsbColor; + +// ------------------------------------------------------------------------ +// RgbwColor represents a color object that is represented by Red, Green, Blue +// component values and an extra White component. It contains helpful color +// routines to manipulate the color. +// ------------------------------------------------------------------------ +struct RgbwColor +{ + // ------------------------------------------------------------------------ + // Construct a RgbwColor using R, G, B, W values (0-255) + // ------------------------------------------------------------------------ + RgbwColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) : + R(r), G(g), B(b), W(w) + { + }; + + // ------------------------------------------------------------------------ + // Construct a RgbColor using a single brightness value (0-255) + // This works well for creating gray tone colors + // (0) = black, (255) = white, (128) = gray + // ------------------------------------------------------------------------ + RgbwColor(uint8_t brightness) : + R(0), G(0), B(0), W(brightness) + { + }; + + // ------------------------------------------------------------------------ + // Construct a RgbwColor using RgbColor + // ------------------------------------------------------------------------ + RgbwColor(const RgbColor& color) : + R(color.R), + G(color.G), + B(color.B), + W(0) + { + }; + + // ------------------------------------------------------------------------ + // Construct a RgbwColor using HtmlColor + // ------------------------------------------------------------------------ + RgbwColor(const HtmlColor& color); + + // ------------------------------------------------------------------------ + // Construct a RgbwColor using HslColor + // ------------------------------------------------------------------------ + RgbwColor(const HslColor& color); + + // ------------------------------------------------------------------------ + // Construct a RgbwColor using HsbColor + // ------------------------------------------------------------------------ + RgbwColor(const HsbColor& color); + + // ------------------------------------------------------------------------ + // Construct a RgbwColor that will have its values set in latter operations + // CAUTION: The R,G,B, W members are not initialized and may not be consistent + // ------------------------------------------------------------------------ + RgbwColor() + { + }; + + // ------------------------------------------------------------------------ + // Comparison operators + // ------------------------------------------------------------------------ + bool operator==(const RgbwColor& other) const + { + return (R == other.R && G == other.G && B == other.B && W == other.W); + }; + + bool operator!=(const RgbwColor& other) const + { + return !(*this == other); + }; + + // ------------------------------------------------------------------------ + // Returns if the color is grey, all values are equal other than white + // ------------------------------------------------------------------------ + bool IsMonotone() const + { + return (R == B && R == G); + }; + + // ------------------------------------------------------------------------ + // Returns if the color components are all zero, the white component maybe + // anything + // ------------------------------------------------------------------------ + bool IsColorLess() const + { + return (R == 0 && B == 0 && G == 0); + }; + + // ------------------------------------------------------------------------ + // CalculateBrightness will calculate the overall brightness + // NOTE: This is a simple linear brightness + // ------------------------------------------------------------------------ + uint8_t CalculateBrightness() const; + + // ------------------------------------------------------------------------ + // Darken will adjust the color by the given delta toward black + // NOTE: This is a simple linear change + // delta - (0-255) the amount to dim the color + // ------------------------------------------------------------------------ + void Darken(uint8_t delta); + + // ------------------------------------------------------------------------ + // Lighten will adjust the color by the given delta toward white + // NOTE: This is a simple linear change + // delta - (0-255) the amount to lighten the color + // ------------------------------------------------------------------------ + void Lighten(uint8_t delta); + + // ------------------------------------------------------------------------ + // LinearBlend between two colors by the amount defined by progress variable + // left - the color to start the blend at + // right - the color to end the blend at + // progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right + // and a value between will blend the color weighted linearly between them + // ------------------------------------------------------------------------ + static RgbwColor LinearBlend(const RgbwColor& left, const RgbwColor& right, float progress); + + // ------------------------------------------------------------------------ + // BilinearBlend between four colors by the amount defined by 2d variable + // c00 - upper left quadrant color + // c01 - upper right quadrant color + // c10 - lower left quadrant color + // c11 - lower right quadrant color + // x - unit value (0.0 - 1.0) that defines the blend progress in horizontal space + // y - unit value (0.0 - 1.0) that defines the blend progress in vertical space + // ------------------------------------------------------------------------ + static RgbwColor BilinearBlend(const RgbwColor& c00, + const RgbwColor& c01, + const RgbwColor& c10, + const RgbwColor& c11, + float x, + float y); + + // ------------------------------------------------------------------------ + // Red, Green, Blue, White color members (0-255) where + // (0,0,0,0) is black and (255,255,255, 0) and (0,0,0,255) is white + // Note (255,255,255,255) is extreme bright white + // ------------------------------------------------------------------------ + uint8_t R; + uint8_t G; + uint8_t B; + uint8_t W; +}; + diff --git a/lib/OneWire-2.3.3.06/OneWire.cpp b/lib/OneWire-2.3.3.06/OneWire.cpp new file mode 100644 index 000000000..5c9945d51 --- /dev/null +++ b/lib/OneWire-2.3.3.06/OneWire.cpp @@ -0,0 +1,597 @@ +/* +Copyright (c) 2007, Jim Studt (original old version - many contributors since) + +The latest version of this library may be found at: + http://www.pjrc.com/teensy/td_libs_OneWire.html + +OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since +January 2010. + +DO NOT EMAIL for technical support, especially not for ESP chips! +All project support questions must be posted on public forums +relevant to the board or chips used. If using Arduino, post on +Arduino's forum. If using ESP, post on the ESP community forums. +There is ABSOLUTELY NO TECH SUPPORT BY PRIVATE EMAIL! + +Github's issue tracker for OneWire should be used only to report +specific bugs. DO NOT request project support via Github. All +project and tech support questions must be posted on forums, not +github issues. If you experience a problem and you are not +absolutely sure it's an issue with the library, ask on a forum +first. Only use github to report issues after experts have +confirmed the issue is with OneWire rather than your project. + +Back in 2010, OneWire was in need of many bug fixes, but had +been abandoned the original author (Jim Studt). None of the known +contributors were interested in maintaining OneWire. Paul typically +works on OneWire every 6 to 12 months. Patches usually wait that +long. If anyone is interested in more actively maintaining OneWire, +please contact Paul (this is pretty much the only reason to use +private email about OneWire). + +OneWire is now very mature code. No changes other than adding +definitions for newer hardware support are anticipated. + +Version 2.3: + Unknown chip fallback mode, Roger Clark + Teensy-LC compatibility, Paul Stoffregen + Search bug fix, Love Nystrom + +Version 2.2: + Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com + Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030 + Fix DS18B20 example negative temperature + Fix DS18B20 example's low res modes, Ken Butcher + Improve reset timing, Mark Tillotson + Add const qualifiers, Bertrik Sikken + Add initial value input to crc16, Bertrik Sikken + Add target_search() function, Scott Roberts + +Version 2.1: + Arduino 1.0 compatibility, Paul Stoffregen + Improve temperature example, Paul Stoffregen + DS250x_PROM example, Guillermo Lovato + PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com + Improvements from Glenn Trewitt: + - crc16() now works + - check_crc16() does all of calculation/checking work. + - Added read_bytes() and write_bytes(), to reduce tedious loops. + - Added ds2408 example. + Delete very old, out-of-date readme file (info is here) + +Version 2.0: Modifications by Paul Stoffregen, January 2010: +http://www.pjrc.com/teensy/td_libs_OneWire.html + Search fix from Robin James + http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 + Use direct optimized I/O in all cases + Disable interrupts during timing critical sections + (this solves many random communication errors) + Disable interrupts during read-modify-write I/O + Reduce RAM consumption by eliminating unnecessary + variables and trimming many to 8 bits + Optimize both crc8 - table version moved to flash + +Modified to work with larger numbers of devices - avoids loop. +Tested in Arduino 11 alpha with 12 sensors. +26 Sept 2008 -- Robin James +http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 + +Updated to work with arduino-0008 and to include skip() as of +2007/07/06. --RJL20 + +Modified to calculate the 8-bit CRC directly, avoiding the need for +the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010 +-- Tom Pollard, Jan 23, 2008 + +Jim Studt's original library was modified by Josh Larios. + +Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008 + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation 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 furnished 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 FOR 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. + +Much of the code was inspired by Derek Yerger's code, though I don't +think much of that remains. In any event that was.. + (copyleft) 2006 by Derek Yerger - Free to distribute freely. + +The CRC code was excerpted and inspired by the Dallas Semiconductor +sample code bearing this copyright. +//--------------------------------------------------------------------------- +// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation 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 furnished 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 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL DALLAS SEMICONDUCTOR 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. +// +// Except as contained in this notice, the name of Dallas Semiconductor +// shall not be used except as stated in the Dallas Semiconductor +// Branding Policy. +//-------------------------------------------------------------------------- +*/ + +#include "OneWire.h" + + +OneWire::OneWire(uint8_t pin) +{ + pinMode(pin, INPUT); + bitmask = PIN_TO_BITMASK(pin); + baseReg = PIN_TO_BASEREG(pin); +#if ONEWIRE_SEARCH + reset_search(); +#endif +} + + +// Perform the onewire reset function. We will wait up to 250uS for +// the bus to come high, if it doesn't then it is broken or shorted +// and we return a 0; +// +// Returns 1 if a device asserted a presence pulse, 0 otherwise. +// +uint8_t OneWire::reset(void) +{ + IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; + volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; + uint8_t r; + uint8_t retries = 125; + + noInterrupts(); + DIRECT_MODE_INPUT(reg, mask); + interrupts(); + // wait until the wire is high... just in case + do { + if (--retries == 0) return 0; + delayMicroseconds(2); + } while ( !DIRECT_READ(reg, mask)); + + noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + interrupts(); + delayMicroseconds(480); + noInterrupts(); + DIRECT_MODE_INPUT(reg, mask); // allow it to float + delayMicroseconds(70); + r = !DIRECT_READ(reg, mask); + interrupts(); + delayMicroseconds(410); + return r; +} + +// +// Write a bit. Port and bit is used to cut lookup time and provide +// more certain timing. +// +void OneWire::write_bit(uint8_t v) +{ + IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; + volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; + + if (v & 1) { + noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(10); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + interrupts(); + delayMicroseconds(55); + } else { + noInterrupts(); + DIRECT_WRITE_LOW(reg, mask); + DIRECT_MODE_OUTPUT(reg, mask); // drive output low + delayMicroseconds(65); + DIRECT_WRITE_HIGH(reg, mask); // drive output high + interrupts(); + delayMicroseconds(5); + } +} + +// +// Read a bit. Port and bit is used to cut lookup time and provide +// more certain timing. +// +uint8_t OneWire::read_bit(void) +{ + IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; + volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; + uint8_t r; + + noInterrupts(); + DIRECT_MODE_OUTPUT(reg, mask); + DIRECT_WRITE_LOW(reg, mask); + delayMicroseconds(3); + DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise + delayMicroseconds(10); + r = DIRECT_READ(reg, mask); + interrupts(); + delayMicroseconds(53); + return r; +} + +// +// Write a byte. The writing code uses the active drivers to raise the +// pin high, if you need power after the write (e.g. DS18S20 in +// parasite power mode) then set 'power' to 1, otherwise the pin will +// go tri-state at the end of the write to avoid heating in a short or +// other mishap. +// +void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { + uint8_t bitMask; + + for (bitMask = 0x01; bitMask; bitMask <<= 1) { + OneWire::write_bit( (bitMask & v)?1:0); + } + if ( !power) { + noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + DIRECT_WRITE_LOW(baseReg, bitmask); + interrupts(); + } +} + +void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) { + for (uint16_t i = 0 ; i < count ; i++) + write(buf[i]); + if (!power) { + noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + DIRECT_WRITE_LOW(baseReg, bitmask); + interrupts(); + } +} + +// +// Read a byte +// +uint8_t OneWire::read() { + uint8_t bitMask; + uint8_t r = 0; + + for (bitMask = 0x01; bitMask; bitMask <<= 1) { + if ( OneWire::read_bit()) r |= bitMask; + } + return r; +} + +void OneWire::read_bytes(uint8_t *buf, uint16_t count) { + for (uint16_t i = 0 ; i < count ; i++) + buf[i] = read(); +} + +// +// Do a ROM select +// +void OneWire::select(const uint8_t rom[8]) +{ + uint8_t i; + + write(0x55); // Choose ROM + + for (i = 0; i < 8; i++) write(rom[i]); +} + +// +// Do a ROM skip +// +void OneWire::skip() +{ + write(0xCC); // Skip ROM +} + +void OneWire::depower() +{ + noInterrupts(); + DIRECT_MODE_INPUT(baseReg, bitmask); + interrupts(); +} + +#if ONEWIRE_SEARCH + +// +// You need to use this function to start a search again from the beginning. +// You do not need to do it for the first search, though you could. +// +void OneWire::reset_search() +{ + // reset the search state + LastDiscrepancy = 0; + LastDeviceFlag = FALSE; + LastFamilyDiscrepancy = 0; + for(int i = 7; ; i--) { + ROM_NO[i] = 0; + if ( i == 0) break; + } +} + +// Setup the search to find the device type 'family_code' on the next call +// to search(*newAddr) if it is present. +// +void OneWire::target_search(uint8_t family_code) +{ + // set the search state to find SearchFamily type devices + ROM_NO[0] = family_code; + for (uint8_t i = 1; i < 8; i++) + ROM_NO[i] = 0; + LastDiscrepancy = 64; + LastFamilyDiscrepancy = 0; + LastDeviceFlag = FALSE; +} + +// +// Perform a search. If this function returns a '1' then it has +// enumerated the next device and you may retrieve the ROM from the +// OneWire::address variable. If there are no devices, no further +// devices, or something horrible happens in the middle of the +// enumeration then a 0 is returned. If a new device is found then +// its address is copied to newAddr. Use OneWire::reset_search() to +// start over. +// +// --- Replaced by the one from the Dallas Semiconductor web site --- +//-------------------------------------------------------------------------- +// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing +// search state. +// Return TRUE : device found, ROM number in ROM_NO buffer +// FALSE : device not found, end of search +// +uint8_t OneWire::search(uint8_t *newAddr, bool search_mode /* = true */) +{ + uint8_t id_bit_number; + uint8_t last_zero, rom_byte_number, search_result; + uint8_t id_bit, cmp_id_bit; + + unsigned char rom_byte_mask, search_direction; + + // initialize for search + id_bit_number = 1; + last_zero = 0; + rom_byte_number = 0; + rom_byte_mask = 1; + search_result = 0; + + // if the last call was not the last one + if (!LastDeviceFlag) + { + // 1-Wire reset + if (!reset()) + { + // reset the search + LastDiscrepancy = 0; + LastDeviceFlag = FALSE; + LastFamilyDiscrepancy = 0; + return FALSE; + } + + // issue the search command + if (search_mode == true) { + write(0xF0); // NORMAL SEARCH + } else { + write(0xEC); // CONDITIONAL SEARCH + } + + // loop to do the search + do + { + // read a bit and its complement + id_bit = read_bit(); + cmp_id_bit = read_bit(); + + // check for no devices on 1-wire + if ((id_bit == 1) && (cmp_id_bit == 1)) + break; + else + { + // all devices coupled have 0 or 1 + if (id_bit != cmp_id_bit) + search_direction = id_bit; // bit write value for search + else + { + // if this discrepancy if before the Last Discrepancy + // on a previous next then pick the same as last time + if (id_bit_number < LastDiscrepancy) + search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0); + else + // if equal to last pick 1, if not then pick 0 + search_direction = (id_bit_number == LastDiscrepancy); + + // if 0 was picked then record its position in LastZero + if (search_direction == 0) + { + last_zero = id_bit_number; + + // check for Last discrepancy in family + if (last_zero < 9) + LastFamilyDiscrepancy = last_zero; + } + } + + // set or clear the bit in the ROM byte rom_byte_number + // with mask rom_byte_mask + if (search_direction == 1) + ROM_NO[rom_byte_number] |= rom_byte_mask; + else + ROM_NO[rom_byte_number] &= ~rom_byte_mask; + + // serial number search direction write bit + write_bit(search_direction); + + // increment the byte counter id_bit_number + // and shift the mask rom_byte_mask + id_bit_number++; + rom_byte_mask <<= 1; + + // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask + if (rom_byte_mask == 0) + { + rom_byte_number++; + rom_byte_mask = 1; + } + } + } + while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 + + // if the search was successful then + if (!(id_bit_number < 65)) + { + // search successful so set LastDiscrepancy,LastDeviceFlag,search_result + LastDiscrepancy = last_zero; + + // check for last device + if (LastDiscrepancy == 0) + LastDeviceFlag = TRUE; + + search_result = TRUE; + } + } + + // if no device found then reset counters so next 'search' will be like a first + if (!search_result || !ROM_NO[0]) + { + LastDiscrepancy = 0; + LastDeviceFlag = FALSE; + LastFamilyDiscrepancy = 0; + search_result = FALSE; + } else { + for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; + } + return search_result; + } + +#endif + +#if ONEWIRE_CRC +// The 1-Wire CRC scheme is described in Maxim Application Note 27: +// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" +// + +#if ONEWIRE_CRC8_TABLE +// This table comes from Dallas sample code where it is freely reusable, +// though Copyright (C) 2000 Dallas Semiconductor Corporation +static const uint8_t PROGMEM dscrc_table[] = { + 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, + 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, + 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, + 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, + 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, + 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, + 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, + 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, + 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, + 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, + 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, + 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, + 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, + 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, + 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, + 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; + +// +// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM +// and the registers. (note: this might better be done without to +// table, it would probably be smaller and certainly fast enough +// compared to all those delayMicrosecond() calls. But I got +// confused, so I use this table from the examples.) +// +uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + + while (len--) { + crc = pgm_read_byte(dscrc_table + (crc ^ *addr++)); + } + return crc; +} +#else +// +// Compute a Dallas Semiconductor 8 bit CRC directly. +// this is much slower, but much smaller, than the lookup table. +// +uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + + while (len--) { +#if defined(__AVR__) + crc = _crc_ibutton_update(crc, *addr++); +#else + uint8_t inbyte = *addr++; + for (uint8_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) crc ^= 0x8C; + inbyte >>= 1; + } +#endif + } + return crc; +} +#endif + +#if ONEWIRE_CRC16 +bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc) +{ + crc = ~crc16(input, len, crc); + return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1]; +} + +uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc) +{ +#if defined(__AVR__) + for (uint16_t i = 0 ; i < len ; i++) { + crc = _crc16_update(crc, input[i]); + } +#else + static const uint8_t oddparity[16] = + { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; + + for (uint16_t i = 0 ; i < len ; i++) { + // Even though we're just copying a byte from the input, + // we'll be doing 16-bit computation with it. + uint16_t cdata = input[i]; + cdata = (cdata ^ crc) & 0xff; + crc >>= 8; + + if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4]) + crc ^= 0xC001; + + cdata <<= 6; + crc ^= cdata; + cdata <<= 1; + crc ^= cdata; + } +#endif + return crc; +} +#endif + +#endif diff --git a/lib/OneWire-2.3.3.06/OneWire.h b/lib/OneWire-2.3.3.06/OneWire.h new file mode 100644 index 000000000..c394f1d05 --- /dev/null +++ b/lib/OneWire-2.3.3.06/OneWire.h @@ -0,0 +1,545 @@ +#ifndef OneWire_h +#define OneWire_h + +#include + +#if defined(__AVR__) +#include +#endif + +#if ARDUINO >= 100 +#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc +#else +#include "WProgram.h" // for delayMicroseconds +#include "pins_arduino.h" // for digitalPinToBitMask, etc +#endif + +// You can exclude certain features from OneWire. In theory, this +// might save some space. In practice, the compiler automatically +// removes unused code (technically, the linker, using -fdata-sections +// and -ffunction-sections when compiling, and Wl,--gc-sections +// when linking), so most of these will not result in any code size +// reduction. Well, unless you try to use the missing features +// and redesign your program to not need them! ONEWIRE_CRC8_TABLE +// is the exception, because it selects a fast but large algorithm +// or a small but slow algorithm. + +// you can exclude onewire_search by defining that to 0 +#ifndef ONEWIRE_SEARCH +#define ONEWIRE_SEARCH 1 +#endif + +// You can exclude CRC checks altogether by defining this to 0 +#ifndef ONEWIRE_CRC +#define ONEWIRE_CRC 1 +#endif + +// Select the table-lookup method of computing the 8-bit CRC +// by setting this to 1. The lookup table enlarges code size by +// about 250 bytes. It does NOT consume RAM (but did in very +// old versions of OneWire). If you disable this, a slower +// but very compact algorithm is used. +#ifndef ONEWIRE_CRC8_TABLE +#define ONEWIRE_CRC8_TABLE 1 +#endif + +// You can allow 16-bit CRC checks by defining this to 1 +// (Note that ONEWIRE_CRC must also be 1.) +#ifndef ONEWIRE_CRC16 +#define ONEWIRE_CRC16 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +// Platform specific I/O definitions + +#if defined(__AVR__) +#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint8_t +#define IO_REG_BASE_ATTR asm("r30") +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) +#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) +#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) +#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) + +#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) +#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) +#define PIN_TO_BITMASK(pin) (1) +#define IO_REG_TYPE uint8_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR __attribute__ ((unused)) +#define DIRECT_READ(base, mask) (*((base)+512)) +#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) +#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) +#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) +#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) + +#elif defined(__MKL26Z64__) +#define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint8_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask)) +#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask)) +#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask)) + +#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) +// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due. +// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268 +// If you have trouble with OneWire on Arduino Due, please check the +// status of delayMicroseconds() before reporting a bug in OneWire! +#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER)) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) +#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) +#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) +#ifndef PROGMEM +#define PROGMEM +#endif +#ifndef pgm_read_byte +#define pgm_read_byte(addr) (*(const uint8_t *)(addr)) +#endif + +#elif defined(__PIC32MX__) +#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 +#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 +#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 +#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 +#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 + +#elif defined(ARDUINO_ARCH_ESP8266) +// Special note: I depend on the ESP community to maintain these definitions and +// submit good pull requests. I can not answer any ESP questions or help you +// resolve any problems related to ESP chips. Please do not contact me and please +// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked +// on ESP community forums. +#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) +#define PIN_TO_BITMASK(pin) (1 << pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS +#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS +#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS +#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS +#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS + +#elif defined(ARDUINO_ARCH_ESP32) +#include +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR + +static inline __attribute__((always_inline)) +IO_REG_TYPE directRead(IO_REG_TYPE pin) +{ + if ( pin < 32 ) + return (GPIO.in >> pin) & 0x1; + else if ( pin < 40 ) + return (GPIO.in1.val >> (pin - 32)) & 0x1; + + return 0; +} + +static inline __attribute__((always_inline)) +void directWriteLow(IO_REG_TYPE pin) +{ + if ( pin < 32 ) + GPIO.out_w1tc = ((uint32_t)1 << pin); + else if ( pin < 34 ) + GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); +} + +static inline __attribute__((always_inline)) +void directWriteHigh(IO_REG_TYPE pin) +{ + if ( pin < 32 ) + GPIO.out_w1ts = ((uint32_t)1 << pin); + else if ( pin < 34 ) + GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); +} + +static inline __attribute__((always_inline)) +void directModeInput(IO_REG_TYPE pin) +{ + if ( digitalPinIsValid(pin) ) + { + uint32_t rtc_reg(rtc_gpio_desc[pin].reg); + + if ( rtc_reg ) // RTC pins PULL settings + { + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); + } + + if ( pin < 32 ) + GPIO.enable_w1tc = ((uint32_t)1 << pin); + else + GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); + + uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? + pinFunction |= FUN_IE; // input enable but required for output as well? + pinFunction |= ((uint32_t)2 << MCU_SEL_S); + + ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; + + GPIO.pin[pin].val = 0; + } +} + +static inline __attribute__((always_inline)) +void directModeOutput(IO_REG_TYPE pin) +{ + if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs + { + uint32_t rtc_reg(rtc_gpio_desc[pin].reg); + + if ( rtc_reg ) // RTC pins PULL settings + { + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); + ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); + } + + if ( pin < 32 ) + GPIO.enable_w1ts = ((uint32_t)1 << pin); + else // already validated to pins <= 33 + GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); + + uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? + pinFunction |= FUN_IE; // input enable but required for output as well? + pinFunction |= ((uint32_t)2 << MCU_SEL_S); + + ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; + + GPIO.pin[pin].val = 0; + } +} + +#define DIRECT_READ(base, pin) directRead(pin) +#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin) +#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin) +#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin) +#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) +#warning "ESP32 OneWire testing" + +#elif defined(__SAMD21G18A__) +#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin)) +#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0) +#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask)) +#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask)) +#define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask)) +#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask)) + +#elif defined(RBL_NRF51822) +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin) +#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin) +#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin) +#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL) +#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin) + +#elif defined(__arc__) /* Arduino101/Genuino101 specifics */ + +#include "scss_registers.h" +#include "portable.h" +#include "avr/pgmspace.h" + +#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId) +#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType) +#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase) +#define DIR_OFFSET_SS 0x01 +#define DIR_OFFSET_SOC 0x04 +#define EXT_PORT_OFFSET_SS 0x0A +#define EXT_PORT_OFFSET_SOC 0x50 + +/* GPIO registers base address */ +#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase) +#define PIN_TO_BITMASK(pin) pin +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR + +static inline __attribute__((always_inline)) +IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + IO_REG_TYPE ret; + if (SS_GPIO == GPIO_TYPE(pin)) { + ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS)); + } else { + ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC); + } + return ((ret >> GPIO_ID(pin)) & 0x01); +} + +static inline __attribute__((always_inline)) +void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), + ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); + } else { + MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin)); + } +} + +static inline __attribute__((always_inline)) +void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), + ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); + } else { + MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin)); + } +} + +static inline __attribute__((always_inline)) +void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base); + } else { + MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin)); + } +} + +static inline __attribute__((always_inline)) +void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) +{ + if (SS_GPIO == GPIO_TYPE(pin)) { + WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base); + } else { + MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin)); + } +} + +#define DIRECT_READ(base, pin) directRead(base, pin) +#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin) +#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin) +#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin) +#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin) + +#elif defined(__riscv) + +/* + * Tested on highfive1 + * + * Stable results are achieved operating in the + * two high speed modes of the highfive1. It + * seems to be less reliable in slow mode. + */ +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin) +#define IO_REG_TYPE uint32_t +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR + +static inline __attribute__((always_inline)) +IO_REG_TYPE directRead(IO_REG_TYPE mask) +{ + return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0; +} + +static inline __attribute__((always_inline)) +void directModeInput(IO_REG_TYPE mask) +{ + GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; + GPIO_REG(GPIO_IOF_EN) &= ~mask; + + GPIO_REG(GPIO_INPUT_EN) |= mask; + GPIO_REG(GPIO_OUTPUT_EN) &= ~mask; +} + +static inline __attribute__((always_inline)) +void directModeOutput(IO_REG_TYPE mask) +{ + GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; + GPIO_REG(GPIO_IOF_EN) &= ~mask; + + GPIO_REG(GPIO_INPUT_EN) &= ~mask; + GPIO_REG(GPIO_OUTPUT_EN) |= mask; +} + +static inline __attribute__((always_inline)) +void directWriteLow(IO_REG_TYPE mask) +{ + GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask; +} + +static inline __attribute__((always_inline)) +void directWriteHigh(IO_REG_TYPE mask) +{ + GPIO_REG(GPIO_OUTPUT_VAL) |= mask; +} + +#define DIRECT_READ(base, mask) directRead(mask) +#define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask) +#define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask) +#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask) +#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask) + +#else +#define PIN_TO_BASEREG(pin) (0) +#define PIN_TO_BITMASK(pin) (pin) +#define IO_REG_TYPE unsigned int +#define IO_REG_BASE_ATTR +#define IO_REG_MASK_ATTR +#define DIRECT_READ(base, pin) digitalRead(pin) +#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW) +#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH) +#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT) +#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT) +#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture." + +#endif + + +class OneWire +{ + private: + IO_REG_TYPE bitmask; + volatile IO_REG_TYPE *baseReg; + +#if ONEWIRE_SEARCH + // global search state + unsigned char ROM_NO[8]; + uint8_t LastDiscrepancy; + uint8_t LastFamilyDiscrepancy; + uint8_t LastDeviceFlag; +#endif + + public: + OneWire( uint8_t pin); + + // Perform a 1-Wire reset cycle. Returns 1 if a device responds + // with a presence pulse. Returns 0 if there is no device or the + // bus is shorted or otherwise held low for more than 250uS + uint8_t reset(void); + + // Issue a 1-Wire rom select command, you do the reset first. + void select(const uint8_t rom[8]); + + // Issue a 1-Wire rom skip command, to address all on bus. + void skip(void); + + // Write a byte. If 'power' is one then the wire is held high at + // the end for parasitically powered devices. You are responsible + // for eventually depowering it by calling depower() or doing + // another read or write. + void write(uint8_t v, uint8_t power = 0); + + void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); + + // Read a byte. + uint8_t read(void); + + void read_bytes(uint8_t *buf, uint16_t count); + + // Write a bit. The bus is always left powered at the end, see + // note in write() about that. + void write_bit(uint8_t v); + + // Read a bit. + uint8_t read_bit(void); + + // Stop forcing power onto the bus. You only need to do this if + // you used the 'power' flag to write() or used a write_bit() call + // and aren't about to do another read or write. You would rather + // not leave this powered if you don't have to, just in case + // someone shorts your bus. + void depower(void); + +#if ONEWIRE_SEARCH + // Clear the search state so that if will start from the beginning again. + void reset_search(); + + // Setup the search to find the device type 'family_code' on the next call + // to search(*newAddr) if it is present. + void target_search(uint8_t family_code); + + // Look for the next device. Returns 1 if a new address has been + // returned. A zero might mean that the bus is shorted, there are + // no devices, or you have already retrieved all of them. It + // might be a good idea to check the CRC to make sure you didn't + // get garbage. The order is deterministic. You will always get + // the same devices in the same order. + uint8_t search(uint8_t *newAddr, bool search_mode = true); +#endif + +#if ONEWIRE_CRC + // Compute a Dallas Semiconductor 8 bit CRC, these are used in the + // ROM and scratchpad registers. + static uint8_t crc8(const uint8_t *addr, uint8_t len); + +#if ONEWIRE_CRC16 + // Compute the 1-Wire CRC16 and compare it against the received CRC. + // Example usage (reading a DS2408): + // // Put everything in a buffer so we can compute the CRC easily. + // uint8_t buf[13]; + // buf[0] = 0xF0; // Read PIO Registers + // buf[1] = 0x88; // LSB address + // buf[2] = 0x00; // MSB address + // WriteBytes(net, buf, 3); // Write 3 cmd bytes + // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 + // if (!CheckCRC16(buf, 11, &buf[11])) { + // // Handle error. + // } + // + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param inverted_crc - The two CRC16 bytes in the received data. + // This should just point into the received data, + // *not* at a 16-bit integer. + // @param crc - The crc starting value (optional) + // @return True, iff the CRC matches. + static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); + + // Compute a Dallas Semiconductor 16 bit CRC. This is required to check + // the integrity of data received from many 1-Wire devices. Note that the + // CRC computed here is *not* what you'll get from the 1-Wire network, + // for two reasons: + // 1) The CRC is transmitted bitwise inverted. + // 2) Depending on the endian-ness of your processor, the binary + // representation of the two-byte return value may have a different + // byte order than the two bytes you get from 1-Wire. + // @param input - Array of bytes to checksum. + // @param len - How many bytes to use. + // @param crc - The crc starting value (optional) + // @return The CRC16, as defined by Dallas Semiconductor. + static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); +#endif +#endif +}; + +#endif diff --git a/lib/OneWire-2.3.3.06/examples/DS18x20_Temperature/DS18x20_Temperature.pde b/lib/OneWire-2.3.3.06/examples/DS18x20_Temperature/DS18x20_Temperature.pde new file mode 100644 index 000000000..68ca19432 --- /dev/null +++ b/lib/OneWire-2.3.3.06/examples/DS18x20_Temperature/DS18x20_Temperature.pde @@ -0,0 +1,112 @@ +#include + +// OneWire DS18S20, DS18B20, DS1822 Temperature Example +// +// http://www.pjrc.com/teensy/td_libs_OneWire.html +// +// The DallasTemperature library can do all this work for you! +// http://milesburton.com/Dallas_Temperature_Control_Library + +OneWire ds(10); // on pin 10 (a 4.7K resistor is necessary) + +void setup(void) { + Serial.begin(9600); +} + +void loop(void) { + byte i; + byte present = 0; + byte type_s; + byte data[12]; + byte addr[8]; + float celsius, fahrenheit; + + if ( !ds.search(addr)) { + Serial.println("No more addresses."); + Serial.println(); + ds.reset_search(); + delay(250); + return; + } + + Serial.print("ROM ="); + for( i = 0; i < 8; i++) { + Serial.write(' '); + Serial.print(addr[i], HEX); + } + + if (OneWire::crc8(addr, 7) != addr[7]) { + Serial.println("CRC is not valid!"); + return; + } + Serial.println(); + + // the first ROM byte indicates which chip + switch (addr[0]) { + case 0x10: + Serial.println(" Chip = DS18S20"); // or old DS1820 + type_s = 1; + break; + case 0x28: + Serial.println(" Chip = DS18B20"); + type_s = 0; + break; + case 0x22: + Serial.println(" Chip = DS1822"); + type_s = 0; + break; + default: + Serial.println("Device is not a DS18x20 family device."); + return; + } + + ds.reset(); + ds.select(addr); + ds.write(0x44, 1); // start conversion, with parasite power on at the end + + delay(1000); // maybe 750ms is enough, maybe not + // we might do a ds.depower() here, but the reset will take care of it. + + present = ds.reset(); + ds.select(addr); + ds.write(0xBE); // Read Scratchpad + + Serial.print(" Data = "); + Serial.print(present, HEX); + Serial.print(" "); + for ( i = 0; i < 9; i++) { // we need 9 bytes + data[i] = ds.read(); + Serial.print(data[i], HEX); + Serial.print(" "); + } + Serial.print(" CRC="); + Serial.print(OneWire::crc8(data, 8), HEX); + Serial.println(); + + // Convert the data to actual temperature + // because the result is a 16 bit signed integer, it should + // be stored to an "int16_t" type, which is always 16 bits + // even when compiled on a 32 bit processor. + int16_t raw = (data[1] << 8) | data[0]; + if (type_s) { + raw = raw << 3; // 9 bit resolution default + if (data[7] == 0x10) { + // "count remain" gives full 12 bit resolution + raw = (raw & 0xFFF0) + 12 - data[6]; + } + } else { + byte cfg = (data[4] & 0x60); + // at lower res, the low bits are undefined, so let's zero them + if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms + else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms + else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms + //// default is 12 bit resolution, 750 ms conversion time + } + celsius = (float)raw / 16.0; + fahrenheit = celsius * 1.8 + 32.0; + Serial.print(" Temperature = "); + Serial.print(celsius); + Serial.print(" Celsius, "); + Serial.print(fahrenheit); + Serial.println(" Fahrenheit"); +} diff --git a/lib/OneWire-2.3.3.06/examples/DS2408_Switch/DS2408_Switch.pde b/lib/OneWire-2.3.3.06/examples/DS2408_Switch/DS2408_Switch.pde new file mode 100644 index 000000000..b70eda97a --- /dev/null +++ b/lib/OneWire-2.3.3.06/examples/DS2408_Switch/DS2408_Switch.pde @@ -0,0 +1,74 @@ +#include + +/* + * DS2408 8-Channel Addressable Switch + * + * Writte by Glenn Trewitt, glenn at trewitt dot org + * + * Some notes about the DS2408: + * - Unlike most input/output ports, the DS2408 doesn't have mode bits to + * set whether the pins are input or output. If you issue a read command, + * they're inputs. If you write to them, they're outputs. + * - For reading from a switch, you should use 10K pull-up resisters. + */ + +OneWire net(10); // on pin 10 + + +void PrintBytes(const uint8_t* addr, uint8_t count, bool newline=false) { + for (uint8_t i = 0; i < count; i++) { + Serial.print(addr[i]>>4, HEX); + Serial.print(addr[i]&0x0f, HEX); + } + if (newline) + Serial.println(); +} + + +void setup(void) { + Serial.begin(9600); +} + +void loop(void) { + byte addr[8]; + + if (!net.search(addr)) { + Serial.print("No more addresses.\n"); + net.reset_search(); + delay(1000); + return; + } + + if (OneWire::crc8(addr, 7) != addr[7]) { + Serial.print("CRC is not valid!\n"); + return; + } + + if (addr[0] != 0x29) { + PrintBytes(addr, 8); + Serial.print(" is not a DS2408.\n"); + return; + } + + Serial.print(" Reading DS2408 "); + PrintBytes(addr, 8); + Serial.println(); + + uint8_t buf[13]; // Put everything in the buffer so we can compute CRC easily. + buf[0] = 0xF0; // Read PIO Registers + buf[1] = 0x88; // LSB address + buf[2] = 0x00; // MSB address + net.write_bytes(buf, 3); + net.read_bytes(buf+3, 10); // 3 cmd bytes, 6 data bytes, 2 0xFF, 2 CRC16 + net.reset(); + + if (!OneWire::check_crc16(buf, 11, &buf[11])) { + Serial.print("CRC failure in DS2408 at "); + PrintBytes(addr, 8, true); + return; + } + Serial.print(" DS2408 data = "); + // First 3 bytes contain command, register address. + Serial.println(buf[3], BIN); +} + diff --git a/lib/OneWire-2.3.3.06/examples/DS250x_PROM/DS250x_PROM.pde b/lib/OneWire-2.3.3.06/examples/DS250x_PROM/DS250x_PROM.pde new file mode 100644 index 000000000..a85b1c292 --- /dev/null +++ b/lib/OneWire-2.3.3.06/examples/DS250x_PROM/DS250x_PROM.pde @@ -0,0 +1,90 @@ +/* +DS250x add-only programmable memory reader w/SKIP ROM. + + The DS250x is a 512/1024bit add-only PROM(you can add data but cannot change the old one) that's used mainly for device identification purposes + like serial number, mfgr data, unique identifiers, etc. It uses the Maxim 1-wire bus. + + This sketch will use the SKIP ROM function that skips the 1-Wire search phase since we only have one device connected in the bus on digital pin 6. + If more than one device is connected to the bus, it will fail. + Sketch will not verify if device connected is from the DS250x family since the skip rom function effectively skips the family-id byte readout. + thus it is possible to run this sketch with any Maxim OneWire device in which case the command CRC will most likely fail. + Sketch will only read the first page of memory(32bits) starting from the lower address(0000h), if more than 1 device is present, then use the sketch with search functions. + Remember to put a 4.7K pullup resistor between pin 6 and +Vcc + + To change the range or ammount of data to read, simply change the data array size, LSB/MSB addresses and for loop iterations + + This example code is in the public domain and is provided AS-IS. + + Built with Arduino 0022 and PJRC OneWire 2.0 library http://www.pjrc.com/teensy/td_libs_OneWire.html + + created by Guillermo Lovato + march/2011 + + */ + +#include +OneWire ds(6); // OneWire bus on digital pin 6 +void setup() { + Serial.begin (9600); +} + +void loop() { + byte i; // This is for the for loops + boolean present; // device present var + byte data[32]; // container for the data from device + byte leemem[3] = { // array with the commands to initiate a read, DS250x devices expect 3 bytes to start a read: command,LSB&MSB adresses + 0xF0 , 0x00 , 0x00 }; // 0xF0 is the Read Data command, followed by 00h 00h as starting address(the beginning, 0000h) + byte ccrc; // Variable to store the command CRC + byte ccrc_calc; + + present = ds.reset(); // OneWire bus reset, always needed to start operation on the bus, returns a 1/TRUE if there's a device present. + ds.skip(); // Skip ROM search + + if (present == TRUE){ // We only try to read the data if there's a device present + Serial.println("DS250x device present"); + ds.write(leemem[0],1); // Read data command, leave ghost power on + ds.write(leemem[1],1); // LSB starting address, leave ghost power on + ds.write(leemem[2],1); // MSB starting address, leave ghost power on + + ccrc = ds.read(); // DS250x generates a CRC for the command we sent, we assign a read slot and store it's value + ccrc_calc = OneWire::crc8(leemem, 3); // We calculate the CRC of the commands we sent using the library function and store it + + if ( ccrc_calc != ccrc) { // Then we compare it to the value the ds250x calculated, if it fails, we print debug messages and abort + Serial.println("Invalid command CRC!"); + Serial.print("Calculated CRC:"); + Serial.println(ccrc_calc,HEX); // HEX makes it easier to observe and compare + Serial.print("DS250x readback CRC:"); + Serial.println(ccrc,HEX); + return; // Since CRC failed, we abort the rest of the loop and start over + } + Serial.println("Data is: "); // For the printout of the data + for ( i = 0; i < 32; i++) { // Now it's time to read the PROM data itself, each page is 32 bytes so we need 32 read commands + data[i] = ds.read(); // we store each read byte to a different position in the data array + Serial.print(data[i]); // printout in ASCII + Serial.print(" "); // blank space + } + Serial.println(); + delay(5000); // Delay so we don't saturate the serial output + } + else { // Nothing is connected in the bus + Serial.println("Nothing connected"); + delay(3000); + } +} + + + + + + + + + + + + + + + + + diff --git a/lib/OneWire-2.3.3.06/keywords.txt b/lib/OneWire-2.3.3.06/keywords.txt new file mode 100644 index 000000000..bee5d90b2 --- /dev/null +++ b/lib/OneWire-2.3.3.06/keywords.txt @@ -0,0 +1,38 @@ +####################################### +# Syntax Coloring Map For OneWire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +OneWire KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +reset KEYWORD2 +write_bit KEYWORD2 +read_bit KEYWORD2 +write KEYWORD2 +write_bytes KEYWORD2 +read KEYWORD2 +read_bytes KEYWORD2 +select KEYWORD2 +skip KEYWORD2 +depower KEYWORD2 +reset_search KEYWORD2 +search KEYWORD2 +crc8 KEYWORD2 +crc16 KEYWORD2 +check_crc16 KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/lib/OneWire-2.3.3.06/library.json b/lib/OneWire-2.3.3.06/library.json new file mode 100644 index 000000000..1e95e2e9f --- /dev/null +++ b/lib/OneWire-2.3.3.06/library.json @@ -0,0 +1,61 @@ +{ + "name": "OneWire", + "description": "Control 1-Wire protocol (DS18S20, DS18B20, DS2408 and etc)", + "keywords": "onewire, 1-wire, bus, sensor, temperature, ibutton", + "authors": [ + { + "name": "Paul Stoffregen", + "email": "paul@pjrc.com", + "url": "http://www.pjrc.com", + "maintainer": true + }, + { + "name": "Jim Studt" + }, + { + "name": "Tom Pollard", + "email": "pollard@alum.mit.edu" + }, + { + "name": "Derek Yerger" + }, + { + "name": "Josh Larios" + }, + { + "name": "Robin James" + }, + { + "name": "Glenn Trewitt" + }, + { + "name": "Jason Dangel", + "email": "dangel.jason AT gmail.com" + }, + { + "name": "Guillermo Lovato" + }, + { + "name": "Ken Butcher" + }, + { + "name": "Mark Tillotson" + }, + { + "name": "Bertrik Sikken" + }, + { + "name": "Scott Roberts" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/PaulStoffregen/OneWire" + }, + "version": "2.3.2", + "homepage": "https://www.pjrc.com/teensy/td_libs_OneWire.html", + "frameworks": "Arduino", + "examples": [ + "examples/*/*.pde" + ] +} diff --git a/lib/OneWire-2.3.3.06/library.properties b/lib/OneWire-2.3.3.06/library.properties new file mode 100644 index 000000000..cd8fc05f7 --- /dev/null +++ b/lib/OneWire-2.3.3.06/library.properties @@ -0,0 +1,10 @@ +name=OneWire +version=2.3.3 +author=Jim Studt, Tom Pollard, Robin James, Glenn Trewitt, Jason Dangel, Guillermo Lovato, Paul Stoffregen, Scott Roberts, Bertrik Sikken, Mark Tillotson, Ken Butcher, Roger Clark, Love Nystrom +maintainer=Paul Stoffregen +sentence=Access 1-wire temperature sensors, memory and other chips. +paragraph= +category=Communication +url=http://www.pjrc.com/teensy/td_libs_OneWire.html +architectures=* + diff --git a/lib/PubSubClient-2.6.09/.gitignore b/lib/PubSubClient-2.6.09/.gitignore new file mode 100644 index 000000000..1c3ba189b --- /dev/null +++ b/lib/PubSubClient-2.6.09/.gitignore @@ -0,0 +1 @@ +tests/bin diff --git a/lib/PubSubClient-2.6.09/.travis.yml b/lib/PubSubClient-2.6.09/.travis.yml new file mode 100644 index 000000000..e7b28cb9c --- /dev/null +++ b/lib/PubSubClient-2.6.09/.travis.yml @@ -0,0 +1,7 @@ +sudo: false +language: cpp +compiler: + - g++ +script: cd tests && make && make test +os: + - linux diff --git a/lib/PubSubClient-2.6.09/CHANGES.txt b/lib/PubSubClient-2.6.09/CHANGES.txt new file mode 100644 index 000000000..8c8bef64e --- /dev/null +++ b/lib/PubSubClient-2.6.09/CHANGES.txt @@ -0,0 +1,68 @@ +2.4 + * Add MQTT_SOCKET_TIMEOUT to prevent it blocking indefinitely + whilst waiting for inbound data + * Fixed return code when publishing >256 bytes + +2.3 + * Add publish(topic,payload,retained) function + +2.2 + * Change code layout to match Arduino Library reqs + +2.1 + * Add MAX_TRANSFER_SIZE def to chunk messages if needed + * Reject topic/payloads that exceed MQTT_MAX_PACKET_SIZE + +2.0 + * Add (and default to) MQTT 3.1.1 support + * Fix PROGMEM handling for Intel Galileo/ESP8266 + * Add overloaded constructors for convenience + * Add chainable setters for server/callback/client/stream + * Add state function to return connack return code + +1.9 + * Do not split MQTT packets over multiple calls to _client->write() + * API change: All constructors now require an instance of Client + to be passed in. + * Fixed example to match 1.8 api changes - dpslwk + * Added username/password support - WilHall + * Added publish_P - publishes messages from PROGMEM - jobytaffey + +1.8 + * KeepAlive interval is configurable in PubSubClient.h + * Maximum packet size is configurable in PubSubClient.h + * API change: Return boolean rather than int from various functions + * API change: Length parameter in message callback changed + from int to unsigned int + * Various internal tidy-ups around types +1.7 + * Improved keepalive handling + * Updated to the Arduino-1.0 API +1.6 + * Added the ability to publish a retained message + +1.5 + * Added default constructor + * Fixed compile error when used with arduino-0021 or later + +1.4 + * Fixed connection lost handling + +1.3 + * Fixed packet reading bug in PubSubClient.readPacket + +1.2 + * Fixed compile error when used with arduino-0016 or later + + +1.1 + * Reduced size of library + * Added support for Will messages + * Clarified licensing - see LICENSE.txt + + +1.0 + * Only Quality of Service (QOS) 0 messaging is supported + * The maximum message size, including header, is 128 bytes + * The keepalive interval is set to 30 seconds + * No support for Will messages diff --git a/lib/PubSubClient-2.6.09/LICENSE.txt b/lib/PubSubClient-2.6.09/LICENSE.txt new file mode 100644 index 000000000..217df35cc --- /dev/null +++ b/lib/PubSubClient-2.6.09/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2015 Nicholas O'Leary + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation 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 furnished 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 FOR 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. diff --git a/lib/PubSubClient-2.6.09/README.md b/lib/PubSubClient-2.6.09/README.md new file mode 100644 index 000000000..83176919c --- /dev/null +++ b/lib/PubSubClient-2.6.09/README.md @@ -0,0 +1,47 @@ +# Arduino Client for MQTT + +This library provides a client for doing simple publish/subscribe messaging with +a server that supports MQTT. + +## Examples + +The library comes with a number of example sketches. See File > Examples > PubSubClient +within the Arduino application. + +Full API documentation is available here: http://pubsubclient.knolleary.net + +## Limitations + + - It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1. + - The maximum message size, including header, is **128 bytes** by default. This + is configurable via `MQTT_MAX_PACKET_SIZE` in `PubSubClient.h`. + - The keepalive interval is set to 15 seconds by default. This is configurable + via `MQTT_KEEPALIVE` in `PubSubClient.h`. + - The client uses MQTT 3.1.1 by default. It can be changed to use MQTT 3.1 by + changing value of `MQTT_VERSION` in `PubSubClient.h`. + + +## Compatible Hardware + +The library uses the Arduino Ethernet Client api for interacting with the +underlying network hardware. This means it Just Works with a growing number of +boards and shields, including: + + - Arduino Ethernet + - Arduino Ethernet Shield + - Arduino YUN – use the included `YunClient` in place of `EthernetClient`, and + be sure to do a `Bridge.begin()` first + - Arduino WiFi Shield - if you want to send packets > 90 bytes with this shield, + enable the `MQTT_MAX_TRANSFER_SIZE` define in `PubSubClient.h`. + - Sparkfun WiFly Shield – [library](https://github.com/dpslwk/WiFly) + - TI CC3000 WiFi - [library](https://github.com/sparkfun/SFE_CC3000_Library) + - Intel Galileo/Edison + - ESP8266 + +The library cannot currently be used with hardware based on the ENC28J60 chip – +such as the Nanode or the Nuelectronics Ethernet Shield. For those, there is an +[alternative library](https://github.com/njh/NanodeMQTT) available. + +## License + +This code is released under the MIT License. diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino b/lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino new file mode 100644 index 000000000..e9f7b180f --- /dev/null +++ b/lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino @@ -0,0 +1,43 @@ +/* + Basic MQTT example with Authentication + + - connects to an MQTT server, providing username + and password + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +void setup() +{ + Ethernet.begin(mac, ip); + // Note - the default maximum packet size is 128 bytes. If the + // combined length of clientId, username and password exceed this, + // you will need to increase the value of MQTT_MAX_PACKET_SIZE in + // PubSubClient.h + + if (client.connect("arduinoClient", "testuser", "testpass")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino b/lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino new file mode 100644 index 000000000..f545adef8 --- /dev/null +++ b/lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino @@ -0,0 +1,77 @@ +/* + Basic MQTT example + + This sketch demonstrates the basic capabilities of the library. + It connects to an MQTT server then: + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic", printing out any messages + it receives. NB - it assumes the received payloads are strings not binary + + It will reconnect to the server if the connection is lost using a blocking + reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to + achieve the same result without blocking the main loop. + +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (int i=0;i Preferences -> Additional Boards Manager URLs": + http://arduino.esp8266.com/stable/package_esp8266com_index.json + - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" + - Select your ESP8266 in "Tools -> Board" + +*/ + +#include +#include + +// Update these with values suitable for your network. + +const char* ssid = "........"; +const char* password = "........"; +const char* mqtt_server = "broker.mqtt-dashboard.com"; + +WiFiClient espClient; +PubSubClient client(espClient); +long lastMsg = 0; +char msg[50]; +int value = 0; + +void setup_wifi() { + + delay(10); + // We start by connecting to a WiFi network + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + randomSeed(micros()); + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); + + // Switch on the LED if an 1 was received as first character + if ((char)payload[0] == '1') { + digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level + // but actually the LED is on; this is because + // it is acive low on the ESP-01) + } else { + digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH + } + +} + +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Create a random client ID + String clientId = "ESP8266Client-"; + clientId += String(random(0xffff), HEX); + // Attempt to connect + if (client.connect(clientId.c_str())) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.publish("outTopic", "hello world"); + // ... and resubscribe + client.subscribe("inTopic"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void setup() { + pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(mqtt_server, 1883); + client.setCallback(callback); +} + +void loop() { + + if (!client.connected()) { + reconnect(); + } + client.loop(); + + long now = millis(); + if (now - lastMsg > 2000) { + lastMsg = now; + ++value; + snprintf (msg, 75, "hello world #%ld", value); + Serial.print("Publish message: "); + Serial.println(msg); + client.publish("outTopic", msg); + } +} diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino new file mode 100644 index 000000000..42afb2a3a --- /dev/null +++ b/lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino @@ -0,0 +1,60 @@ +/* + Publishing in the callback + + - connects to an MQTT server + - subscribes to the topic "inTopic" + - when a message is received, republishes it to "outTopic" + + This example shows how to publish messages within the + callback function. The callback function header needs to + be declared before the PubSubClient constructor and the + actual callback defined afterwards. + This ensures the client reference in the callback function + is valid. + +*/ + +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +// Callback function header +void callback(char* topic, byte* payload, unsigned int length); + +EthernetClient ethClient; +PubSubClient client(server, 1883, callback, ethClient); + +// Callback function +void callback(char* topic, byte* payload, unsigned int length) { + // In order to republish this payload, a copy must be made + // as the orignal payload buffer will be overwritten whilst + // constructing the PUBLISH packet. + + // Allocate the correct amount of memory for the payload copy + byte* p = (byte*)malloc(length); + // Copy the payload to the new buffer + memcpy(p,payload,length); + client.publish("outTopic", p, length); + // Free the memory + free(p); +} + +void setup() +{ + + Ethernet.begin(mac, ip); + if (client.connect("arduinoClient")) { + client.publish("outTopic","hello world"); + client.subscribe("inTopic"); + } +} + +void loop() +{ + client.loop(); +} diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino new file mode 100644 index 000000000..080b7391c --- /dev/null +++ b/lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino @@ -0,0 +1,67 @@ +/* + Reconnecting MQTT example - non-blocking + + This sketch demonstrates how to keep the client connected + using a non-blocking reconnect function. If the client loses + its connection, it attempts to reconnect every 5 seconds + without blocking the main loop. + +*/ + +#include +#include +#include + +// Update these with values suitable for your hardware/network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +EthernetClient ethClient; +PubSubClient client(ethClient); + +long lastReconnectAttempt = 0; + +boolean reconnect() { + if (client.connect("arduinoClient")) { + // Once connected, publish an announcement... + client.publish("outTopic","hello world"); + // ... and resubscribe + client.subscribe("inTopic"); + } + return client.connected(); +} + +void setup() +{ + client.setServer(server, 1883); + client.setCallback(callback); + + Ethernet.begin(mac, ip); + delay(1500); + lastReconnectAttempt = 0; +} + + +void loop() +{ + if (!client.connected()) { + long now = millis(); + if (now - lastReconnectAttempt > 5000) { + lastReconnectAttempt = now; + // Attempt to reconnect + if (reconnect()) { + lastReconnectAttempt = 0; + } + } + } else { + // Client connected + + client.loop(); + } + +} diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino b/lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino new file mode 100644 index 000000000..67c22872c --- /dev/null +++ b/lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino @@ -0,0 +1,57 @@ +/* + Example of using a Stream object to store the message payload + + Uses SRAM library: https://github.com/ennui2342/arduino-sram + but could use any Stream based class such as SD + + - connects to an MQTT server + - publishes "hello world" to the topic "outTopic" + - subscribes to the topic "inTopic" +*/ + +#include +#include +#include +#include + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +IPAddress ip(172, 16, 0, 100); +IPAddress server(172, 16, 0, 2); + +SRAM sram(4, SRAM_1024); + +void callback(char* topic, byte* payload, unsigned int length) { + sram.seek(1); + + // do something with the message + for(uint8_t i=0; i +maintainer=Nick O'Leary +sentence=A client library for MQTT messaging. +paragraph=MQTT is a lightweight messaging protocol ideal for small devices. This library allows you to send and receive MQTT messages. It supports the latest MQTT 3.1.1 protocol and can be configured to use the older MQTT 3.1 if needed. It supports all Arduino Ethernet Client compatible hardware, including the Intel Galileo/Edison, ESP8266 and TI CC3000. +category=Communication +url=http://pubsubclient.knolleary.net +architectures=* diff --git a/lib/PubSubClient-2.6.09/src/PubSubClient.cpp b/lib/PubSubClient-2.6.09/src/PubSubClient.cpp new file mode 100644 index 000000000..11e1c874a --- /dev/null +++ b/lib/PubSubClient-2.6.09/src/PubSubClient.cpp @@ -0,0 +1,589 @@ +/* + PubSubClient.cpp - A simple client for MQTT. + Nick O'Leary + http://knolleary.net +*/ + +#include "PubSubClient.h" +#include "Arduino.h" + +PubSubClient::PubSubClient() { + this->_state = MQTT_DISCONNECTED; + this->_client = NULL; + this->stream = NULL; + setCallback(NULL); +} + +PubSubClient::PubSubClient(Client& client) { + this->_state = MQTT_DISCONNECTED; + setClient(client); + this->stream = NULL; +} + +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(addr, port); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(addr,port); + setClient(client); + setStream(stream); +} +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(addr, port); + setCallback(callback); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(addr,port); + setCallback(callback); + setClient(client); + setStream(stream); +} + +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(ip, port); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(ip,port); + setClient(client); + setStream(stream); +} +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(ip, port); + setCallback(callback); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(uint8_t *ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(ip,port); + setCallback(callback); + setClient(client); + setStream(stream); +} + +PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(const char* domain, uint16_t port, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setClient(client); + setStream(stream); +} +PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setCallback(callback); + setClient(client); + this->stream = NULL; +} +PubSubClient::PubSubClient(const char* domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) { + this->_state = MQTT_DISCONNECTED; + setServer(domain,port); + setCallback(callback); + setClient(client); + setStream(stream); +} + +boolean PubSubClient::connect(const char *id) { + return connect(id,NULL,NULL,0,0,0,0); +} + +boolean PubSubClient::connect(const char *id, const char *user, const char *pass) { + return connect(id,user,pass,0,0,0,0); +} + +boolean PubSubClient::connect(const char *id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { + return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage); +} + +boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage) { + if (!connected()) { + int result = 0; + + if (domain != NULL) { + result = _client->connect(this->domain, this->port); + } else { + result = _client->connect(this->ip, this->port); + } + if (result == 1) { + nextMsgId = 1; + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + unsigned int j; + +#if MQTT_VERSION == MQTT_VERSION_3_1 + uint8_t d[9] = {0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION}; +#define MQTT_HEADER_VERSION_LENGTH 9 +#elif MQTT_VERSION == MQTT_VERSION_3_1_1 + uint8_t d[7] = {0x00,0x04,'M','Q','T','T',MQTT_VERSION}; +#define MQTT_HEADER_VERSION_LENGTH 7 +#endif + for (j = 0;j>1); + } + } + + buffer[length++] = v; + + buffer[length++] = ((MQTT_KEEPALIVE) >> 8); + buffer[length++] = ((MQTT_KEEPALIVE) & 0xFF); + length = writeString(id,buffer,length); + if (willTopic) { + length = writeString(willTopic,buffer,length); + length = writeString(willMessage,buffer,length); + } + + if(user != NULL) { + length = writeString(user,buffer,length); + if(pass != NULL) { + length = writeString(pass,buffer,length); + } + } + + write(MQTTCONNECT,buffer,length-5); + + lastInActivity = lastOutActivity = millis(); + + while (!_client->available()) { + unsigned long t = millis(); + if (t-lastInActivity >= ((int32_t) MQTT_SOCKET_TIMEOUT*1000UL)) { + _state = MQTT_CONNECTION_TIMEOUT; + _client->stop(); + return false; + } + } + uint8_t llen; + uint16_t len = readPacket(&llen); + + if (len == 4) { + if (buffer[3] == 0) { + lastInActivity = millis(); + pingOutstanding = false; + _state = MQTT_CONNECTED; + return true; + } else { + _state = buffer[3]; + } + } + _client->stop(); + } else { + _state = MQTT_CONNECT_FAILED; + } + return false; + } + return true; +} + +// reads a byte into result +boolean PubSubClient::readByte(uint8_t * result) { + uint32_t previousMillis = millis(); + while(!_client->available()) { + delay(1); // Add esp8266 de-blocking (Tasmota #790) + uint32_t currentMillis = millis(); + if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ + return false; + } + } + *result = _client->read(); + return true; +} + +// reads a byte into result[*index] and increments index +boolean PubSubClient::readByte(uint8_t * result, uint16_t * index){ + uint16_t current_index = *index; + uint8_t * write_address = &(result[current_index]); + if(readByte(write_address)){ + *index = current_index + 1; + return true; + } + return false; +} + +uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { + uint16_t len = 0; + if(!readByte(buffer, &len)) return 0; + bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH; + uint32_t multiplier = 1; + uint16_t length = 0; + uint8_t digit = 0; + uint16_t skip = 0; + uint8_t start = 0; + + do { + if(!readByte(&digit)) return 0; + buffer[len++] = digit; + length += (digit & 127) * multiplier; + multiplier *= 128; + } while ((digit & 128) != 0); + *lengthLength = len-1; + + if (isPublish) { + // Read in topic length to calculate bytes to skip over for Stream writing + if(!readByte(buffer, &len)) return 0; + if(!readByte(buffer, &len)) return 0; + skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2]; + start = 2; + if (buffer[0]&MQTTQOS1) { + // skip message id + skip += 2; + } + } + + for (uint16_t i = start;istream) { + if (isPublish && len-*lengthLength-2>skip) { + this->stream->write(digit); + } + } + if (len < MQTT_MAX_PACKET_SIZE) { + buffer[len] = digit; + } + len++; + } + + if (!this->stream && len > MQTT_MAX_PACKET_SIZE) { + len = 0; // This will cause the packet to be ignored. + } + + return len; +} + +boolean PubSubClient::loop() { + if (connected()) { + unsigned long t = millis(); + if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { + if (pingOutstanding) { + this->_state = MQTT_CONNECTION_TIMEOUT; + _client->stop(); + return false; + } else { + buffer[0] = MQTTPINGREQ; + buffer[1] = 0; + _client->write(buffer,2); + lastOutActivity = t; + lastInActivity = t; + pingOutstanding = true; + } + } + if (_client->available()) { + uint8_t llen; + uint16_t len = readPacket(&llen); + uint16_t msgId = 0; + uint8_t *payload; + if (len > 0) { + lastInActivity = t; + uint8_t type = buffer[0]&0xF0; + if (type == MQTTPUBLISH) { + if (callback) { + uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */ + memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ + buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ + char *topic = (char*) buffer+llen+2; + // msgId only present for QOS>0 + if ((buffer[0]&0x06) == MQTTQOS1) { + msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; + payload = buffer+llen+3+tl+2; + callback(topic,payload,len-llen-3-tl-2); + + buffer[0] = MQTTPUBACK; + buffer[1] = 2; + buffer[2] = (msgId >> 8); + buffer[3] = (msgId & 0xFF); + _client->write(buffer,4); + lastOutActivity = t; + + } else { + payload = buffer+llen+3+tl; + callback(topic,payload,len-llen-3-tl); + } + } + } else if (type == MQTTPINGREQ) { + buffer[0] = MQTTPINGRESP; + buffer[1] = 0; + _client->write(buffer,2); + } else if (type == MQTTPINGRESP) { + pingOutstanding = false; + } + } + } + return true; + } + return false; +} + +boolean PubSubClient::publish(const char* topic, const char* payload) { + return publish(topic,(const uint8_t*)payload,strlen(payload),false); +} + +boolean PubSubClient::publish(const char* topic, const char* payload, boolean retained) { + return publish(topic,(const uint8_t*)payload,strlen(payload),retained); +} + +boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength) { + return publish(topic, payload, plength, false); +} + +boolean PubSubClient::publish(const char* topic, const uint8_t* payload, unsigned int plength, boolean retained) { + if (connected()) { + if (MQTT_MAX_PACKET_SIZE < 5 + 2+strlen(topic) + plength) { + // Too long + return false; + } + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + length = writeString(topic,buffer,length); + uint16_t i; + for (i=0;i 0) { + digit |= 0x80; + } + buffer[pos++] = digit; + llen++; + } while(len>0); + + pos = writeString(topic,buffer,pos); + + rc += _client->write(buffer,pos); + + for (i=0;iwrite((char)pgm_read_byte_near(payload + i)); + } + + lastOutActivity = millis(); + + return rc == tlen + 4 + plength; +} + +boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { + uint8_t lenBuf[4]; + uint8_t llen = 0; + uint8_t digit; + uint8_t pos = 0; + uint16_t rc; + uint16_t len = length; + do { + digit = len % 128; + len = len / 128; + if (len > 0) { + digit |= 0x80; + } + lenBuf[pos++] = digit; + llen++; + } while(len>0); + + buf[4-llen] = header; + for (int i=0;i 0) && result) { + bytesToWrite = (bytesRemaining > MQTT_MAX_TRANSFER_SIZE)?MQTT_MAX_TRANSFER_SIZE:bytesRemaining; + rc = _client->write(writeBuf,bytesToWrite); + result = (rc == bytesToWrite); + bytesRemaining -= rc; + writeBuf += rc; + } + return result; +#else + rc = _client->write(buf+(4-llen),length+1+llen); + lastOutActivity = millis(); + return (rc == 1+llen+length); +#endif +} + +boolean PubSubClient::subscribe(const char* topic) { + return subscribe(topic, 0); +} + +boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { + if (qos < 0 || qos > 1) { + return false; + } + if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + // Too long + return false; + } + if (connected()) { + // Leave room in the buffer for header and variable length field + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString((char*)topic, buffer,length); + buffer[length++] = qos; + return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +boolean PubSubClient::unsubscribe(const char* topic) { + if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { + // Too long + return false; + } + if (connected()) { + uint16_t length = 5; + nextMsgId++; + if (nextMsgId == 0) { + nextMsgId = 1; + } + buffer[length++] = (nextMsgId >> 8); + buffer[length++] = (nextMsgId & 0xFF); + length = writeString(topic, buffer,length); + return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-5); + } + return false; +} + +void PubSubClient::disconnect() { + buffer[0] = MQTTDISCONNECT; + buffer[1] = 0; + _client->write(buffer,2); + _state = MQTT_DISCONNECTED; + _client->stop(); + lastInActivity = lastOutActivity = millis(); +} + +uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t pos) { + const char* idp = string; + uint16_t i = 0; + pos += 2; + while (*idp) { + buf[pos++] = *idp++; + i++; + } + buf[pos-i-2] = (i >> 8); + buf[pos-i-1] = (i & 0xFF); + return pos; +} + + +boolean PubSubClient::connected() { + boolean rc; + if (_client == NULL ) { + rc = false; + } else { + rc = (int)_client->connected(); + if (!rc) { + if (this->_state == MQTT_CONNECTED) { + this->_state = MQTT_CONNECTION_LOST; + _client->flush(); + _client->stop(); + } + } + } + return rc; +} + +PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { + IPAddress addr(ip[0],ip[1],ip[2],ip[3]); + return setServer(addr,port); +} + +PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) { + this->ip = ip; + this->port = port; + this->domain = NULL; + return *this; +} + +PubSubClient& PubSubClient::setServer(const char * domain, uint16_t port) { + this->domain = domain; + this->port = port; + return *this; +} + +PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) { + this->callback = callback; + return *this; +} + +PubSubClient& PubSubClient::setClient(Client& client){ + this->_client = &client; + return *this; +} + +PubSubClient& PubSubClient::setStream(Stream& stream){ + this->stream = &stream; + return *this; +} + +int PubSubClient::state() { + return this->_state; +} diff --git a/lib/PubSubClient-2.6.09/src/PubSubClient.h b/lib/PubSubClient-2.6.09/src/PubSubClient.h new file mode 100644 index 000000000..e2f1b32b1 --- /dev/null +++ b/lib/PubSubClient-2.6.09/src/PubSubClient.h @@ -0,0 +1,145 @@ +/* + PubSubClient.h - A simple client for MQTT. + Nick O'Leary + http://knolleary.net +*/ + +#ifndef PubSubClient_h +#define PubSubClient_h + +#include +#include "IPAddress.h" +#include "Client.h" +#include "Stream.h" + +#define MQTT_VERSION_3_1 3 +#define MQTT_VERSION_3_1_1 4 + +// MQTT_VERSION : Pick the version +//#define MQTT_VERSION MQTT_VERSION_3_1 +#ifndef MQTT_VERSION +#define MQTT_VERSION MQTT_VERSION_3_1_1 +#endif + +// MQTT_MAX_PACKET_SIZE : Maximum packet size +#ifndef MQTT_MAX_PACKET_SIZE +//#define MQTT_MAX_PACKET_SIZE 128 +#define MQTT_MAX_PACKET_SIZE 512 +#endif + +// MQTT_KEEPALIVE : keepAlive interval in Seconds +#ifndef MQTT_KEEPALIVE +#define MQTT_KEEPALIVE 15 +#endif + +// MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds +#ifndef MQTT_SOCKET_TIMEOUT +#define MQTT_SOCKET_TIMEOUT 15 +#endif + +// MQTT_MAX_TRANSFER_SIZE : limit how much data is passed to the network client +// in each write call. Needed for the Arduino Wifi Shield. Leave undefined to +// pass the entire MQTT packet in each write call. +//#define MQTT_MAX_TRANSFER_SIZE 80 + +// Possible values for client.state() +#define MQTT_CONNECTION_TIMEOUT -4 +#define MQTT_CONNECTION_LOST -3 +#define MQTT_CONNECT_FAILED -2 +#define MQTT_DISCONNECTED -1 +#define MQTT_CONNECTED 0 +#define MQTT_CONNECT_BAD_PROTOCOL 1 +#define MQTT_CONNECT_BAD_CLIENT_ID 2 +#define MQTT_CONNECT_UNAVAILABLE 3 +#define MQTT_CONNECT_BAD_CREDENTIALS 4 +#define MQTT_CONNECT_UNAUTHORIZED 5 + +#define MQTTCONNECT 1 << 4 // Client request to connect to Server +#define MQTTCONNACK 2 << 4 // Connect Acknowledgment +#define MQTTPUBLISH 3 << 4 // Publish message +#define MQTTPUBACK 4 << 4 // Publish Acknowledgment +#define MQTTPUBREC 5 << 4 // Publish Received (assured delivery part 1) +#define MQTTPUBREL 6 << 4 // Publish Release (assured delivery part 2) +#define MQTTPUBCOMP 7 << 4 // Publish Complete (assured delivery part 3) +#define MQTTSUBSCRIBE 8 << 4 // Client Subscribe request +#define MQTTSUBACK 9 << 4 // Subscribe Acknowledgment +#define MQTTUNSUBSCRIBE 10 << 4 // Client Unsubscribe request +#define MQTTUNSUBACK 11 << 4 // Unsubscribe Acknowledgment +#define MQTTPINGREQ 12 << 4 // PING Request +#define MQTTPINGRESP 13 << 4 // PING Response +#define MQTTDISCONNECT 14 << 4 // Client is Disconnecting +#define MQTTReserved 15 << 4 // Reserved + +#define MQTTQOS0 (0 << 1) +#define MQTTQOS1 (1 << 1) +#define MQTTQOS2 (2 << 1) + +#ifdef ESP8266 +#include +#define MQTT_CALLBACK_SIGNATURE std::function callback +#else +#define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int) +#endif + +class PubSubClient { +private: + Client* _client; + uint8_t buffer[MQTT_MAX_PACKET_SIZE]; + uint16_t nextMsgId; + unsigned long lastOutActivity; + unsigned long lastInActivity; + bool pingOutstanding; + MQTT_CALLBACK_SIGNATURE; + uint16_t readPacket(uint8_t*); + boolean readByte(uint8_t * result); + boolean readByte(uint8_t * result, uint16_t * index); + boolean write(uint8_t header, uint8_t* buf, uint16_t length); + uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); + IPAddress ip; + const char* domain; + uint16_t port; + Stream* stream; + int _state; +public: + PubSubClient(); + PubSubClient(Client& client); + PubSubClient(IPAddress, uint16_t, Client& client); + PubSubClient(IPAddress, uint16_t, Client& client, Stream&); + PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); + PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + PubSubClient(uint8_t *, uint16_t, Client& client); + PubSubClient(uint8_t *, uint16_t, Client& client, Stream&); + PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); + PubSubClient(uint8_t *, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + PubSubClient(const char*, uint16_t, Client& client); + PubSubClient(const char*, uint16_t, Client& client, Stream&); + PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); + PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + + PubSubClient& setServer(IPAddress ip, uint16_t port); + PubSubClient& setServer(uint8_t * ip, uint16_t port); + PubSubClient& setServer(const char * domain, uint16_t port); + PubSubClient& setCallback(MQTT_CALLBACK_SIGNATURE); + PubSubClient& setClient(Client& client); + PubSubClient& setStream(Stream& stream); + + boolean connect(const char* id); + boolean connect(const char* id, const char* user, const char* pass); + boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); + boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); + void disconnect(); + boolean publish(const char* topic, const char* payload); + boolean publish(const char* topic, const char* payload, boolean retained); + boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); + boolean publish(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + boolean publish_P(const char* topic, const uint8_t * payload, unsigned int plength, boolean retained); + boolean subscribe(const char* topic); + boolean subscribe(const char* topic, uint8_t qos); + boolean unsubscribe(const char* topic); + boolean loop(); + boolean connected(); + int state(); +}; + + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/.gitignore b/lib/PubSubClient-2.6.09/tests/.gitignore new file mode 100644 index 000000000..215de78d7 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/.gitignore @@ -0,0 +1,4 @@ +.build +tmpbin +logs +*.pyc diff --git a/lib/PubSubClient-2.6.09/tests/Makefile b/lib/PubSubClient-2.6.09/tests/Makefile new file mode 100644 index 000000000..1f7163675 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/Makefile @@ -0,0 +1,25 @@ +SRC_PATH=./src +OUT_PATH=./bin +TEST_SRC=$(wildcard ${SRC_PATH}/*_spec.cpp) +TEST_BIN= $(TEST_SRC:${SRC_PATH}/%.cpp=${OUT_PATH}/%) +VPATH=${SRC_PATH} +SHIM_FILES=${SRC_PATH}/lib/*.cpp +PSC_FILE=../src/PubSubClient.cpp +CC=g++ +CFLAGS=-I${SRC_PATH}/lib -I../src + +all: $(TEST_BIN) + +${OUT_PATH}/%: ${SRC_PATH}/%.cpp ${PSC_FILE} ${SHIM_FILES} + mkdir -p ${OUT_PATH} + ${CC} ${CFLAGS} $^ -o $@ + +clean: + @rm -rf ${OUT_PATH} + +test: + @bin/connect_spec + @bin/publish_spec + @bin/receive_spec + @bin/subscribe_spec + @bin/keepalive_spec diff --git a/lib/PubSubClient-2.6.09/tests/README.md b/lib/PubSubClient-2.6.09/tests/README.md new file mode 100644 index 000000000..e5700a6d6 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/README.md @@ -0,0 +1,93 @@ +# Arduino Client for MQTT Test Suite + +This is a regression test suite for the `PubSubClient` library. + +There are two parts: + + - Tests that can be compiled and run on any machine + - Tests that build the example sketches using the Arduino IDE + + +It is a work-in-progress and is subject to complete refactoring as the whim takes +me. + + +## Local tests + +These are a set of executables that can be run to test specific areas of functionality. +They do not require a real Arduino to be attached, nor the use of the Arduino IDE. + +The tests include a set of mock files to stub out the parts of the Arduino environment the library +depends on. + +### Dependencies + + - g++ + +### Running + +Build the tests using the provided `Makefile`: + + $ make + +This will create a set of executables in `./bin/`. Run each of these executables to test the corresponding functionality. + +*Note:* the `connect_spec` and `keepalive_spec` tests involve testing keepalive timers so naturally take a few minutes to run through. + +## Arduino tests + +*Note:* INO Tool doesn't currently play nicely with Arduino 1.5. This has broken this test suite. + +Without a suitable arduino plugged in, the test suite will only check the +example sketches compile cleanly against the library. + +With an arduino plugged in, each sketch that has a corresponding python +test case is built, uploaded and then the tests run. + +### Dependencies + + - Python 2.7+ + - [INO Tool](http://inotool.org/) - this provides command-line build/upload of Arduino sketches + +### Running + +The test suite _does not_ run an MQTT server - it is assumed to be running already. + + $ python testsuite.py + +A summary of activity is printed to the console. More comprehensive logs are written +to the `logs` directory. + +### What it does + +For each sketch in the library's `examples` directory, e.g. `mqtt_basic.ino`, the suite looks for a matching test case +`testcases/mqtt_basic.py`. + +The test case must follow these conventions: + - sub-class `unittest.TestCase` + - provide the class methods `setUpClass` and `tearDownClass` (TODO: make this optional) + - all test method names begin with `test_` + +The suite will call the `setUpClass` method _before_ uploading the sketch. This +allows any test setup to be performed before the sketch runs - such as connecting +a client and subscribing to topics. + + +### Settings + +The file `testcases/settings.py` is used to config the test environment. + + - `server_ip` - the IP address of the broker the client should connect to (the broker port is assumed to be 1883). + - `arduino_ip` - the IP address the arduino should use (when not testing DHCP). + +Before each sketch is compiled, these values are automatically substituted in. To +do this, the suite looks for lines that _start_ with the following: + + byte server[] = { + byte ip[] = { + +and replaces them with the appropriate values. + + + + diff --git a/lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp b/lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp new file mode 100644 index 000000000..3c46e0cc4 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp @@ -0,0 +1,273 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + + +int test_connect_fails_no_network() { + IT("fails to connect if underlying client doesn't connect"); + ShimClient shimClient; + shimClient.setAllowConnect(false); + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_FALSE(rc); + int state = client.state(); + IS_TRUE(state == MQTT_CONNECT_FAILED); + END_IT +} + +int test_connect_fails_on_no_response() { + IT("fails to connect if no response received after 15 seconds"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_FALSE(rc); + int state = client.state(); + IS_TRUE(state == MQTT_CONNECTION_TIMEOUT); + END_IT +} + +int test_connect_properly_formatted() { + IT("sends a properly formatted connect packet and succeeds"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + byte expectServer[] = { 172, 16, 0, 2 }; + shimClient.expectConnect(expectServer,1883); + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + END_IT +} + +int test_connect_properly_formatted_hostname() { + IT("accepts a hostname"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + shimClient.expectConnect((char* const)"localhost",1883); + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client((char* const)"localhost", 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_connect_fails_on_bad_rc() { + IT("fails to connect if a bad return code is received"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + byte connack[] = { 0x20, 0x02, 0x00, 0x01 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_FALSE(rc); + + int state = client.state(); + IS_TRUE(state == 0x01); + + END_IT +} + +int test_connect_accepts_username_password() { + IT("accepts a username and password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = { 0x10,0x24,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x4,0x70,0x61,0x73,0x73}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_accepts_username_no_password() { + IT("accepts a username but no password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = { 0x10,0x1e,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x82,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x20); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",0); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} +int test_connect_accepts_username_blank_password() { + IT("accepts a username and blank password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = { 0x10,0x20,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x0}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_ignores_password_no_username() { + IT("ignores a password but no username"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",0,(char*)"pass"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_with_will() { + IT("accepts a will"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = {0x10,0x30,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xe,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x9,0x77,0x69,0x6c,0x6c,0x54,0x6f,0x70,0x69,0x63,0x0,0xb,0x77,0x69,0x6c,0x6c,0x4d,0x65,0x73,0x73,0x61,0x67,0x65}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x32); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"willTopic",1,0,(char*)"willMessage"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_with_will_username_password() { + IT("accepts a will, username and password"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connect[] = {0x10,0x40,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xce,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x9,0x77,0x69,0x6c,0x6c,0x54,0x6f,0x70,0x69,0x63,0x0,0xb,0x77,0x69,0x6c,0x6c,0x4d,0x65,0x73,0x73,0x61,0x67,0x65,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x8,0x70,0x61,0x73,0x73,0x77,0x6f,0x72,0x64}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.expect(connect,0x42); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"password",(char*)"willTopic",1,0,(char*)"willMessage"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_connect_disconnect_connect() { + IT("connects, disconnects and connects again"); + ShimClient shimClient; + + shimClient.setAllowConnect(true); + byte expectServer[] = { 172, 16, 0, 2 }; + shimClient.expectConnect(expectServer,1883); + byte connect[] = {0x10,0x18,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0x2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31}; + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + + shimClient.expect(connect,26); + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + + int state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + byte disconnect[] = {0xE0,0x00}; + shimClient.expect(disconnect,2); + + client.disconnect(); + + IS_FALSE(client.connected()); + IS_FALSE(shimClient.connected()); + IS_FALSE(shimClient.error()); + + state = client.state(); + IS_TRUE(state == MQTT_DISCONNECTED); + + shimClient.expect(connect,28); + shimClient.respond(connack,4); + rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + state = client.state(); + IS_TRUE(state == MQTT_CONNECTED); + + END_IT +} + +int main() +{ + SUITE("Connect"); + test_connect_fails_no_network(); + test_connect_fails_on_no_response(); + + test_connect_properly_formatted(); + test_connect_accepts_username_password(); + test_connect_fails_on_bad_rc(); + test_connect_properly_formatted_hostname(); + + test_connect_accepts_username_no_password(); + test_connect_ignores_password_no_username(); + test_connect_with_will(); + test_connect_with_will_username_password(); + test_connect_disconnect_connect(); + FINISH +} diff --git a/lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp b/lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp new file mode 100644 index 000000000..ea643cf17 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp @@ -0,0 +1,185 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" +#include + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + + +int test_keepalive_pings_idle() { + IT("keeps an idle connection alive (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + byte pingresp[] = { 0xD0,0x0 }; + shimClient.respond(pingresp,2); + + for (int i = 0; i < 50; i++) { + sleep(1); + if ( i == 15 || i == 31 || i == 47) { + shimClient.expect(pingreq,2); + shimClient.respond(pingresp,2); + } + rc = client.loop(); + IS_TRUE(rc); + } + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_keepalive_pings_with_outbound_qos0() { + IT("keeps a connection alive that only sends qos0 (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + + for (int i = 0; i < 50; i++) { + TRACE(i<<":"); + shimClient.expect(publish,16); + rc = client.publish((char*)"topic",(char*)"payload"); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + sleep(1); + if ( i == 15 || i == 31 || i == 47) { + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + byte pingresp[] = { 0xD0,0x0 }; + shimClient.respond(pingresp,2); + } + rc = client.loop(); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + } + + END_IT +} + +int test_keepalive_pings_with_inbound_qos0() { + IT("keeps a connection alive that only receives qos0 (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + + for (int i = 0; i < 50; i++) { + TRACE(i<<":"); + sleep(1); + if ( i == 15 || i == 31 || i == 47) { + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + byte pingresp[] = { 0xD0,0x0 }; + shimClient.respond(pingresp,2); + } + shimClient.respond(publish,16); + rc = client.loop(); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + } + + END_IT +} + +int test_keepalive_no_pings_inbound_qos1() { + IT("does not send pings for connections with inbound qos1 (takes 1 minute)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + byte puback[] = {0x40,0x2,0x12,0x34}; + + for (int i = 0; i < 50; i++) { + shimClient.respond(publish,18); + shimClient.expect(puback,4); + sleep(1); + rc = client.loop(); + IS_TRUE(rc); + IS_FALSE(shimClient.error()); + } + + END_IT +} + +int test_keepalive_disconnects_hung() { + IT("disconnects a hung connection (takes 30 seconds)"); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte pingreq[] = { 0xC0,0x0 }; + shimClient.expect(pingreq,2); + + for (int i = 0; i < 32; i++) { + sleep(1); + rc = client.loop(); + } + IS_FALSE(rc); + + int state = client.state(); + IS_TRUE(state == MQTT_CONNECTION_TIMEOUT); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int main() +{ + SUITE("Keep-alive"); + test_keepalive_pings_idle(); + test_keepalive_pings_with_outbound_qos0(); + test_keepalive_pings_with_inbound_qos0(); + test_keepalive_no_pings_inbound_qos1(); + test_keepalive_disconnects_hung(); + + FINISH +} diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h b/lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h new file mode 100644 index 000000000..c6752801a --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h @@ -0,0 +1,23 @@ +#ifndef Arduino_h +#define Arduino_h + +#include +#include +#include +#include + + +extern "C"{ + typedef uint8_t byte ; + typedef uint8_t boolean ; + + /* sketch */ + extern void setup( void ) ; + extern void loop( void ) ; + uint32_t millis( void ); +} + +#define PROGMEM +#define pgm_read_byte_near(x) *(x) + +#endif // Arduino_h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp b/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp new file mode 100644 index 000000000..a72bf65e2 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp @@ -0,0 +1,50 @@ +#include "BDDTest.h" +#include "trace.h" +#include +#include +#include +#include + +int testCount = 0; +int testPasses = 0; +const char* testDescription; + +std::list failureList; + +void bddtest_suite(const char* name) { + LOG(name << "\n"); +} + +int bddtest_test(const char* file, int line, const char* assertion, int result) { + if (!result) { + LOG("✗\n"); + std::ostringstream os; + os << " ! "<::iterator it = failureList.begin(); it != failureList.end(); it++) { + LOG("\n"); + LOG(*it); + LOG("\n"); + } + + LOG(std::dec << testPasses << "/" << testCount << " tests passed\n\n"); + if (testPasses == testCount) { + return 0; + } + return 1; +} diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h b/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h new file mode 100644 index 000000000..1197fdd42 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h @@ -0,0 +1,23 @@ +#ifndef bddtest_h +#define bddtest_h + +void bddtest_suite(const char* name); +int bddtest_test(const char*, int, const char*, int); +void bddtest_start(const char*); +void bddtest_end(); +int bddtest_summary(); + +#define SUITE(x) { bddtest_suite(x); } +#define TEST(x) { if (!bddtest_test(__FILE__, __LINE__, #x, (x))) return false; } + +#define IT(x) { bddtest_start(x); } +#define END_IT { bddtest_end();return true;} + +#define FINISH { return bddtest_summary(); } + +#define IS_TRUE(x) TEST(x) +#define IS_FALSE(x) TEST(!(x)) +#define IS_EQUAL(x,y) TEST(x==y) +#define IS_NOT_EQUAL(x,y) TEST(x!=y) + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp b/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp new file mode 100644 index 000000000..f07759a3a --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp @@ -0,0 +1,34 @@ +#include "Buffer.h" +#include "Arduino.h" + +Buffer::Buffer() { + this->pos = 0; + this->length = 0; +} + +Buffer::Buffer(uint8_t* buf, size_t size) { + this->pos = 0; + this->length = 0; + this->add(buf,size); +} +bool Buffer::available() { + return this->pos < this->length; +} + +uint8_t Buffer::next() { + if (this->available()) { + return this->buffer[this->pos++]; + } + return 0; +} + +void Buffer::reset() { + this->pos = 0; +} + +void Buffer::add(uint8_t* buf, size_t size) { + uint16_t i = 0; + for (;ibuffer[this->length++] = buf[i]; + } +} diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h b/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h new file mode 100644 index 000000000..f448cade8 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h @@ -0,0 +1,23 @@ +#ifndef buffer_h +#define buffer_h + +#include "Arduino.h" + +class Buffer { +private: + uint8_t buffer[1024]; + uint16_t pos; + uint16_t length; + +public: + Buffer(); + Buffer(uint8_t* buf, size_t size); + + virtual bool available(); + virtual uint8_t next(); + virtual void reset(); + + virtual void add(uint8_t* buf, size_t size); +}; + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Client.h b/lib/PubSubClient-2.6.09/tests/src/lib/Client.h new file mode 100644 index 000000000..9e18c0764 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/Client.h @@ -0,0 +1,21 @@ +#ifndef client_h +#define client_h +#include "IPAddress.h" + +class Client { +public: + virtual int connect(IPAddress ip, uint16_t port) =0; + virtual int connect(const char *host, uint16_t port) =0; + virtual size_t write(uint8_t) =0; + virtual size_t write(const uint8_t *buf, size_t size) =0; + virtual int available() = 0; + virtual int read() = 0; + virtual int read(uint8_t *buf, size_t size) = 0; + virtual int peek() = 0; + virtual void flush() = 0; + virtual void stop() = 0; + virtual uint8_t connected() = 0; + virtual operator bool() = 0; +}; + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp b/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp new file mode 100644 index 000000000..610ff4c53 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp @@ -0,0 +1,44 @@ + +#include +#include + +IPAddress::IPAddress() +{ + memset(_address, 0, sizeof(_address)); +} + +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +{ + _address[0] = first_octet; + _address[1] = second_octet; + _address[2] = third_octet; + _address[3] = fourth_octet; +} + +IPAddress::IPAddress(uint32_t address) +{ + memcpy(_address, &address, sizeof(_address)); +} + +IPAddress::IPAddress(const uint8_t *address) +{ + memcpy(_address, address, sizeof(_address)); +} + +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + memcpy(_address, address, sizeof(_address)); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + memcpy(_address, (const uint8_t *)&address, sizeof(_address)); + return *this; +} + +bool IPAddress::operator==(const uint8_t* addr) +{ + return memcmp(addr, _address, sizeof(_address)) == 0; +} + diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h b/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h new file mode 100644 index 000000000..e75a8fe65 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h @@ -0,0 +1,72 @@ +/* + * + * MIT License: + * Copyright (c) 2011 Adrian McEwen + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation 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 + * furnished 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 FOR 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. + * + * adrianm@mcqn.com 1/1/2011 + */ + +#ifndef IPAddress_h +#define IPAddress_h + + +// A class to make it easier to handle and pass around IP addresses + +class IPAddress { +private: + uint8_t _address[4]; // IPv4 address + // Access the raw byte array containing the address. Because this returns a pointer + // to the internal structure rather than a copy of the address this function should only + // be used when you know that the usage of the returned uint8_t* will be transient and not + // stored. + uint8_t* raw_address() { return _address; }; + +public: + // Constructors + IPAddress(); + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + IPAddress(uint32_t address); + IPAddress(const uint8_t *address); + + // Overloaded cast operator to allow IPAddress objects to be used where a pointer + // to a four-byte uint8_t array is expected + operator uint32_t() { return *((uint32_t*)_address); }; + bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); }; + bool operator==(const uint8_t* addr); + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const { return _address[index]; }; + uint8_t& operator[](int index) { return _address[index]; }; + + // Overloaded copy operators to allow initialisation of IPAddress objects from other types + IPAddress& operator=(const uint8_t *address); + IPAddress& operator=(uint32_t address); + + + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; +}; + + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp b/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp new file mode 100644 index 000000000..f70115fa8 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp @@ -0,0 +1,153 @@ +#include "ShimClient.h" +#include "trace.h" +#include +#include +#include + +extern "C" { + uint32_t millis(void) { + return time(0)*1000; + } +} + +ShimClient::ShimClient() { + this->responseBuffer = new Buffer(); + this->expectBuffer = new Buffer(); + this->_allowConnect = true; + this->_connected = false; + this->_error = false; + this->expectAnything = true; + this->_received = 0; + this->_expectedPort = 0; +} + +int ShimClient::connect(IPAddress ip, uint16_t port) { + if (this->_allowConnect) { + this->_connected = true; + } + if (this->_expectedPort !=0) { + // if (memcmp(ip,this->_expectedIP,4) != 0) { + // TRACE( "ip mismatch\n"); + // this->_error = true; + // } + if (port != this->_expectedPort) { + TRACE( "port mismatch\n"); + this->_error = true; + } + } + return this->_connected; +} +int ShimClient::connect(const char *host, uint16_t port) { + if (this->_allowConnect) { + this->_connected = true; + } + if (this->_expectedPort !=0) { + if (strcmp(host,this->_expectedHost) != 0) { + TRACE( "host mismatch\n"); + this->_error = true; + } + if (port != this->_expectedPort) { + TRACE( "port mismatch\n"); + this->_error = true; + } + + } + return this->_connected; +} +size_t ShimClient::write(uint8_t b) { + this->_received += 1; + TRACE(std::hex << (unsigned int)b); + if (!this->expectAnything) { + if (this->expectBuffer->available()) { + uint8_t expected = this->expectBuffer->next(); + if (expected != b) { + this->_error = true; + TRACE("!=" << (unsigned int)expected); + } + } else { + this->_error = true; + } + } + TRACE("\n"<< std::dec); + return 1; +} +size_t ShimClient::write(const uint8_t *buf, size_t size) { + this->_received += size; + TRACE( "[" << std::dec << (unsigned int)(size) << "] "); + uint16_t i=0; + for (;i0) { + TRACE(":"); + } + TRACE(std::hex << (unsigned int)(buf[i])); + + if (!this->expectAnything) { + if (this->expectBuffer->available()) { + uint8_t expected = this->expectBuffer->next(); + if (expected != buf[i]) { + this->_error = true; + TRACE("!=" << (unsigned int)expected); + } + } else { + this->_error = true; + } + } + } + TRACE("\n"<responseBuffer->available(); +} +int ShimClient::read() { return this->responseBuffer->next(); } +int ShimClient::read(uint8_t *buf, size_t size) { + uint16_t i = 0; + for (;iread(); + } + return size; +} +int ShimClient::peek() { return 0; } +void ShimClient::flush() {} +void ShimClient::stop() { + this->setConnected(false); +} +uint8_t ShimClient::connected() { return this->_connected; } +ShimClient::operator bool() { return true; } + + +ShimClient* ShimClient::respond(uint8_t *buf, size_t size) { + this->responseBuffer->add(buf,size); + return this; +} + +ShimClient* ShimClient::expect(uint8_t *buf, size_t size) { + this->expectAnything = false; + this->expectBuffer->add(buf,size); + return this; +} + +void ShimClient::setConnected(bool b) { + this->_connected = b; +} +void ShimClient::setAllowConnect(bool b) { + this->_allowConnect = b; +} + +bool ShimClient::error() { + return this->_error; +} + +uint16_t ShimClient::received() { + return this->_received; +} + +void ShimClient::expectConnect(IPAddress ip, uint16_t port) { + this->_expectedIP = ip; + this->_expectedPort = port; +} + +void ShimClient::expectConnect(const char *host, uint16_t port) { + this->_expectedHost = host; + this->_expectedPort = port; +} diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h b/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h new file mode 100644 index 000000000..2e3f874fc --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h @@ -0,0 +1,51 @@ +#ifndef shimclient_h +#define shimclient_h + +#include "Arduino.h" +#include "Client.h" +#include "IPAddress.h" +#include "Buffer.h" + + +class ShimClient : public Client { +private: + Buffer* responseBuffer; + Buffer* expectBuffer; + bool _allowConnect; + bool _connected; + bool expectAnything; + bool _error; + uint16_t _received; + IPAddress _expectedIP; + uint16_t _expectedPort; + const char* _expectedHost; + +public: + ShimClient(); + virtual int connect(IPAddress ip, uint16_t port); + virtual int connect(const char *host, uint16_t port); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int available(); + virtual int read(); + virtual int read(uint8_t *buf, size_t size); + virtual int peek(); + virtual void flush(); + virtual void stop(); + virtual uint8_t connected(); + virtual operator bool(); + + virtual ShimClient* respond(uint8_t *buf, size_t size); + virtual ShimClient* expect(uint8_t *buf, size_t size); + + virtual void expectConnect(IPAddress ip, uint16_t port); + virtual void expectConnect(const char *host, uint16_t port); + + virtual uint16_t received(); + virtual bool error(); + + virtual void setAllowConnect(bool b); + virtual void setConnected(bool b); +}; + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp b/lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp new file mode 100644 index 000000000..b0ecbb44e --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp @@ -0,0 +1,39 @@ +#include "Stream.h" +#include "trace.h" +#include +#include + +Stream::Stream() { + this->expectBuffer = new Buffer(); + this->_error = false; + this->_written = 0; +} + +size_t Stream::write(uint8_t b) { + this->_written++; + TRACE(std::hex << (unsigned int)b); + if (this->expectBuffer->available()) { + uint8_t expected = this->expectBuffer->next(); + if (expected != b) { + this->_error = true; + TRACE("!=" << (unsigned int)expected); + } + } else { + this->_error = true; + } + TRACE("\n"<< std::dec); + return 1; +} + + +bool Stream::error() { + return this->_error; +} + +void Stream::expect(uint8_t *buf, size_t size) { + this->expectBuffer->add(buf,size); +} + +uint16_t Stream::length() { + return this->_written; +} diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Stream.h b/lib/PubSubClient-2.6.09/tests/src/lib/Stream.h new file mode 100644 index 000000000..4e41f86fa --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/Stream.h @@ -0,0 +1,22 @@ +#ifndef Stream_h +#define Stream_h + +#include "Arduino.h" +#include "Buffer.h" + +class Stream { +private: + Buffer* expectBuffer; + bool _error; + uint16_t _written; + +public: + Stream(); + virtual size_t write(uint8_t); + + virtual bool error(); + virtual void expect(uint8_t *buf, size_t size); + virtual uint16_t length(); +}; + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/trace.h b/lib/PubSubClient-2.6.09/tests/src/lib/trace.h new file mode 100644 index 000000000..42eb99104 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/lib/trace.h @@ -0,0 +1,10 @@ +#ifndef trace_h +#define trace_h +#include + +#include + +#define LOG(x) {std::cout << x << std::flush; } +#define TRACE(x) {if (getenv("TRACE")) { std::cout << x << std::flush; }} + +#endif diff --git a/lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp b/lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp new file mode 100644 index 000000000..232df0d37 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp @@ -0,0 +1,190 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +int test_publish() { + IT("publishes a null-terminated string"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.expect(publish,16); + + rc = client.publish((char*)"topic",(char*)"payload"); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_publish_bytes() { + IT("publishes a byte array"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; + int length = 5; + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; + shimClient.expect(publish,14); + + rc = client.publish((char*)"topic",payload,length); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_publish_retained() { + IT("publishes retained - 1"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; + int length = 5; + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; + shimClient.expect(publish,14); + + rc = client.publish((char*)"topic",payload,length,true); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_retained_2() { + IT("publishes retained - 2"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,'A','B','C','D','E'}; + shimClient.expect(publish,14); + + rc = client.publish((char*)"topic",(char*)"ABCDE",true); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_not_connected() { + IT("publish fails when not connected"); + ShimClient shimClient; + + PubSubClient client(server, 1883, callback, shimClient); + + int rc = client.publish((char*)"topic",(char*)"payload"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_too_long() { + IT("publish fails when topic/payload are too long"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + // 0 1 2 3 4 5 6 7 8 9 0 1 2 + rc = client.publish((char*)"topic",(char*)"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_publish_P() { + IT("publishes using PROGMEM"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte payload[] = { 0x01,0x02,0x03,0x0,0x05 }; + int length = 5; + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x31,0xc,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1,0x2,0x3,0x0,0x5}; + shimClient.expect(publish,14); + + rc = client.publish_P((char*)"topic",payload,length,true); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + + + +int main() +{ + SUITE("Publish"); + test_publish(); + test_publish_bytes(); + test_publish_retained(); + test_publish_retained_2(); + test_publish_not_connected(); + test_publish_too_long(); + test_publish_P(); + + FINISH +} diff --git a/lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp b/lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp new file mode 100644 index 000000000..54a62ee5c --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp @@ -0,0 +1,249 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +bool callback_called = false; +char lastTopic[1024]; +char lastPayload[1024]; +unsigned int lastLength; + +void reset_callback() { + callback_called = false; + lastTopic[0] = '\0'; + lastPayload[0] = '\0'; + lastLength = 0; +} + +void callback(char* topic, byte* payload, unsigned int length) { + callback_called = true; + strcpy(lastTopic,topic); + memcpy(lastPayload,payload,length); + lastLength = length; +} + +int test_receive_callback() { + IT("receives a callback message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.respond(publish,16); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(memcmp(lastPayload,"payload",7)==0); + IS_TRUE(lastLength == 7); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_stream() { + IT("receives a streamed callback message"); + reset_callback(); + + Stream stream; + stream.expect((uint8_t*)"payload",7); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient, stream); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x30,0xe,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.respond(publish,16); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(lastLength == 7); + + IS_FALSE(stream.error()); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_max_sized_message() { + IT("receives an max-sized message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + int length = MQTT_MAX_PACKET_SIZE; + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + byte bigPublish[length]; + memset(bigPublish,'A',length); + bigPublish[length] = 'B'; + memcpy(bigPublish,publish,16); + shimClient.respond(bigPublish,length); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(lastLength == length-9); + IS_TRUE(memcmp(lastPayload,bigPublish+9,lastLength)==0); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_oversized_message() { + IT("drops an oversized message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + int length = MQTT_MAX_PACKET_SIZE+1; + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + byte bigPublish[length]; + memset(bigPublish,'A',length); + bigPublish[length] = 'B'; + memcpy(bigPublish,publish,16); + shimClient.respond(bigPublish,length); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_FALSE(callback_called); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_oversized_stream_message() { + IT("drops an oversized message"); + reset_callback(); + + Stream stream; + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient, stream); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + int length = MQTT_MAX_PACKET_SIZE+1; + byte publish[] = {0x30,length-2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + + byte bigPublish[length]; + memset(bigPublish,'A',length); + bigPublish[length] = 'B'; + memcpy(bigPublish,publish,16); + + shimClient.respond(bigPublish,length); + stream.expect(bigPublish+9,length-9); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(lastLength == length-9); + + IS_FALSE(stream.error()); + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_receive_qos1() { + IT("receives a qos1 message"); + reset_callback(); + + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte publish[] = {0x32,0x10,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x12,0x34,0x70,0x61,0x79,0x6c,0x6f,0x61,0x64}; + shimClient.respond(publish,18); + + byte puback[] = {0x40,0x2,0x12,0x34}; + shimClient.expect(puback,4); + + rc = client.loop(); + + IS_TRUE(rc); + + IS_TRUE(callback_called); + IS_TRUE(strcmp(lastTopic,"topic")==0); + IS_TRUE(memcmp(lastPayload,"payload",7)==0); + IS_TRUE(lastLength == 7); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int main() +{ + SUITE("Receive"); + test_receive_callback(); + test_receive_stream(); + test_receive_max_sized_message(); + test_receive_oversized_message(); + test_receive_oversized_stream_message(); + test_receive_qos1(); + + FINISH +} diff --git a/lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp b/lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp new file mode 100644 index 000000000..a41982355 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp @@ -0,0 +1,177 @@ +#include "PubSubClient.h" +#include "ShimClient.h" +#include "Buffer.h" +#include "BDDTest.h" +#include "trace.h" + + +byte server[] = { 172, 16, 0, 2 }; + +void callback(char* topic, byte* payload, unsigned int length) { + // handle message arrived +} + +int test_subscribe_no_qos() { + IT("subscribe without qos defaults to 0"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x0 }; + shimClient.expect(subscribe,12); + byte suback[] = { 0x90,0x3,0x0,0x2,0x0 }; + shimClient.respond(suback,5); + + rc = client.subscribe((char*)"topic"); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_qos_1() { + IT("subscribes qos 1"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte subscribe[] = { 0x82,0xa,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63,0x1 }; + shimClient.expect(subscribe,12); + byte suback[] = { 0x90,0x3,0x0,0x2,0x1 }; + shimClient.respond(suback,5); + + rc = client.subscribe((char*)"topic",1); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_not_connected() { + IT("subscribe fails when not connected"); + ShimClient shimClient; + + PubSubClient client(server, 1883, callback, shimClient); + + int rc = client.subscribe((char*)"topic"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_invalid_qos() { + IT("subscribe fails with invalid qos values"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + rc = client.subscribe((char*)"topic",2); + IS_FALSE(rc); + rc = client.subscribe((char*)"topic",254); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_subscribe_too_long() { + IT("subscribe fails with too long topic"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + // max length should be allowed + // 0 1 2 3 4 5 6 7 8 9 0 1 2 + rc = client.subscribe((char*)"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"); + IS_TRUE(rc); + + // 0 1 2 3 4 5 6 7 8 9 0 1 2 + rc = client.subscribe((char*)"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + + +int test_unsubscribe() { + IT("unsubscribes"); + ShimClient shimClient; + shimClient.setAllowConnect(true); + + byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; + shimClient.respond(connack,4); + + PubSubClient client(server, 1883, callback, shimClient); + int rc = client.connect((char*)"client_test1"); + IS_TRUE(rc); + + byte unsubscribe[] = { 0xA2,0x9,0x0,0x2,0x0,0x5,0x74,0x6f,0x70,0x69,0x63 }; + shimClient.expect(unsubscribe,12); + byte unsuback[] = { 0xB0,0x2,0x0,0x2 }; + shimClient.respond(unsuback,4); + + rc = client.unsubscribe((char*)"topic"); + IS_TRUE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int test_unsubscribe_not_connected() { + IT("unsubscribe fails when not connected"); + ShimClient shimClient; + + PubSubClient client(server, 1883, callback, shimClient); + + int rc = client.unsubscribe((char*)"topic"); + IS_FALSE(rc); + + IS_FALSE(shimClient.error()); + + END_IT +} + +int main() +{ + SUITE("Subscribe"); + test_subscribe_no_qos(); + test_subscribe_qos_1(); + test_subscribe_not_connected(); + test_subscribe_invalid_qos(); + test_subscribe_too_long(); + test_unsubscribe(); + test_unsubscribe_not_connected(); + FINISH +} diff --git a/lib/PubSubClient-2.6.09/tests/testcases/__init__.py b/lib/PubSubClient-2.6.09/tests/testcases/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py new file mode 100644 index 000000000..f23ef71c1 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py @@ -0,0 +1,39 @@ +import unittest +import settings +import time +import mosquitto + + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + + +class mqtt_basic(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic", 0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_one(self): + i = 30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i > 0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue[0] + self.assertEqual(msg.mid, 0, "message id not 0") + self.assertEqual(msg.topic, "outTopic", "message topic incorrect") + self.assertEqual(msg.payload, "hello world") + self.assertEqual(msg.qos, 0, "message qos not 0") + self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py new file mode 100644 index 000000000..45b0a8515 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py @@ -0,0 +1,59 @@ +import unittest +import settings +import time +import mosquitto + + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + + +class mqtt_publish_in_callback(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic", 0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_connect(self): + i = 30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i > 0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid, 0, "message id not 0") + self.assertEqual(msg.topic, "outTopic", "message topic incorrect") + self.assertEqual(msg.payload, "hello world") + self.assertEqual(msg.qos, 0, "message qos not 0") + self.assertEqual(msg.retain, False, "message retain flag incorrect") + + def test_publish(self): + self.assertEqual(len(self.message_queue), 0, "message queue not empty") + payload = "abcdefghij" + self.client.publish("inTopic", payload) + + i = 30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + + self.assertTrue(i > 0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid, 0, "message id not 0") + self.assertEqual(msg.topic, "outTopic", "message topic incorrect") + self.assertEqual(msg.payload, payload) + self.assertEqual(msg.qos, 0, "message qos not 0") + self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-2.6.09/tests/testcases/settings.py b/lib/PubSubClient-2.6.09/tests/testcases/settings.py new file mode 100644 index 000000000..4ad8719d8 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/testcases/settings.py @@ -0,0 +1,2 @@ +server_ip = "172.16.0.2" +arduino_ip = "172.16.0.100" diff --git a/lib/PubSubClient-2.6.09/tests/testsuite.py b/lib/PubSubClient-2.6.09/tests/testsuite.py new file mode 100644 index 000000000..788fc5d97 --- /dev/null +++ b/lib/PubSubClient-2.6.09/tests/testsuite.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +import os +import os.path +import sys +import shutil +from subprocess import call +import importlib +import unittest +import re + +from testcases import settings + + +class Workspace(object): + + def __init__(self): + self.root_dir = os.getcwd() + self.build_dir = os.path.join(self.root_dir, "tmpbin") + self.log_dir = os.path.join(self.root_dir, "logs") + self.tests_dir = os.path.join(self.root_dir, "testcases") + self.examples_dir = os.path.join(self.root_dir, "../PubSubClient/examples") + self.examples = [] + self.tests = [] + if not os.path.isdir("../PubSubClient"): + raise Exception("Cannot find PubSubClient library") + try: + return __import__('ino') + except ImportError: + raise Exception("ino tool not installed") + + def init(self): + if os.path.isdir(self.build_dir): + shutil.rmtree(self.build_dir) + os.mkdir(self.build_dir) + if os.path.isdir(self.log_dir): + shutil.rmtree(self.log_dir) + os.mkdir(self.log_dir) + + os.chdir(self.build_dir) + call(["ino", "init"]) + + shutil.copytree("../../PubSubClient", "lib/PubSubClient") + + filenames = [] + for root, dirs, files in os.walk(self.examples_dir): + filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.examples.append(Sketch(self, e)) + + filenames = [] + for root, dirs, files in os.walk(self.tests_dir): + filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.tests.append(Sketch(self, e)) + + def clean(self): + shutil.rmtree(self.build_dir) + + +class Sketch(object): + def __init__(self, wksp, fn): + self.w = wksp + self.filename = fn + self.basename = os.path.basename(self.filename) + self.build_log = os.path.join(self.w.log_dir, "%s.log" % (os.path.basename(self.filename),)) + self.build_err_log = os.path.join(self.w.log_dir, "%s.err.log" % (os.path.basename(self.filename),)) + self.build_upload_log = os.path.join(self.w.log_dir, "%s.upload.log" % (os.path.basename(self.filename),)) + + def build(self): + sys.stdout.write(" Build: ") + sys.stdout.flush() + + # Copy sketch over, replacing IP addresses as necessary + fin = open(self.filename, "r") + lines = fin.readlines() + fin.close() + fout = open(os.path.join(self.w.build_dir, "src", "sketch.ino"), "w") + for l in lines: + if re.match(r"^byte server\[\] = {", l): + fout.write("byte server[] = { %s };\n" % (settings.server_ip.replace(".", ", "),)) + elif re.match(r"^byte ip\[\] = {", l): + fout.write("byte ip[] = { %s };\n" % (settings.arduino_ip.replace(".", ", "),)) + else: + fout.write(l) + fout.flush() + fout.close() + + # Run build + fout = open(self.build_log, "w") + ferr = open(self.build_err_log, "w") + rc = call(["ino", "build"], stdout=fout, stderr=ferr) + fout.close() + ferr.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_err_log) as f: + for line in f: + print(" " + line) + return False + + def upload(self): + sys.stdout.write(" Upload: ") + sys.stdout.flush() + fout = open(self.build_upload_log, "w") + rc = call(["ino", "upload"], stdout=fout, stderr=fout) + fout.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_upload_log) as f: + for line in f: + print(" " + line) + return False + + def test(self): + # import the matching test case, if it exists + try: + basename = os.path.basename(self.filename)[:-4] + i = importlib.import_module("testcases." + basename) + except: + sys.stdout.write(" Test: no tests found") + sys.stdout.write("\n") + return + c = getattr(i, basename) + + testmethods = [m for m in dir(c) if m.startswith("test_")] + testmethods.sort() + tests = [] + for m in testmethods: + tests.append(c(m)) + + result = unittest.TestResult() + c.setUpClass() + if self.upload(): + sys.stdout.write(" Test: ") + sys.stdout.flush() + for t in tests: + t.run(result) + print(str(result.testsRun - len(result.failures) - len(result.errors)) + "/" + str(result.testsRun)) + if not result.wasSuccessful(): + if len(result.failures) > 0: + for f in result.failures: + print("-- " + str(f[0])) + print(f[1]) + if len(result.errors) > 0: + print(" Errors:") + for f in result.errors: + print("-- " + str(f[0])) + print(f[1]) + c.tearDownClass() + + +if __name__ == '__main__': + run_tests = True + + w = Workspace() + w.init() + + for e in w.examples: + print("--------------------------------------") + print("[" + e.basename + "]") + if e.build() and run_tests: + e.test() + for e in w.tests: + print("--------------------------------------") + print("[" + e.basename + "]") + if e.build() and run_tests: + e.test() + + w.clean() diff --git a/lib/readme.txt b/lib/readme.txt new file mode 100644 index 000000000..dbadc3d63 --- /dev/null +++ b/lib/readme.txt @@ -0,0 +1,36 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +More information about PlatformIO Library Dependency Finder +- http://docs.platformio.org/page/librarymanager/ldf.html diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index e16e2acad..93d4069c0 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,13 @@ -/* 5.9.1e +/* 5.9.1f + * Upgrade library ArduinoJson to 5.11.2 + * Upgrade library IRRemoteEsp8266 to 2.2.1 + 2 commits but tweaked some protocols to keep code usage small + * Upgrade library NeoPixelBus to 2.2.9 + * Upgrade library OneWire to 2.3.3 + 6 commits + * Formalize library PubSubClient to 2.6 + 9 commits and additional delay + * Add optional ADS1115 driver as alternative for unsupported I2Cdevlib in esp8266-core 2.4.0-rc2 + * Fix wrong response name for command HlwISet (#1214) + * + * 5.9.1e * Add + (plus) and - (minus) to command color to select 1 out of 12 preset colors * Add + (plus) and - (minus) to command ct to control ColdWarm led ColorTemperature (+34/-34) * Tune Arilux RF code diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d4bdfa3fa..135da99f3 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05090105 // 5.9.1e +#define VERSION 0x05090106 // 5.9.1f // Location specific includes #include "sonoff.h" // Enumaration used in user_config.h diff --git a/sonoff/support.ino b/sonoff/support.ino index ab215b8f3..3ad2a54f3 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -32,7 +32,7 @@ static unsigned long oswatch_last_loop_time; byte oswatch_blocked_loop = 0; #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception -void OsWatchTicker() ICACHE_RAM_ATTR; +//void OsWatchTicker() ICACHE_RAM_ATTR; #endif // USE_WS2812_DMA void OsWatchTicker() diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 6044107fe..a8831955e 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -171,12 +171,13 @@ #define USE_BMP // Add I2C code for BMP/BME280 sensor #define USE_BH1750 // Add I2C code for BH1750 sensor // #define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0.5k code) -// #define USE_ADS1115 // Add I2C code for ADS1x15 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) +// #define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (library not needed) (+0.7k code) +// #define USE_ADS1115_I2CDEV // Add I2C code for ADS1115 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) // #define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code) -#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+3k code, 0.3k mem) +#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0.3k mem) // #define USE_IR_HVAC // Support for HVAC system using IR (+2k code) - #define USE_IR_RECEIVE // Support for IR receiver (+4k code) + #define USE_IR_RECEIVE // Support for IR receiver (+5.5k code) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem) - Disable by // #define USE_WS2812_CTYPE 1 // WS2812 Color type (0 - RGB, 1 - GRB, 2 - RGBW, 3 - GRBW) diff --git a/sonoff/xdrv_irremote.ino b/sonoff/xdrv_irremote.ino index c1a824636..423270684 100644 --- a/sonoff/xdrv_irremote.ino +++ b/sonoff/xdrv_irremote.ino @@ -22,10 +22,15 @@ * IR Remote send and receive using IRremoteESP8266 library \*********************************************************************************************/ -#ifndef USE_IR_HVAC #include -#else -#include + +// Based on IRremoteESP8266.h enum decode_type_t +const char kIrRemoteProtocols[] PROGMEM = + "UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP"; + +#ifdef USE_IR_HVAC + +#include // HVAC TOSHIBA_ #define HVAC_TOSHIBA_HDR_MARK 4400 @@ -47,6 +52,8 @@ const char kHvacModeOptions[] = "HDCA"; * IR Send \*********************************************************************************************/ +#include + IRsend *irsend = NULL; void IrSendInit(void) @@ -64,11 +71,9 @@ void IrSendInit(void) * IR Receive \*********************************************************************************************/ -#define IR_TIME_AVOID_DUPLICATE 500 // Milliseconds +#include -// Based on IRremoteESP8266.h enum decode_type_t -const char kIrRemoteProtocols[] PROGMEM = - "UNKNOWN|RC5|RC6|NEC|SONY|PANASONIC|JVC|SAMSUNG|WHYNTER|AIWA_RC_T501|LG|SANYO|MITSUBISHI|DISH|SHARP"; +#define IR_TIME_AVOID_DUPLICATE 500 // Milliseconds IRrecv *irrecv = NULL; unsigned long ir_lasttime = 0; @@ -123,7 +128,7 @@ void IrReceiveCheck() boolean IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, boolean HVAC_Power, int HVAC_Temp) { - unsigned int rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; + uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; byte data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; char *p; diff --git a/sonoff/xsns_03_hlw8012.ino b/sonoff/xsns_03_hlw8012.ino index 0d1ffc411..a2655edc1 100644 --- a/sonoff/xsns_03_hlw8012.ino +++ b/sonoff/xsns_03_hlw8012.ino @@ -574,7 +574,7 @@ boolean HlwCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len, if ((payload > 0) && (payload < 16001) && hlw_cf1_current_pulse_length) { Settings.hlw_current_calibration = (payload * hlw_cf1_current_pulse_length) / HLW_IREF; } - snprintf_P(command, sizeof(command), PSTR(D_CMND_HLWPCAL)); + snprintf_P(command, sizeof(command), PSTR(D_CMND_HLWICAL)); nvalue = Settings.hlw_current_calibration; unit = UNIT_MICROSECOND; } diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index 3a9d48760..f4682de44 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -1,7 +1,7 @@ /* - xsns_12_ads1115.ino - ADS1x15 A/D Converter support for Sonoff-Tasmota + xsns_12_ads1115_ada.ino - ADS1115 A/D Converter support for Sonoff-Tasmota - Copyright (C) 2017 Stefan Bode and Theo Arends + Copyright (C) 2017 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,53 +22,135 @@ /*********************************************************************************************\ * ADS1115 - 4 channel 16BIT A/D converter * - * Required library: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/ADS1115 + * Required library: none but based on Adafruit Industries ADS1015 library * * I2C Address: 0x48, 0x49, 0x4A or 0x4B * * The ADC input range (or gain) can be changed via the following - * functions, but be careful never to exceed VDD +0.3V max, or to + * defines, but be careful never to exceed VDD +0.3V max, or to * exceed the upper and lower limits if you adjust the input range! * Setting these values incorrectly may destroy your ADC! - * ADS1015 ADS1115 - * ------- ------- - * ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default) - * ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV - * ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV - * ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV - * ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV - * ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV + * ADS1115 + * ------- + * ADS1115_REG_CONFIG_PGA_6_144V // 2/3x gain +/- 6.144V 1 bit = 0.1875mV + * ADS1115_REG_CONFIG_PGA_4_096V // 1x gain +/- 4.096V 1 bit = 0.125mV + * ADS1115_REG_CONFIG_PGA_2_048V // 2x gain +/- 2.048V 1 bit = 0.0625mV (default) + * ADS1115_REG_CONFIG_PGA_1_024V // 4x gain +/- 1.024V 1 bit = 0.03125mV + * ADS1115_REG_CONFIG_PGA_0_512V // 8x gain +/- 0.512V 1 bit = 0.015625mV + * ADS1115_REG_CONFIG_PGA_0_256V // 16x gain +/- 0.256V 1 bit = 0.0078125mV \*********************************************************************************************/ -#include +#define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND) +#define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC) +#define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin +#define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin -ADS1115 adc0; +#define ADS1115_CONVERSIONDELAY (8) // CONVERSION DELAY (in mS) + +/*====================================================================== +POINTER REGISTER +-----------------------------------------------------------------------*/ +#define ADS1115_REG_POINTER_MASK (0x03) +#define ADS1115_REG_POINTER_CONVERT (0x00) +#define ADS1115_REG_POINTER_CONFIG (0x01) +#define ADS1115_REG_POINTER_LOWTHRESH (0x02) +#define ADS1115_REG_POINTER_HITHRESH (0x03) + +/*====================================================================== +CONFIG REGISTER +-----------------------------------------------------------------------*/ +#define ADS1115_REG_CONFIG_OS_MASK (0x8000) +#define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) // Write: Set to start a single-conversion +#define ADS1115_REG_CONFIG_OS_BUSY (0x0000) // Read: Bit = 0 when conversion is in progress +#define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) // Read: Bit = 1 when device is not performing a conversion + +#define ADS1115_REG_CONFIG_MUX_MASK (0x7000) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) // Differential P = AIN0, N = AIN1 (default) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) // Differential P = AIN0, N = AIN3 +#define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) // Differential P = AIN1, N = AIN3 +#define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) // Differential P = AIN2, N = AIN3 +#define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) // Single-ended AIN0 +#define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) // Single-ended AIN1 +#define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) // Single-ended AIN2 +#define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) // Single-ended AIN3 + +#define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) +#define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) // +/-6.144V range = Gain 2/3 +#define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) // +/-4.096V range = Gain 1 +#define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) // +/-2.048V range = Gain 2 (default) +#define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) // +/-1.024V range = Gain 4 +#define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) // +/-0.512V range = Gain 8 +#define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) // +/-0.256V range = Gain 16 + +#define ADS1115_REG_CONFIG_MODE_MASK (0x0100) +#define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) // Continuous conversion mode +#define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) // Power-down single-shot mode (default) + +#define ADS1115_REG_CONFIG_DR_MASK (0x00E0) +#define ADS1115_REG_CONFIG_DR_128SPS (0x0000) // 128 samples per second +#define ADS1115_REG_CONFIG_DR_250SPS (0x0020) // 250 samples per second +#define ADS1115_REG_CONFIG_DR_490SPS (0x0040) // 490 samples per second +#define ADS1115_REG_CONFIG_DR_920SPS (0x0060) // 920 samples per second +#define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) // 1600 samples per second (default) +#define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) // 2400 samples per second +#define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) // 3300 samples per second +#define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) // 6000 samples per second + +#define ADS1115_REG_CONFIG_CMODE_MASK (0x0010) +#define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default) +#define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) // Window comparator + +#define ADS1115_REG_CONFIG_CPOL_MASK (0x0008) +#define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) // ALERT/RDY pin is low when active (default) +#define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) // ALERT/RDY pin is high when active + +#define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) // Determines if ALERT/RDY pin latches once asserted +#define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) // Non-latching comparator (default) +#define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) // Latching comparator + +#define ADS1115_REG_CONFIG_CQUE_MASK (0x0003) +#define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) // Assert ALERT/RDY after one conversions +#define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) // Assert ALERT/RDY after two conversions +#define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) // Assert ALERT/RDY after four conversions +#define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default) uint8_t ads1115_type = 0; uint8_t ads1115_address; -uint8_t ads1115_addresses[] = { - ADS1115_ADDRESS_ADDR_GND, // address pin low (GND) - ADS1115_ADDRESS_ADDR_VDD, // address pin high (VCC) - ADS1115_ADDRESS_ADDR_SDA, // address pin tied to SDA pin - ADS1115_ADDRESS_ADDR_SCL // address pin tied to SCL pin -}; +uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; -int16_t Ads1115GetConversion(byte channel) +//Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); +//Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); +void Ads1115StartComparator(uint8_t channel, uint16_t mode) { - switch (channel) { - case 0: - adc0.getConversionP0GND(); - break; - case 1: - adc0.getConversionP1GND(); - break; - case 2: - adc0.getConversionP2GND(); - break; - case 3: - adc0.getConversionP3GND(); - break; - } + // Start with default values + uint16_t config = mode | + ADS1115_REG_CONFIG_CQUE_NONE | // Comparator enabled and asserts on 1 match + ADS1115_REG_CONFIG_CLAT_NONLAT | // Non Latching mode + ADS1115_REG_CONFIG_PGA_2_048V | // ADC Input voltage range (Gain) + ADS1115_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val) + ADS1115_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val) + ADS1115_REG_CONFIG_DR_6000SPS; // 6000 samples per second + + // Set single-ended input channel + config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel)); + + // Write config register to the ADC + I2cWrite16(ads1115_address, ADS1115_REG_POINTER_CONFIG, config); +} + +int16_t Ads1115GetConversion(uint8_t channel) +{ + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); + // Wait for the conversion to complete + delay(ADS1115_CONVERSIONDELAY); + // Read the conversion results + I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT); + + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); + delay(ADS1115_CONVERSIONDELAY); + // Read the conversion results + uint16_t res = I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT); + return (int16_t)res; } /********************************************************************************************/ @@ -81,12 +163,8 @@ void Ads1115Detect() for (byte i = 0; i < sizeof(ads1115_addresses); i++) { ads1115_address = ads1115_addresses[i]; - ADS1115 adc0(ads1115_address); - if (adc0.testConnection()) { - adc0.initialize(); - adc0.setGain(ADS1115_PGA_2P048); // Set the gain (PGA) +/-4.096V - adc0.setRate(ADS1115_RATE_860); - adc0.setMode(ADS1115_MODE_CONTINUOUS); + if (I2cRead16(ads1115_address, ADS1115_REG_POINTER_CONVERT)) { + Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); ads1115_type = 1; break; } diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino new file mode 100644 index 000000000..10def543c --- /dev/null +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -0,0 +1,162 @@ +/* + xsns_12_ads1115.ino - ADS1x15 A/D Converter support for Sonoff-Tasmota + + Copyright (C) 2017 Stefan Bode and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_I2C +#ifdef USE_ADS1115_I2CDEV +/*********************************************************************************************\ + * ADS1115 - 4 channel 16BIT A/D converter + * + * Required library: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/ADS1115 + * + * I2C Address: 0x48, 0x49, 0x4A or 0x4B + * + * The ADC input range (or gain) can be changed via the following + * functions, but be careful never to exceed VDD +0.3V max, or to + * exceed the upper and lower limits if you adjust the input range! + * Setting these values incorrectly may destroy your ADC! + * ADS1015 ADS1115 + * ------- ------- + * ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default) + * ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV + * ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV + * ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV + * ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV + * ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV +\*********************************************************************************************/ + +#include + +ADS1115 adc0; + +uint8_t ads1115_type = 0; +uint8_t ads1115_address; +uint8_t ads1115_addresses[] = { + ADS1115_ADDRESS_ADDR_GND, // address pin low (GND) + ADS1115_ADDRESS_ADDR_VDD, // address pin high (VCC) + ADS1115_ADDRESS_ADDR_SDA, // address pin tied to SDA pin + ADS1115_ADDRESS_ADDR_SCL // address pin tied to SCL pin +}; + +int16_t Ads1115GetConversion(byte channel) +{ + switch (channel) { + case 0: + adc0.getConversionP0GND(); + break; + case 1: + adc0.getConversionP1GND(); + break; + case 2: + adc0.getConversionP2GND(); + break; + case 3: + adc0.getConversionP3GND(); + break; + } +} + +/********************************************************************************************/ + +void Ads1115Detect() +{ + if (ads1115_type) { + return; + } + + for (byte i = 0; i < sizeof(ads1115_addresses); i++) { + ads1115_address = ads1115_addresses[i]; + ADS1115 adc0(ads1115_address); + if (adc0.testConnection()) { + adc0.initialize(); + adc0.setGain(ADS1115_PGA_2P048); // Set the gain (PGA) +/-4.096V + adc0.setRate(ADS1115_RATE_860); + adc0.setMode(ADS1115_MODE_CONTINUOUS); + ads1115_type = 1; + break; + } + } + if (ads1115_type) { + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address); + AddLog(LOG_LEVEL_DEBUG); + } +} + +void Ads1115Show(boolean json) +{ + if (ads1115_type) { + char stemp[10]; + + byte dsxflg = 0; + for (byte i = 0; i < 4; i++) { + int16_t adc_value = Ads1115GetConversion(i); + + if (json) { + if (!dsxflg ) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":{"), mqtt_data); + stemp[0] = '\0'; + } + dsxflg++; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_ANALOG_INPUT "%d\":%d"), mqtt_data, stemp, i, adc_value); + strcpy(stemp, ","); +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value); +#endif // USE_WEBSERVER + } + } + if (json) { + if (dsxflg) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + } + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_12 + +boolean Xsns12(byte function) +{ + boolean result = false; + + if (i2c_flg) { + switch (function) { +// case FUNC_XSNS_INIT: +// break; + case FUNC_XSNS_PREP: + Ads1115Detect(); + break; + case FUNC_XSNS_JSON_APPEND: + Ads1115Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_XSNS_WEB: + Ads1115Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_ADS1115_I2CDEV +#endif // USE_I2C