diff --git a/.gitignore b/.gitignore index 7c759ade..a94330dd 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,6 @@ xtensa-esp32-elf/ xtensa-esp32-elf_psram/ backup.sh + + +\.vscode/ diff --git a/LICENSE.md b/LICENSE.md index 8df14915..9512d2cd 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,24 +1,256 @@ # MicroPython for ESP32 -# License information +## License information -All the source code in this repository is released under MIT or Apache v2.0 license, with the exceptions mentioned bellow. +
+All the source code in this repository is released under MIT or Apache v2.0 license. All the sources related to **MicroPython** are under **MIT** license. -**esp-idf** on which this port is based, is released under **Apache v2.0** license. +**esp-idf** on which this port is based, is released under **Apache v2.0** license ([details](http://esp-idf.readthedocs.io/en/latest/COPYRIGHT.html)). -All the sources created/modified by the repository owner are released under **MIT** license and contains the following copyright notice:
-*Copyright (c) 2018 LoBo (https://github.com/loboris)* +> All the sources created/modified by the repository owner are released under **MIT** license and contains the following copyright notice:
+> *Copyright (c) 2018 LoBo (https://github.com/loboris)* Most of the source files contains license and copyright notice, please check the individual files for more information.
-Also check the license information in individual components directories. +Also check the license information in individual components directories.
--- -The only exception to the MIT/Apache licensing is the **quickmail** library (*MicroPython_BUILD/components/quickmail*) which is licensed under **GNU GPL** v3.0+ license. +``` + +The MIT License (MIT) + +Copyright (c) 2018, LoBo (https://github.com/loboris) + +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. + +``` + +--- + +``` + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +--- -In case you don't want to use GPL licensed code, the library (it's directory) can be **removed** (deleted) from the repository clone/fork, leaving the project only **MIT/Apache** licensed. -To build the project without quickmail support disable
-`→ MicroPython → Modules → MAIL support in Curl module` in **menuconfig** diff --git a/MicroPython_BUILD/.cproject b/MicroPython_BUILD/.cproject index 74a90087..ea47ad5f 100644 --- a/MicroPython_BUILD/.cproject +++ b/MicroPython_BUILD/.cproject @@ -26,7 +26,7 @@ - - @@ -117,7 +125,6 @@ ${PWD}/BUILD.sh - -j8 all true false @@ -125,7 +132,6 @@ ${PWD}/BUILD.sh - flash true false @@ -133,7 +139,6 @@ ${PWD}/BUILD.sh - clean true false @@ -141,13 +146,14 @@ ${PWD}/BUILD.sh - -v all + -v -f16 all true false true ${PWD}/BUILD.sh + -f8 flash true false @@ -155,6 +161,7 @@ ${PWD}/BUILD.sh + -f16 flash true false @@ -177,14 +184,13 @@ ${PWD}/BUILD.sh - -j8 clean all + -j8 -f16 clean all true false true ${PWD}/BUILD.sh - -j8 clean all flash true false @@ -193,7 +199,14 @@ mate-terminal --working-directory="${PWD}" -e "./BUILD.sh menuconfig" & - + true + false + true + + + ${PWD}/BUILD.sh + + -j8 -v clean all true false true diff --git a/MicroPython_BUILD/.gitignore b/MicroPython_BUILD/.gitignore index 9ff72e14..bd16cacc 100644 --- a/MicroPython_BUILD/.gitignore +++ b/MicroPython_BUILD/.gitignore @@ -22,9 +22,12 @@ build/ patches/ -partitions_mpy.csv +*.id +qstrdefs.generated.h +/partitions_mpy.csv /sdkconfig sdkconfig.old +sdkconfig.lobo _sdkconfig.saved sdkconfig.fw_esp32 sdkconfig.fw_esp32_ota @@ -32,6 +35,8 @@ sdkconfig.fw_psram sdkconfig.fw_psram_ota sdkconfig.fw_all sdkconfig.fw_psram_all +sdkconfig.fw_psram_all_bt make_firmwares.sh +make_firmware_archives.sh mncfg_exit.txt diff --git a/MicroPython_BUILD/.project b/MicroPython_BUILD/.project index 090b3570..db89833e 100644 --- a/MicroPython_BUILD/.project +++ b/MicroPython_BUILD/.project @@ -30,4 +30,33 @@ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature org.python.pydev.pythonNature + + + 1519906740649 + + 30 + + org.eclipse.ui.ide.multiFilter + 1.0-projectRelativePath-matches-true-false-components/mkfatfs + + + + 1519906740652 + + 30 + + org.eclipse.ui.ide.multiFilter + 1.0-projectRelativePath-matches-true-false-components/mkspiffs + + + + 1519906740654 + + 30 + + org.eclipse.ui.ide.multiFilter + 1.0-projectRelativePath-matches-false-false-components/mpy_cross_build + + + diff --git a/MicroPython_BUILD/.settings/language.settings.xml b/MicroPython_BUILD/.settings/language.settings.xml index a3d2bfd4..e93938fc 100644 --- a/MicroPython_BUILD/.settings/language.settings.xml +++ b/MicroPython_BUILD/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + diff --git a/MicroPython_BUILD/.settings/org.eclipse.cdt.codan.core.prefs b/MicroPython_BUILD/.settings/org.eclipse.cdt.codan.core.prefs index 1a171177..4990fb05 100644 --- a/MicroPython_BUILD/.settings/org.eclipse.cdt.codan.core.prefs +++ b/MicroPython_BUILD/.settings/org.eclipse.cdt.codan.core.prefs @@ -18,13 +18,15 @@ org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={lau org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error @@ -69,4 +71,6 @@ org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} +org.eclipse.cdt.qt.core.qtproblem=Warning +org.eclipse.cdt.qt.core.qtproblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>false,RUN_ON_INC_BUILD\=>false,RUN_ON_FILE_OPEN\=>true,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>null} useParentScope=false diff --git a/MicroPython_BUILD/BUILD.sh b/MicroPython_BUILD/BUILD.sh index fe22af0f..bf9ac0fa 100755 --- a/MicroPython_BUILD/BUILD.sh +++ b/MicroPython_BUILD/BUILD.sh @@ -20,23 +20,30 @@ # makefatfs - create FatFS image # flashfatfs - create and flash FatFS image to ESP32 # copyfatfs - flash prebuilt FatFS image to ESP32 +# makelfsfs - create LittleFS image +# flashlfsfs - create and flash LittleFS image to ESP32 +# copylfsfs - flash prebuilt LittleFS image to ESP32 # size - display static memory footprint of the firmware # size-components - display detailed memory footprint of the firmware # size-files - display detailed memory footprint of the firmware +# miniterm - start pySerial command line program miniterm +# monitor - start esp-idf terminal emulator # Options: # -jN - make with multicore option, N should be the number of cores used -# -v | --verbose - enable verbose output, default: quiet output -# -f8 | --flashsize8 - declare the Flash size of 8 MB -# -f16 | --flashsize16 - declare the Flash size of 16 MB -# -fs | --fssize= - declare the size of Flash file system in KB +# -v | --verbose - enable verbose output, default: quiet output +# -f8 | --flashsize8 - declare the Flash size of 8 MB +# -f16 | --flashsize16 - declare the Flash size of 16 MB +# -fs | --fssize= - declare the size of Flash file system in KB # default: fit the Flash size -# -a | --appsize= - declare the size of application partition in KB +# -a | --appsize= - declare the size of application partition in KB # default: auto detect needed size # the actual size will be 128 KB smaller then the declared size +# -p | --port= - overwritte configured comm port, use the specified instead +# -b | --bdrate= - overwritte configured baud rate, use the specified instead # Note: -# Multiple commands can be given +# Multiple options and commands can be given # ################################################################# @@ -45,7 +52,8 @@ #======================= -TOOLS_VER=ver20180228.id +TOOLS_VER=ver20180827.id +BUILD_VER=ver20180904.id #======================= # ----------------------------- @@ -61,6 +69,8 @@ FORCE_3PART="no" POSITIONAL_ARGS=() BUILD_TYPE="" BUILD_BASE_DIR=${PWD} +BUILD_COMPORT="" +BUILD_BDRATE="" # --------------------------------------- # Include functions used in build process @@ -87,6 +97,7 @@ if [ $? -ne 0 ]; then exit 1 fi +# Goto base repository directory cd ../ # ----------------------------------- @@ -173,11 +184,21 @@ export CROSS_COMPILE=xtensa-esp32-elf- for arg in "${POSITIONAL_ARGS[@]}" do - if [ "${arg}" == "all" ] || [ "${arg}" == "flash" ] || [ "${arg}" == "makefs" ] || [ "${arg}" == "flashfs" ] || [ "${arg}" == "makefatfs" ] || [ "${arg}" == "flashfatfs" ]; then + if [ "${arg}" == "menuconfig" ]; then + check_config + result=$? + if [ $result -eq 1 ]; then + make menuconfig 2>/dev/null + fi + fi + if [ "${arg}" == "all" ] || [ "${arg}" == "flash" ] || [ "${arg}" == "makefs" ] || [ "${arg}" == "flashfs" ] || [ "${arg}" == "makefatfs" ] || [ "${arg}" == "flashfatfs" ] || [ "${arg}" == "makelfsfs" ] || [ "${arg}" == "flashlfsfs" ]; then set_partitions ${APP_SIZE} if [ $? -ne 0 ]; then exit 1 fi + if [ "${arg}" == "all" ] || [ "${arg}" == "flash" ]; then + check_config + fi fi if [ "${arg}" == "flash" ]; then @@ -206,6 +227,7 @@ do if [ $result -eq 0 ]; then echo "OK." if [ "${arg}" == "all" ]; then + set_partitions ${APP_SIZE} echo "--------------------------------" echo "Build complete." echo "You can now run ./BUILD.sh flash" diff --git a/MicroPython_BUILD/Makefile b/MicroPython_BUILD/Makefile index d00bb780..4ad7dd7c 100644 --- a/MicroPython_BUILD/Makefile +++ b/MicroPython_BUILD/Makefile @@ -5,18 +5,20 @@ PROJECT_NAME := MicroPython -# ########################################################################## -# Variables for creating/flashing spiffs image file +# ########################################################################### +# Variables for creating/flashing image file ifeq ($(OS),Windows_NT) MKSPIFFS_BIN="mkspiffs.exe" MKFATFS_BIN="mkfatfs.exe" + MKLITTLEFS_BIN="mklfs.exe" else MKSPIFFS_BIN="mkspiffs" MKFATFS_BIN="mkfatfs" + MKLITTLEFS_BIN="mklfs" endif FILESYS_SIZE = $(shell echo $$(( $(CONFIG_MICROPY_INTERNALFS_SIZE) * 1024 ))) INTERNALFS_IMAGE_COMPONENT_PATH := $(PWD)/components/internalfs_image -# ########################################################################## +# ########################################################################### echo_flash_cmd: @@ -48,7 +50,35 @@ copyfs: @echo "-----------------------------" @echo "$(INTERNALFS_IMAGE_COMPONENT_PATH)/spiffs_image.img" @echo "-----------------------------" - $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_MICROPY_INTERNALFS_START) $(INTERNALFS_IMAGE_COMPONENT_PATH)/spiffs_image.img + $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_MICROPY_INTERNALFS_START) $(INTERNALFS_IMAGE_COMPONENT_PATH)/internalfs_image.img + +makelfsfs: + @echo "Making LittleFS image; Flash address: $(CONFIG_MICROPY_INTERNALFS_START), Size: $(CONFIG_MICROPY_INTERNALFS_SIZE) KB ..." + $(PROJECT_PATH)/components/mklittlefs/$(MKLITTLEFS_BIN) -b $(CONFIG_MICROPY_BLOCK_SIZE) -c $(CONFIG_MICROPY_BLOCK_COUNT) $(CONFIG_MICROPY_USE_WL) $(INTERNALFS_IMAGE_COMPONENT_PATH)/image $(BUILD_DIR_BASE)/lfs_image.img + @echo "--------------------------" + @echo "To flash to ESP32 execute:" + @echo "--------------------------" + @echo "$(ESPTOOLPY_WRITE_FLASH) $(CONFIG_MICROPY_INTERNALFS_START) $(BUILD_DIR_BASE)/lfs_image.img)" + @echo "--------------------------------" + @echo "or execute ./BUILD.sh flashlfsfs" + @echo "--------------------------------" + +flashlfsfs: + @echo "Making LittleFS image; Flash address: $(CONFIG_MICROPY_INTERNALFS_START), Size: $(CONFIG_MICROPY_INTERNALFS_SIZE) KB ..." + $(PROJECT_PATH)/components/mklittlefs/$(MKLITTLEFS_BIN) -b $(CONFIG_MICROPY_BLOCK_SIZE) -c $(CONFIG_MICROPY_BLOCK_COUNT) $(CONFIG_MICROPY_USE_WL) $(INTERNALFS_IMAGE_COMPONENT_PATH)/image $(BUILD_DIR_BASE)/lfs_image.img + @echo "----------------------" + @echo "Flashing the image ..." + @echo "----------------------" + $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_MICROPY_INTERNALFS_START) $(BUILD_DIR_BASE)/lfs_image.img + @echo "----------------------" + +copylfsfs: + @echo "-----------------------------------" + @echo "Flashing default LittleFS image ..." + @echo "-----------------------------------" + @echo "$(INTERNALFS_IMAGE_COMPONENT_PATH)/lfs_image.img" + @echo "-----------------------------" + $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_MICROPY_INTERNALFS_START) $(INTERNALFS_IMAGE_COMPONENT_PATH)/internalfs_image.img makefatfs: @echo "Making fatfs image; Flash address: $(CONFIG_MICROPY_INTERNALFS_START), Size: $(CONFIG_MICROPY_INTERNALFS_SIZE) KB ..." @@ -78,6 +108,6 @@ copyfatfs: @echo "----------------------------" @echo "$(INTERNALFS_IMAGE_COMPONENT_PATH)/fatfs_image.img" @echo "-----------------------------" - $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_MICROPY_INTERNALFS_START) $(INTERNALFS_IMAGE_COMPONENT_PATH)/fatfs_image.img + $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_MICROPY_INTERNALFS_START) $(INTERNALFS_IMAGE_COMPONENT_PATH)/internalfs_image.img include $(IDF_PATH)/make/project.mk diff --git a/MicroPython_BUILD/build_func.sh b/MicroPython_BUILD/build_func.sh index e9403d7f..3588d89b 100755 --- a/MicroPython_BUILD/build_func.sh +++ b/MicroPython_BUILD/build_func.sh @@ -1,6 +1,7 @@ fs_type_fat="no" fs_fat_sect=4096 +fs_use_wl="" linplatform="" linprocessor="" linmachine="" @@ -29,6 +30,20 @@ get_arguments() { ;; -fs|--fssize) FS_SIZE="$2" + shift # past argument + shift # past value + ;; + -p|--port) + BUILD_COMPORT="$2" + BUILD_COMPORT=" ESPPORT=${BUILD_COMPORT}" + + shift # past argument + shift # past value + ;; + -b|--bdrate) + BUILD_BDRATE="$2" + BUILD_BDRATE=" ESPBAUD=${BUILD_BDRATE}" + shift # past argument shift # past value ;; @@ -74,14 +89,33 @@ get_bin_size() { #---------------------- get_config_flash_sz() { - local cfg_fsfat=$(grep -e CONFIG_MICROPY_USE_SPIFFS=y sdkconfig) - if [ "${cfg_fsfat}" == "" ]; then + local cfg_fsfat=$(grep -e CONFIG_LITTLEFLASH_USE_WEAR_LEVELING=y sdkconfig) + if [ "${cfg_fsfat}" != "" ]; then + fs_use_wl="-w" + fi + + cfg_fsfat=$(grep -e CONFIG_MICROPY_FILESYSTEM_TYPE=1 sdkconfig) + if [ "${cfg_fsfat}" == "CONFIG_MICROPY_FILESYSTEM_TYPE=1" ]; then + # FatFS fs_type_fat="yes" cfg_fsfat=$(grep -e CONFIG_WL_SECTOR_SIZE_512=y sdkconfig) if [ "${cfg_fsfat}" == "CONFIG_WL_SECTOR_SIZE_512=y" ]; then fs_fat_sect=512 fi + else + cfg_fsfat=$(grep -e CONFIG_MICROPY_FILESYSTEM_TYPE=2 sdkconfig) + if [ "${cfg_fsfat}" == "CONFIG_MICROPY_FILESYSTEM_TYPE=2" ]; then + # LittleFS + fs_type_fat="yes" + cfg_fsfat=$(grep -e CONFIG_WL_SECTOR_SIZE_512=y sdkconfig) + if [ "${cfg_fsfat}" == "CONFIG_WL_SECTOR_SIZE_512=y" ]; then + if [ "${fs_use_wl}" == "-w" ]; then + fs_fat_sect=512 + fi + fi + fi fi + if [ ${FLASH_SIZE} -eq 4 ]; then # Flash size was not set by options, check config file local cfg_flashsz=$(grep -e CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y sdkconfig) @@ -96,6 +130,26 @@ get_config_flash_sz() { fi } +#--------------- +check_config() { + # If BT is enabled, check and modify, if needed, some configuration + local TMPVAR1="" + local USE_RFCOMM=$(grep -e CONFIG_MICROPY_USE_RFCOMM=y sdkconfig) + local USE_BT=$(grep -e CONFIG_MICROPY_USE_BLUETOOTH=y sdkconfig) + + if [ "${USE_RFCOMM}" == "CONFIG_MICROPY_USE_RFCOMM=y" ] || [ "${USE_BT}" == "CONFIG_MICROPY_USE_BLUETOOTH=y" ]; then + # change to RELEASE optimization level to decrease IRAM usage + TMPVAR1=$(grep -e CONFIG_OPTIMIZATION_LEVEL_DEBUG=y sdkconfig) + if [ "${TMPVAR1}" == "CONFIG_OPTIMIZATION_LEVEL_DEBUG=y" ]; then + sed --in-place='.bak1' 's/CONFIG_OPTIMIZATION_LEVEL_DEBUG=y/CONFIG_OPTIMIZATION_LEVEL_DEBUG=/g' sdkconfig + sed --in-place='.bak2' 's/CONFIG_OPTIMIZATION_LEVEL_RELEASE=/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/g' sdkconfig + rm -f sdkconfig.bak1 > /dev/null 2>&1 + rm -f sdkconfig.bak2 > /dev/null 2>&1 + return 1 + fi + fi + return 0 +} #----------------- set_partitions() { @@ -156,7 +210,7 @@ set_partitions() { fi echo "# -------------------------------------------------------" > partitions_mpy.csv - echo "# - Partition layout generaded by BUILD.sh script -" >> partitions_mpy.csv + echo "# - Partition layout generated by BUILD.sh script -" >> partitions_mpy.csv echo "# -------------------------------------------------------" >> partitions_mpy.csv echo "# Name, Type, SubType, Offset, Size, Flags" >> partitions_mpy.csv echo "# -------------------------------------------------------" >> partitions_mpy.csv @@ -199,7 +253,7 @@ set_partitions() { fi echo "# -------------------------------------------------------" > partitions_mpy.csv - echo "# - Partition layout generaded by BUILD.sh script -" >> partitions_mpy.csv + echo "# - Partition layout generated by BUILD.sh script -" >> partitions_mpy.csv echo "# -------------------------------------------------------" >> partitions_mpy.csv echo "# Name, Type, SubType, Offset, Size, Flags" >> partitions_mpy.csv echo "# -------------------------------------------------------" >> partitions_mpy.csv @@ -209,8 +263,13 @@ set_partitions() { echo "internalfs, data, ${PART_SUB_TYPE} , ${fs_size}K," >> partitions_mpy.csv fi fs_start_hex=$(printf "%x\n" $fs_start) + local fs_sector_count=$(( ($fs_size * 1024) / $fs_fat_sect )) + export CONFIG_MICROPY_INTERNALFS_START="0x${fs_start_hex}" export CONFIG_MICROPY_INTERNALFS_SIZE=${fs_size} + export CONFIG_MICROPY_BLOCK_SIZE=${fs_fat_sect} + export CONFIG_MICROPY_BLOCK_COUNT=${fs_sector_count} + export CONFIG_MICROPY_USE_WL=${fs_use_wl} return 0 } @@ -259,6 +318,7 @@ check_OS() { fi MK_SPIFFS_BIN="mkspiffs.exe" MK_FATFS_BIN="mkfatfs.exe" + MK_LITTLEFS_BIN="mklfs.exe" else if [ "${machine}" == "Linux" ]; then linplatform="$(uname -i)" @@ -267,6 +327,7 @@ check_OS() { fi MK_SPIFFS_BIN="mkspiffs" MK_FATFS_BIN="mkfatfs" + MK_LITTLEFS_BIN="mklfs" fi return 0 } @@ -278,9 +339,9 @@ check_OS() { # ================================================= #-------------------- check_Environment() { - # ---------------------------------------- - # Remove directories from previous version - # ---------------------------------------- + # -------------------------------------------------- + # Remove directories from early MicroPython versions + # -------------------------------------------------- if [ -d "esp-idf" ]; then rm -rf esp-idf/ > /dev/null 2>&1 rmdir esp-idf > /dev/null 2>&1 @@ -330,6 +391,9 @@ check_Environment() { rm -f *.id > /dev/null 2>&1 touch ${TOOLS_VER} echo "toolchains & esp-idf version" > ${TOOLS_VER} + rm -f ${BUILD_BASE_DIR}/*.id > /dev/null 2>&1 + touch ${BUILD_BASE_DIR}/${BUILD_VER} + echo "Build ID, do not delete this file" > ${BUILD_BASE_DIR}/${BUILD_VER} # remove executables rm -f ${BUILD_BASE_DIR}/components/mpy_cross_build/mpy-cross/mpy-cross > /dev/null 2>&1 rm -f ${BUILD_BASE_DIR}/components/mpy_cross_build/mpy-cross/mpy-cross.exe > /dev/null 2>&1 @@ -339,12 +403,30 @@ check_Environment() { rm -f ${BUILD_BASE_DIR}/components/mkspiffs/src/mkspiffs.exe > /dev/null 2>&1 rm -f ${BUILD_BASE_DIR}/components/mkfatfs/src/mkfatfs > /dev/null 2>&1 rm -f ${BUILD_BASE_DIR}/components/mkfatfs/src/mkfatfs.exe > /dev/null 2>&1 + rm -f ${BUILD_BASE_DIR}/components/mklittlefs/mklfs > /dev/null 2>&1 + rm -f ${BUILD_BASE_DIR}/components/mklittlefs/mklfs.exe > /dev/null 2>&1 # remove build directory and configs cp -f ${BUILD_BASE_DIR}/sdkconfig ${BUILD_BASE_DIR}/_sdkconfig.saved > /dev/null 2>&1 rm -f ${BUILD_BASE_DIR}/sdkconfig > /dev/null 2>&1 rm -f ${BUILD_BASE_DIR}/sdkconfig.old > /dev/null 2>&1 rm -rf ${BUILD_BASE_DIR}/build/ > /dev/null 2>&1 rmdir ${BUILD_BASE_DIR}/build > /dev/null 2>&1 + else + # ----------------------- + # Check the build version + # ----------------------- + if [ ! -f "${BUILD_BASE_DIR}/${BUILD_VER}" ]; then + echo "Build updated, running menuconfig is needed..." + rm -f ${BUILD_BASE_DIR}/*.id > /dev/null 2>&1 + touch ${BUILD_BASE_DIR}/${BUILD_VER} + echo "Build ID, do not delete this file" > ${BUILD_BASE_DIR}/${BUILD_VER} + # remove build directory and configs + cp -f ${BUILD_BASE_DIR}/sdkconfig ${BUILD_BASE_DIR}/_sdkconfig.saved > /dev/null 2>&1 + rm -f ${BUILD_BASE_DIR}/sdkconfig > /dev/null 2>&1 + rm -f ${BUILD_BASE_DIR}/sdkconfig.old > /dev/null 2>&1 + rm -rf ${BUILD_BASE_DIR}/build/ > /dev/null 2>&1 + rmdir ${BUILD_BASE_DIR}/build > /dev/null 2>&1 + fi fi if [ ! -d "esp-idf" ]; then @@ -366,6 +448,9 @@ check_Environment() { elif [ "${linplatform}" == "armv7l" ] || [ "${linprocessor}" == "armv7l" ] || [ "${linmachine}" == "armv7l" ]; then echo "unpacking ${machine}/xtensa-esp32-elf (arm)" tar -xf ${machine}/xtensa-esp32-elf_arm.tar.xz > /dev/null 2>&1 + elif [ "${linmachine}" == "aarch64" ]; then + echo "unpacking ${machine}/xtensa-esp32-elf (aarch64)" + tar -xf ${machine}/xtensa-esp32-elf_aarch64.tar.xz > /dev/null 2>&1 else echo "unpacking ${machine}/xtensa-esp32-elf" tar -xf ${machine}/xtensa-esp32-elf.tar.xz > /dev/null 2>&1 @@ -482,6 +567,33 @@ build_MKFatFS() { return 0 } +# =============================================================== +# Build mklfs program which creates LittleFS image from directory +# =============================================================== +#---------------- +build_MKlfsFS() { + if [ ! -f "components/mklittlefs/${MK_LITTLEFS_BIN}" ]; then + export CROSS_COMPILE="" + export PATH=${orig_PATH} + + export BUILD_DIR_BASE=${BUILD_BASE_DIR}/build + echo "===============" + echo "Building mklfs" + make -C components/mklittlefs > /dev/null 2>&1 + if [ $? -eq 0 ]; then + echo "OK." + echo "===============" + else + echo "FAILED" + echo "===============" + return 1 + fi + export PATH=${xtensa_PATH} + export CROSS_COMPILE=xtensa-esp32-elf- + fi + return 0 +} + # =================== # Check build command @@ -539,21 +651,28 @@ executeCommand() { echo "=========================================" echo "Flashing MicroPython firmware to ESP32..." echo "=========================================" - make ${J_OPTION} ${arg} 2>/dev/null + make ${J_OPTION} ${arg}${BUILD_COMPORT}${BUILD_BDRATE} 2>/dev/null # --------------------------------- elif [ "${arg}" == "erase" ]; then echo "======================" echo "Erasing ESP32 Flash..." echo "======================" - make erase_flash + make erase_flash${BUILD_COMPORT}${BUILD_BDRATE} + + # ------------------------------------ + elif [ "${arg}" == "miniterm" ]; then + echo "=====================" + echo "Executing miniterm..." + echo "=====================" + make simple_monitor${BUILD_COMPORT} # ---------------------------------- elif [ "${arg}" == "monitor" ]; then echo "============================" echo "Executing esp-idf monitor..." echo "============================" - make monitor + make monitor${BUILD_COMPORT} # --------------------------------- elif [ "${arg}" == "clean" ]; then @@ -586,6 +705,11 @@ executeCommand() { echo "** Restored 'sdkconfig' **'" fi make menuconfig 2>/dev/null + check_config + result=$? + if [ $result -eq 1 ]; then + make menuconfig 2>/dev/null + fi # --------------------------------- elif [ "${arg}" == "makefs" ]; then @@ -645,6 +769,35 @@ executeCommand() { echo "========================================" make copyfatfs + # ------------------------------------ + elif [ "${arg}" == "makelfsfs" ]; then + build_MKlfsFS + if [ $? -ne 0 ]; then + return 1 + fi + echo "==========================" + echo "Creating LittleFS image..." + echo "==========================" + make makelfsfs + + # ------------------------------------- + elif [ "${arg}" == "flashlfsfs" ]; then + build_MKlfsFS + if [ $? -ne 0 ]; then + return 1 + fi + echo "===================================" + echo "Flashing LittleFS image to ESP32..." + echo "===================================" + make flashlfsfs + + # ------------------------------------- + elif [ "${arg}" == "copylfsfs" ]; then + echo "===========================================" + echo "Flashing default LittleFS image to ESP32..." + echo "===========================================" + make copylfsfs + # ------------------------------- elif [ "${arg}" == "size" ]; then echo "=======================================" @@ -659,8 +812,8 @@ executeCommand() { echo "=========================================" make ${arg} 2>/dev/null - # ----------------------------------- - elif [ "${arg}" == "firmware" ] || [ "${arg}" == "firmwareall" ]; then + # ------------------------------------------------------------------------------------------------------- + elif [ "${arg}" == "firmware" ] || [ "${arg}" == "firmwareall" ] || [ "${arg}" == "firmwareallbt" ]; then echo "=======================" echo "Saving the firmware ..." echo "=======================" @@ -675,6 +828,13 @@ executeCommand() { esp32dir="esp32_all" fi fi + if [ "${arg}" == "firmwareallbt" ]; then + if [ "${BUILD_TYPE}" != "" ]; then + esp32dir="esp32_psram_all_bt" + else + esp32dir="esp32_all_bt" + fi + fi local useota=$(grep -e CONFIG_MICROPY_USE_OTA=y sdkconfig) if [ "${useota}" == "CONFIG_MICROPY_USE_OTA=y" ]; then esp32dir="${esp32dir}_ota" @@ -685,9 +845,7 @@ executeCommand() { cp -f partitions_mpy.csv firmware/${esp32dir} > /dev/null 2>&1 cp -f build/phy_init_data.bin firmware/${esp32dir} > /dev/null 2>&1 cp -f sdkconfig firmware/${esp32dir} > /dev/null 2>&1 - echo "#!/bin/bash" > firmware/${esp32dir}/flash.sh - make echo_flash_cmd >> firmware/${esp32dir}/flash.sh 2>/dev/null - chmod +x firmware/${esp32dir}/flash.sh > /dev/null 2>&1 + rm -f firmware/${esp32dir}/flash.sh > /dev/null 2>&1 return 0 # ------------------------------- diff --git a/MicroPython_BUILD/components/curl/include/curl/curl.h b/MicroPython_BUILD/components/curl/include/curl/curl.h index 86b9b708..af21768d 100644 --- a/MicroPython_BUILD/components/curl/include/curl/curl.h +++ b/MicroPython_BUILD/components/curl/include/curl/curl.h @@ -30,6 +30,8 @@ * https://cool.haxx.se/mailman/listinfo/curl-library/ */ +#include "sdkconfig.h" + #define SIZEOF_CURL_OFF_T 4 #ifdef CURL_NO_OLDIES @@ -218,7 +220,7 @@ typedef int (*curl_xferinfo_callback)(void *clientp, #ifndef CURL_MAX_READ_SIZE /* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */ -#define CURL_MAX_READ_SIZE 524288 +#define CURL_MAX_READ_SIZE 16384 #endif #ifndef CURL_MAX_WRITE_SIZE @@ -228,8 +230,12 @@ typedef int (*curl_xferinfo_callback)(void *clientp, time for those who feel adventurous. The practical minimum is about 400 bytes since libcurl uses a buffer of this size as a scratch area (unrelated to network send operations). */ +#ifdef CONFIG_MICROPY_CURL_MAX_WRITE_SIZE +#define CURL_MAX_WRITE_SIZE CONFIG_MICROPY_CURL_MAX_WRITE_SIZE +#else #define CURL_MAX_WRITE_SIZE 16384 #endif +#endif #ifndef CURL_MAX_HTTP_HEADER /* The only reason to have a max limit for this is to avoid the risk of a bad diff --git a/MicroPython_BUILD/components/curl/lib/connect.c b/MicroPython_BUILD/components/curl/lib/connect.c index 3edb71eb..6eb38c26 100644 --- a/MicroPython_BUILD/components/curl/lib/connect.c +++ b/MicroPython_BUILD/components/curl/lib/connect.c @@ -1409,11 +1409,13 @@ void Curl_conncontrol(struct connectdata *conn, bool closeit = (ctrl == CONNCTRL_CONNECTION) || ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM)); if((ctrl == CONNCTRL_STREAM) && - (conn->handler->flags & PROTOPT_STREAM)) - DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); + (conn->handler->flags & PROTOPT_STREAM)) { + //DEBUGF(infof(conn->data, "Kill stream: %s\n", reason)); + DEBUGF(infof(conn->data, "Kill stream\n")); + } else if(closeit != conn->bits.close) { - DEBUGF(infof(conn->data, "Marked for [%s]: %s\n", - closeit?"closure":"keep alive", reason)); + //DEBUGF(infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive", reason)); + DEBUGF(infof(conn->data, "Marked for [%s]\n", closeit?"closure":"keep alive")); conn->bits.close = closeit; /* the only place in the source code that should assign this bit */ } diff --git a/MicroPython_BUILD/components/curl/lib/ssh.c b/MicroPython_BUILD/components/curl/lib/ssh.c index e0a0b32b..94261aaf 100644 --- a/MicroPython_BUILD/components/curl/lib/ssh.c +++ b/MicroPython_BUILD/components/curl/lib/ssh.c @@ -395,7 +395,7 @@ static void state(struct connectdata *conn, sshstate nowstate) sshc->state = nowstate; } - +/* // ==== LoBo =============================================== int access (const char *file, int type) @@ -446,7 +446,7 @@ return 0; } // ==== LoBo =============================================== - +*/ #ifdef HAVE_LIBSSH2_KNOWNHOST_API static int sshkeycallback(struct Curl_easy *easy, diff --git a/MicroPython_BUILD/components/espmqtt/.gitignore b/MicroPython_BUILD/components/espmqtt/.gitignore index f805e810..2c4b72c7 100644 --- a/MicroPython_BUILD/components/espmqtt/.gitignore +++ b/MicroPython_BUILD/components/espmqtt/.gitignore @@ -31,3 +31,6 @@ # Debug files *.dSYM/ *.su +build +examples/**/build +examples/**/sdkconfig* diff --git a/MicroPython_BUILD/components/espmqtt/README.md b/MicroPython_BUILD/components/espmqtt/README.md index be5a1bbe..447c103b 100644 --- a/MicroPython_BUILD/components/espmqtt/README.md +++ b/MicroPython_BUILD/components/espmqtt/README.md @@ -1,5 +1,175 @@ +[![](https://travis-ci.org/tuanpmt/espmqtt.svg?branch=master)](https://travis-ci.org/tuanpmt/espmqtt) +[![](http://hits.dwyl.io/tuanpmt/espmqtt.svg)](http://hits.dwyl.io/tuanpmt/espmqtt) +[![Twitter Follow](https://img.shields.io/twitter/follow/tuanpmt.svg?style=social&label=Follow)](https://twitter.com/tuanpmt) +![GitHub contributors](https://img.shields.io/github/contributors/tuanpmt/espmqtt.svg) + # ESP32 MQTT Library -This is component based on ESP-IDF for ESP32 +## Features + +- Based on: https://github.com/tuanpmt/esp_mqtt +- Support MQTT over TCP, SSL with mbedtls, MQTT over Websocket, MQTT over Websocket Secure +- Easy to setup with URI +- Multiple instances (Multiple clients in one application) +- Support subscribing, publishing, authentication, will messages, keep alive pings and all 3 QoS levels (it should be a fully functional client). + +## How to use + +Clone this component to [ESP-IDF](https://github.com/espressif/esp-idf) project (as submodule): +``` +git submodule add https://github.com/tuanpmt/espmqtt.git components/espmqtt +``` + +Or run a sample (make sure you have installed the [toolchain](http://esp-idf.readthedocs.io/en/latest/get-started/index.html#setup-toolchain)): + +``` +git clone https://github.com/tuanpmt/espmqtt.git +cd espmqtt/examples/mqtt_tcp +make menuconfig +make flash monitor +``` + +## Documentation +### URI + +- Curently support `mqtt`, `mqtts`, `ws`, `wss` schemes +- MQTT over TCP samples: + + `mqtt://iot.eclipse.org`: MQTT over TCP, default port 1883: + + `mqtt://iot.eclipse.org:1884` MQTT over TCP, port 1884: + + `mqtt://username:password@iot.eclipse.org:1884` MQTT over TCP, port 1884, with username and password +- MQTT over SSL samples: + + `mqtts://iot.eclipse.org`: MQTT over SSL, port 8883 + + `mqtts://iot.eclipse.org:8884`: MQTT over SSL, port 8884 +- MQTT over Websocket samples: + + `ws://iot.eclipse.org:80/ws` +- MQTT over Websocket Secure samples: + + `wss://iot.eclipse.org:443/ws` +- Minimal configurations: + +```c +const esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtt://iot.eclipse.org", + .event_handle = mqtt_event_handler, + // .user_context = (void *)your_context +}; +``` + +- If there are any options related to the URI in `esp_mqtt_client_config_t`, the option defined by the URI will be overridden. Sample: + +```c +const esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtt://iot.eclipse.org:1234", + .event_handle = mqtt_event_handler, + .port = 4567, +}; +//MQTT client will connect to iot.eclipse.org using port 4567 +``` + + +### SSL + +- Get Certification from server, example: `iot.eclipse.org` `openssl s_client -showcerts -connect iot.eclipse.org:8883 /dev/null|openssl x509 -outform PEM >iot_eclipse_org.pem` +- Check the sample application: `examples/mqtt_ssl` +- Configuration: + +```cpp +const esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtts://iot.eclipse.org:8883", + .event_handle = mqtt_event_handler, + .cert_pem = (const char *)iot_eclipse_org_pem_start, +}; +``` + + +### More options for `esp_mqtt_client_config_t` + +- `event_handle` for MQTT events +- `host`: MQTT server domain (ipv4 as string) +- `port`: MQTT server port +- `client_id`: default client id is `ESP32_%CHIPID%` +- `username`: MQTT username +- `password`: MQTT password +- `lwt_topic, lwt_msg, lwt_qos, lwt_retain, lwt_msg_len`: are mqtt lwt options, default NULL +- `disable_clean_session`: mqtt clean session, default clean_session is true +- `keepalive`: (value in seconds) mqtt keepalive, default is 120 seconds +- `disable_auto_reconnect`: this mqtt client will reconnect to server (when errors/disconnect). Set `disable_auto_reconnect=true` to disable +- `user_context` pass user context to this option, then can receive that context in `event->user_context` +- `task_prio, task_stack` for MQTT task, default priority is 5, and task_stack = 6144 bytes (or default task stack can be set via `make menucofig`). +- `buffer_size` for MQTT send/receive buffer, default is 1024 +- `cert_pem` pointer to CERT file for server verify (with SSL), default is NULL, not required to verify the server +- `transport`: override URI transport + + `MQTT_TRANSPORT_OVER_TCP`: MQTT over TCP, using scheme: `mqtt` + + `MQTT_TRANSPORT_OVER_SSL`: MQTT over SSL, using scheme: `mqtts` + + `MQTT_TRANSPORT_OVER_WS`: MQTT over Websocket, using scheme: `ws` + + `MQTT_TRANSPORT_OVER_WSS`: MQTT over Websocket Secure, using scheme: `wss` + +### Change settings in `menuconfig` + +``` +make menuconfig +-> Component config -> ESPMQTT Configuration +``` + +## Example + +Check `examples/mqtt_tcp` and `examples/mqtt_ssl` project. In Short: + +```cpp + +static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) +{ + esp_mqtt_client_handle_t client = event->client; + int msg_id; + // your_context_t *context = event->context; + switch (event->event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED"); + msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + + msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); + ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); + + msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); + ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED"); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); + ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_DATA: + ESP_LOGI(TAG, "MQTT_EVENT_DATA"); + printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); + printf("DATA=%.*s\r\n", event->data_len, event->data); + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(TAG, "MQTT_EVENT_ERROR"); + break; + } + return ESP_OK; +} +const esp_mqtt_client_config_t mqtt_cfg = { + .uri = "mqtt://iot.eclipse.org", + .event_handle = mqtt_event_handler, + // .user_context = (void *)your_context +}; + +esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); +esp_mqtt_client_start(client); +``` + +## License -Full documentation and sample project: https://github.com/tuanpmt/esp32-mqtt +[@tuanpmt](https://twitter.com/tuanpmt) +Apache License diff --git a/MicroPython_BUILD/components/espmqtt/component.mk b/MicroPython_BUILD/components/espmqtt/component.mk index 229049dd..79bcc62c 100644 --- a/MicroPython_BUILD/components/espmqtt/component.mk +++ b/MicroPython_BUILD/components/espmqtt/component.mk @@ -6,8 +6,5 @@ # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, # please read the SDK documents if you need to do this. # -COMPONENT_ADD_INCLUDEDIRS := include -#COMPONENT_PRIV_INCLUDEDIRS := - -#EXTRA_CFLAGS := -DICACHE_RODATA_ATTR -CFLAGS += -Wno-error=implicit-function-declaration -Wno-error=format= -DHAVE_CONFIG_H +COMPONENT_SRCDIRS := . lib +COMPONENT_PRIV_INCLUDEDIRS := lib/include diff --git a/MicroPython_BUILD/components/espmqtt/include/mqtt.h b/MicroPython_BUILD/components/espmqtt/include/mqtt.h deleted file mode 100644 index a6283ea6..00000000 --- a/MicroPython_BUILD/components/espmqtt/include/mqtt.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Boris Lovosevic (https://github.com/loboris) - * - * 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. - */ - -/* - * Mqtt Module using MQTT task. - * Based on ESP32 MQTT Library by Tuan PM, https://github.com/tuanpmt/espmqtt - * Adapted for MicroPython by Boris Lovosevic, https://github.com/loboris - * - */ - -#ifndef _MQTT_H_ -#define _MQTT_H_ - -#include "sdkconfig.h" - -#ifdef CONFIG_MICROPY_USE_MQTT - -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" - -#include "mqtt_msg.h" -#include "ringbuf.h" - -#include "openssl/ssl.h" - -// Constants not defined in menuconfig -#define CONFIG_MQTT_MAX_HOST_LEN 64 -#define CONFIG_MQTT_MAX_CLIENT_LEN 32 -#define CONFIG_MQTT_MAX_USERNAME_LEN 32 -#define CONFIG_MQTT_MAX_PASSWORD_LEN 32 -#define CONFIG_MQTT_MAX_LWT_TOPIC 32 -#define CONFIG_MQTT_MAX_LWT_MSG 32 -#define CONFIG_MQTT_MAX_TASKNAME_LEN 16 - -// Mqtt client status constants -#define MQTT_STATUS_DISCONNECTED 0 -#define MQTT_STATUS_CONNECTED 1 -#define MQTT_STATUS_STOPPING 2 -#define MQTT_STATUS_STOPPED 4 - -#define MQTT_SENDING_TYPE_NONE 0 -#define MQTT_SENDING_TYPE_PUBLISH 1 -#define MQTT_SENDING_TYPE_SUBSCRIBE 2 -#define MQTT_SENDING_TYPE_UNSUBSCRIBE 3 -#define MQTT_SENDING_TYPE_PING 4 - -typedef struct mqtt_client mqtt_client; -typedef struct mqtt_event_data_t mqtt_event_data_t; - -/** - * \return True on connect success, false on error - */ -typedef bool (* mqtt_connect_callback)(mqtt_client *client); -/** - */ -typedef void (* mqtt_disconnect_callback)(mqtt_client *client); -/** - * \param[out] buffer Pointer to buffer to fill - * \param[in] len Number of bytes to read - * \param[in] timeout_ms Time to wait for completion, or 0 for no timeout - * \return Number of bytes read, less than 0 on error - */ -typedef int (* mqtt_read_callback)(mqtt_client *client, void *buffer, int len, int timeout_ms); -/** - * \param[in] buffer Pointer to buffer to write - * \param[in] len Number of bytes to write - * \param[in] timeout_ms Time to wait for completion, or 0 for no timeout - * \return Number of bytes written, less than 0 on error - */ -typedef int (* mqtt_write_callback)(mqtt_client *client, const void *buffer, int len, int timeout_ms); -typedef void (* mqtt_event_callback)(mqtt_client *client, mqtt_event_data_t *event_data); - -typedef struct mqtt_settings { - mqtt_connect_callback connect_cb; - mqtt_disconnect_callback disconnect_cb; - - mqtt_read_callback read_cb; - mqtt_write_callback write_cb; - - mqtt_event_callback connected_cb; - mqtt_event_callback disconnected_cb; - - mqtt_event_callback subscribe_cb; - mqtt_event_callback unsubscribe_cb; - mqtt_event_callback publish_cb; - mqtt_event_callback data_cb; - - void *mpy_connected_cb; - void *mpy_disconnected_cb; - void *mpy_subscribed_cb; - void *mpy_unsubscribed_cb; - void *mpy_published_cb; - void *mpy_data_cb; - - char host[CONFIG_MQTT_MAX_HOST_LEN]; - uint16_t port; - char client_id[CONFIG_MQTT_MAX_CLIENT_LEN]; - char username[CONFIG_MQTT_MAX_USERNAME_LEN]; - char password[CONFIG_MQTT_MAX_PASSWORD_LEN]; - char lwt_topic[CONFIG_MQTT_MAX_LWT_TOPIC]; - char lwt_msg[CONFIG_MQTT_MAX_LWT_MSG]; - uint32_t lwt_msg_len; - uint32_t lwt_qos; - uint32_t lwt_retain; - uint32_t clean_session; - uint32_t keepalive; - bool auto_reconnect; - bool use_ssl; - TaskHandle_t xMqttTask; - TaskHandle_t xMqttSendingTask; - uint32_t xMqttTask_stacksize; - uint32_t xMqttSendingTask_stacksize; -} mqtt_settings; - -typedef struct mqtt_event_data_t -{ - uint8_t type; - const char* topic; - const char* data; - uint16_t topic_length; - uint16_t data_length; - uint32_t data_offset; - uint32_t data_total_length; -} mqtt_event_data_t; - -typedef struct mqtt_state_t -{ - uint16_t port; - int auto_reconnect; - mqtt_connect_info_t* connect_info; - uint8_t* in_buffer; - uint8_t* out_buffer; - int in_buffer_length; - int out_buffer_length; - uint16_t message_length; - uint16_t message_length_read; - mqtt_message_t* outbound_message; - mqtt_connection_t mqtt_connection; - uint16_t pending_msg_id; - int pending_msg_type; - int sending_msg_type; - int pending_publish_qos; -} mqtt_state_t; - -typedef struct mqtt_client { - int socket; - SSL_CTX *ctx; - SSL *ssl; - mqtt_settings *settings; - mqtt_state_t mqtt_state; - mqtt_connect_info_t connect_info; - QueueHandle_t xSendingQueue; - RINGBUF send_rb; - uint32_t keepalive_tick; - uint8_t status; - uint8_t subs_flag; - uint8_t unsubs_flag; - uint8_t *msgbuf; - uint8_t *topicbuf; - bool terminate_mqtt; - char *name; -} mqtt_client; - -const char *MQTT_TAG; - -int mqtt_start(mqtt_client *client); -void mqtt_stop(mqtt_client* client); -void mqtt_task(void *pvParameters); -void mqtt_subscribe(mqtt_client *client, const char *topic, uint8_t qos); -void mqtt_unsubscribe(mqtt_client *client, const char *topic); -int mqtt_publish(mqtt_client* client, const char *topic, const char *data, int len, int qos, int retain); -void mqtt_free(mqtt_client *client); - -#endif - -#endif diff --git a/MicroPython_BUILD/components/espmqtt/include/mqtt_client.h b/MicroPython_BUILD/components/espmqtt/include/mqtt_client.h new file mode 100755 index 00000000..1d9f7d9d --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/include/mqtt_client.h @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * Apache License Version 2.0 + * + * Slightly modified mqtt library from https://github.com/tuanpmt/espmqtt + * + * Copyright (c) 2018 tuanpm (https://github.com/tuanpmt/espmqtt) + * Copyright (c) 2018 LoBo (https://github.com/loboris) +*/ + +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ + +#ifndef _MQTT_CLIENT_H_ +#define _MQTT_CLIENT_H_ + +#include +#include +#include +#include "esp_err.h" + +#include "platform.h" +#include "mqtt_config.h" +#include "mqtt_msg.h" +#include "transport.h" +#include "transport_tcp.h" +#include "transport_ssl.h" +#include "transport_ws.h" +#include "platform.h" +#include "mqtt_outbox.h" + +typedef struct esp_mqtt_client* esp_mqtt_client_handle_t; + +typedef enum { + MQTT_EVENT_ERROR = 0, + MQTT_EVENT_CONNECTED, + MQTT_EVENT_DISCONNECTED, + MQTT_EVENT_SUBSCRIBED, + MQTT_EVENT_UNSUBSCRIBED, + MQTT_EVENT_PUBLISHED, + MQTT_EVENT_DATA, +} esp_mqtt_event_id_t; + +typedef enum { + MQTT_TRANSPORT_UNKNOWN = 0x0, + MQTT_TRANSPORT_OVER_TCP, + MQTT_TRANSPORT_OVER_SSL, + MQTT_TRANSPORT_OVER_WS, + MQTT_TRANSPORT_OVER_WSS +} esp_mqtt_transport_t; + +typedef enum { + MQTT_STATE_ERROR = -1, + MQTT_STATE_UNKNOWN = 0, + MQTT_STATE_INIT, + MQTT_STATE_CONNECTED, + MQTT_STATE_WAIT_TIMEOUT, +} mqtt_client_state_t; + +typedef struct { + esp_mqtt_event_id_t event_id; + esp_mqtt_client_handle_t client; + void *user_context; + char *data; + int data_len; + int total_data_len; + int current_data_offset; + char *topic; + int topic_len; + int msg_id; + int type; +} esp_mqtt_event_t; + +typedef esp_mqtt_event_t* esp_mqtt_event_handle_t; + +typedef esp_err_t (* mqtt_event_callback_t)(esp_mqtt_event_handle_t event); + + +typedef struct { + mqtt_event_callback_t event_handle; + char host[MQTT_MAX_HOST_LEN]; + char uri[MQTT_MAX_HOST_LEN]; + uint32_t port; + char client_id[MQTT_MAX_CLIENT_LEN]; + char username[MQTT_MAX_USERNAME_LEN]; + char password[MQTT_MAX_PASSWORD_LEN]; + char lwt_topic[MQTT_MAX_LWT_TOPIC]; + char lwt_msg[MQTT_MAX_LWT_MSG]; + int lwt_qos; + int lwt_retain; + int lwt_msg_len; + int disable_clean_session; + int keepalive; + bool disable_auto_reconnect; + void *user_context; + int task_prio; + int task_stack; + int buffer_size; + const char *cert_pem; + esp_mqtt_transport_t transport; +} esp_mqtt_client_config_t; + +typedef struct mqtt_state +{ + mqtt_connect_info_t *connect_info; + uint8_t *in_buffer; + uint8_t *out_buffer; + int in_buffer_length; + int out_buffer_length; + uint16_t message_length; + uint16_t message_length_read; + mqtt_message_t *outbound_message; + mqtt_connection_t mqtt_connection; + uint16_t pending_msg_id; + int pending_msg_type; + int pending_publish_qos; + int pending_msg_count; +} mqtt_state_t; + +typedef struct { + mqtt_event_callback_t event_handle; + int task_stack; + int task_prio; + char *uri; + char *host; + char *path; + char *scheme; + int port; + bool auto_reconnect; + void *user_context; + int network_timeout_ms; +} mqtt_config_storage_t; + +struct esp_mqtt_client { + transport_list_handle_t transport_list; + transport_handle_t transport; + mqtt_config_storage_t *config; + mqtt_state_t mqtt_state; + mqtt_connect_info_t connect_info; + mqtt_client_state_t state; + long long keepalive_tick; + long long reconnect_tick; + int wait_timeout_ms; + int auto_reconnect; + esp_mqtt_event_t event; + bool run; + outbox_handle_t outbox; + EventGroupHandle_t status_bits; + void *mpy_mqtt_obj; +}; + +extern const char *MQTT_TAG; + +esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config); +esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client, const char *uri); +esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client); +esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client); +esp_err_t esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos); +esp_err_t esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic); +int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain); +esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client); + +#endif diff --git a/MicroPython_BUILD/components/espmqtt/include/mqtt_config.h b/MicroPython_BUILD/components/espmqtt/include/mqtt_config.h new file mode 100644 index 00000000..b10744ee --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/include/mqtt_config.h @@ -0,0 +1,68 @@ +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ +#ifndef _MQTT_CONFIG_H_ +#define _MQTT_CONFIG_H_ + +#include "sdkconfig.h" + +#define MQTT_PROTOCOL_311 CONFIG_MQTT_PROTOCOL_311 +#define MQTT_RECONNECT_TIMEOUT_MS (10*1000) + +#if CONFIG_MQTT_BUFFER_SIZE +#define MQTT_BUFFER_SIZE_BYTE CONFIG_MQTT_BUFFER_SIZE +#else +#define MQTT_BUFFER_SIZE_BYTE 1024 +#endif + +#define MQTT_MAX_HOST_LEN 64 +#define MQTT_MAX_CLIENT_LEN 32 +#define MQTT_MAX_USERNAME_LEN 32 +#define MQTT_MAX_PASSWORD_LEN 65 +#define MQTT_MAX_LWT_TOPIC 32 +#define MQTT_MAX_LWT_MSG 128 +#define MQTT_TASK_PRIORITY 5 + +#if CONFIG_MQTT_TASK_STACK_SIZE +#define MQTT_TASK_STACK CONFIG_MQTT_TASK_STACK_SIZE +#else +#define MQTT_TASK_STACK (6*1024) +#endif + +#define MQTT_KEEPALIVE_TICK (120) +#define MQTT_CMD_QUEUE_SIZE (10) +#define MQTT_NETWORK_TIMEOUT_MS (10000) + +#ifdef CONFIG_MQTT_TCP_DEFAULT_PORT +#define MQTT_TCP_DEFAULT_PORT CONFIG_MQTT_TCP_DEFAULT_PORT +#else +#define MQTT_TCP_DEFAULT_PORT 1883 +#endif + +#ifdef CONFIG_MQTT_SSL_DEFAULT_PORT +#define MQTT_SSL_DEFAULT_PORT CONFIG_MQTT_SSL_DEFAULT_PORT +#else +#define MQTT_SSL_DEFAULT_PORT 8883 +#endif + +#ifdef CONFIG_MQTT_WS_DEFAULT_PORT +#define MQTT_WS_DEFAULT_PORT CONFIG_MQTT_WS_DEFAULT_PORT +#else +#define MQTT_WS_DEFAULT_PORT 80 +#endif + +#ifdef MQTT_WSS_DEFAULT_PORT +#define MQTT_WSS_DEFAULT_PORT CONFIG_MQTT_WSS_DEFAULT_PORT +#else +#define MQTT_WSS_DEFAULT_PORT 443 +#endif + +#define MQTT_ENABLE_SSL CONFIG_MQTT_TRANSPORT_SSL +#define MQTT_ENABLE_WS CONFIG_MQTT_TRANSPORT_WEBSOCKET +#define MQTT_ENABLE_WSS CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE + +#define OUTBOX_EXPIRED_TIMEOUT_MS (30*1000) +#define OUTBOX_MAX_SIZE (4*1024) +#endif diff --git a/MicroPython_BUILD/components/espmqtt/include/ringbuf.h b/MicroPython_BUILD/components/espmqtt/include/ringbuf.h deleted file mode 100644 index 6444b234..00000000 --- a/MicroPython_BUILD/components/espmqtt/include/ringbuf.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _RING_BUF_H_ -#define _RING_BUF_H_ - -#include - - -typedef struct{ - uint8_t* p_o; /**< Original pointer */ - uint8_t* volatile p_r; /**< Read pointer */ - uint8_t* volatile p_w; /**< Write pointer */ - volatile int32_t fill_cnt; /**< Number of filled slots */ - int32_t size; /**< Buffer size */ - int32_t block_size; -}RINGBUF; - -int32_t rb_init(RINGBUF *r, uint8_t* buf, int32_t size, int32_t block_size); -int32_t rb_put(RINGBUF *r, uint8_t* c); -int32_t rb_get(RINGBUF *r, uint8_t* c); -int32_t rb_available(RINGBUF *r); -uint32_t rb_read(RINGBUF *r, uint8_t *buf, int len); -uint32_t rb_write(RINGBUF *r, uint8_t *buf, int len); - -#endif diff --git a/MicroPython_BUILD/components/espmqtt/include/mqtt_msg.h b/MicroPython_BUILD/components/espmqtt/lib/include/mqtt_msg.h similarity index 75% rename from MicroPython_BUILD/components/espmqtt/include/mqtt_msg.h rename to MicroPython_BUILD/components/espmqtt/lib/include/mqtt_msg.h index 9aceecb6..fd04cd0f 100644 --- a/MicroPython_BUILD/components/espmqtt/include/mqtt_msg.h +++ b/MicroPython_BUILD/components/espmqtt/lib/include/mqtt_msg.h @@ -1,6 +1,6 @@ #ifndef MQTT_MSG_H #define MQTT_MSG_H - +#include "mqtt_config.h" #ifdef __cplusplus extern "C" { #endif @@ -42,61 +42,61 @@ extern "C" { enum mqtt_message_type { - MQTT_MSG_TYPE_CONNECT = 1, - MQTT_MSG_TYPE_CONNACK = 2, - MQTT_MSG_TYPE_PUBLISH = 3, - MQTT_MSG_TYPE_PUBACK = 4, - MQTT_MSG_TYPE_PUBREC = 5, - MQTT_MSG_TYPE_PUBREL = 6, - MQTT_MSG_TYPE_PUBCOMP = 7, - MQTT_MSG_TYPE_SUBSCRIBE = 8, - MQTT_MSG_TYPE_SUBACK = 9, - MQTT_MSG_TYPE_UNSUBSCRIBE = 10, - MQTT_MSG_TYPE_UNSUBACK = 11, - MQTT_MSG_TYPE_PINGREQ = 12, - MQTT_MSG_TYPE_PINGRESP = 13, - MQTT_MSG_TYPE_DISCONNECT = 14 + MQTT_MSG_TYPE_CONNECT = 1, + MQTT_MSG_TYPE_CONNACK = 2, + MQTT_MSG_TYPE_PUBLISH = 3, + MQTT_MSG_TYPE_PUBACK = 4, + MQTT_MSG_TYPE_PUBREC = 5, + MQTT_MSG_TYPE_PUBREL = 6, + MQTT_MSG_TYPE_PUBCOMP = 7, + MQTT_MSG_TYPE_SUBSCRIBE = 8, + MQTT_MSG_TYPE_SUBACK = 9, + MQTT_MSG_TYPE_UNSUBSCRIBE = 10, + MQTT_MSG_TYPE_UNSUBACK = 11, + MQTT_MSG_TYPE_PINGREQ = 12, + MQTT_MSG_TYPE_PINGRESP = 13, + MQTT_MSG_TYPE_DISCONNECT = 14 }; enum mqtt_connect_return_code { - CONNECTION_ACCEPTED = 0, - CONNECTION_REFUSE_PROTOCOL, - CONNECTION_REFUSE_ID_REJECTED, - CONNECTION_REFUSE_SERVER_UNAVAILABLE, - CONNECTION_REFUSE_BAD_USERNAME, - CONNECTION_REFUSE_NOT_AUTHORIZED + CONNECTION_ACCEPTED = 0, + CONNECTION_REFUSE_PROTOCOL, + CONNECTION_REFUSE_ID_REJECTED, + CONNECTION_REFUSE_SERVER_UNAVAILABLE, + CONNECTION_REFUSE_BAD_USERNAME, + CONNECTION_REFUSE_NOT_AUTHORIZED }; typedef struct mqtt_message { - uint8_t* data; - uint16_t length; + uint8_t* data; + uint32_t length; } mqtt_message_t; typedef struct mqtt_connection { - mqtt_message_t message; + mqtt_message_t message; - uint16_t message_id; - uint8_t* buffer; - uint16_t buffer_length; + uint16_t message_id; + uint8_t* buffer; + uint16_t buffer_length; } mqtt_connection_t; typedef struct mqtt_connect_info { - char* client_id; - char* username; - char* password; - char* will_topic; - char* will_message; - int keepalive; - int will_length; - int will_qos; - int will_retain; - int clean_session; + char* client_id; + char* username; + char* password; + char* will_topic; + char* will_message; + int keepalive; + int will_length; + int will_qos; + int will_retain; + int clean_session; } mqtt_connect_info_t; @@ -108,9 +108,9 @@ static inline int mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1 static inline int mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); } void mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length); -int mqtt_get_total_length(uint8_t* buffer, uint16_t length); -const char* mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length); -const char* mqtt_get_publish_data(uint8_t* buffer, uint16_t* length); +uint32_t mqtt_get_total_length(uint8_t* buffer, uint16_t length); +const char* mqtt_get_publish_topic(uint8_t* buffer, uint32_t* length); +const char* mqtt_get_publish_data(uint8_t* buffer, uint32_t* length); uint16_t mqtt_get_id(uint8_t* buffer, uint16_t length); mqtt_message_t* mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info); diff --git a/MicroPython_BUILD/components/espmqtt/lib/include/mqtt_outbox.h b/MicroPython_BUILD/components/espmqtt/lib/include/mqtt_outbox.h new file mode 100644 index 00000000..b94bd80f --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/include/mqtt_outbox.h @@ -0,0 +1,47 @@ +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ +#ifndef _MQTT_OUTOBX_H_ +#define _MQTT_OUTOBX_H_ +#include "platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct outbox_item { + char *buffer; + int len; + int msg_id; + int msg_type; + int tick; + int retry_count; + bool pending; + STAILQ_ENTRY(outbox_item) next; +} outbox_item_t; + +STAILQ_HEAD(outbox_list_t, outbox_item); + +typedef struct outbox_list_t * outbox_handle_t; +typedef outbox_item_t *outbox_item_handle_t; + +outbox_handle_t outbox_init(); +outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, uint8_t *data, int len, int msg_id, int msg_type, int tick); +outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox); +outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id); +esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type); +esp_err_t outbox_delete_msgid(outbox_handle_t outbox, int msg_id); +esp_err_t outbox_delete_msgtype(outbox_handle_t outbox, int msg_type); +esp_err_t outbox_delete_expired(outbox_handle_t outbox, int current_tick, int timeout); + +esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id); +int outbox_get_size(outbox_handle_t outbox); +esp_err_t outbox_cleanup(outbox_handle_t outbox, int max_size); +void outbox_destroy(outbox_handle_t outbox); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MicroPython_BUILD/components/espmqtt/lib/include/platform.h b/MicroPython_BUILD/components/espmqtt/lib/include/platform.h new file mode 100644 index 00000000..45eb3bf6 --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/include/platform.h @@ -0,0 +1,37 @@ +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ +#ifndef _PLATFORM_H__ +#define _PLATFORM_H__ + +//Support ESP32 +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "freertos/queue.h" +#include "freertos/event_groups.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" + +#include "rom/queue.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_system.h" + +char *platform_create_id_string(); +int platform_random(int max); +long long platform_tick_get_ms(); +void ms_to_timeval(int timeout_ms, struct timeval *tv); + +#define ESP_MEM_CHECK(TAG, a, action) if (!(a)) { \ + ESP_LOGE(TAG,"%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \ + action; \ + } + +#endif diff --git a/MicroPython_BUILD/components/espmqtt/lib/include/transport.h b/MicroPython_BUILD/components/espmqtt/lib/include/transport.h new file mode 100644 index 00000000..9dbd8809 --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/include/transport.h @@ -0,0 +1,242 @@ +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ +#ifndef _TRANSPORT_H_ +#define _TRANSPORT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct transport_list_t* transport_list_handle_t; +typedef struct transport_item_t* transport_handle_t; + +typedef int (*connect_func)(transport_handle_t t, const char *host, int port, int timeout_ms); +typedef int (*io_func)(transport_handle_t t, const char *buffer, int len, int timeout_ms); +typedef int (*io_read_func)(transport_handle_t t, char *buffer, int len, int timeout_ms); +typedef int (*trans_func)(transport_handle_t t); +typedef int (*poll_func)(transport_handle_t t, int timeout_ms); + +/** + * @brief Create transport list + * + * @return A handle can hold all transports + */ +transport_list_handle_t transport_list_init(); + +/** + * @brief Cleanup and free all transports, include itself, + * this function will invoke transport_destroy of every transport have added this the list + * + * @param[in] list The list + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t transport_list_destroy(transport_list_handle_t list); + +/** + * @brief Add a transport to the list, and define a scheme to indentify this transport in the list + * + * @param[in] list The list + * @param[in] t The Transport + * @param[in] scheme The scheme + * + * @return + * - ESP_OK + */ +esp_err_t transport_list_add(transport_list_handle_t list, transport_handle_t t, const char *scheme); + +/** + * @brief This function will remove all transport from the list, + * invoke transport_destroy of every transport have added this the list + * + * @param[in] list The list + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t transport_list_clean(transport_list_handle_t list); + +/** + * @brief Get the transport by scheme, which has been defined when calling function `transport_list_add` + * + * @param[in] list The list + * @param[in] tag The tag + * + * @return The transport handle + */ +transport_handle_t transport_list_get_transport(transport_list_handle_t list, const char *scheme); + +/** + * @brief Initialize a transport handle object + * + * @return The transport handle + */ +transport_handle_t transport_init(); + +/** + * @brief Cleanup and free memory the transport + * + * @param[in] t The transport handle + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t transport_destroy(transport_handle_t t); + +/** + * @brief Get default port number used by this transport + * + * @param[in] t The transport handle + * + * @return the port number + */ +int transport_get_default_port(transport_handle_t t); + +/** + * @brief Set default port number that can be used by this transport + * + * @param[in] t The transport handle + * @param[in] port The port number + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t transport_set_default_port(transport_handle_t t, int port); + +/** + * @brief Transport connection function, to make a connection to server + * + * @param t The transport handle + * @param[in] host Hostname + * @param[in] port Port + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - socket for will use by this transport + * - (-1) if there are any errors, should check errno + */ +int transport_connect(transport_handle_t t, const char *host, int port, int timeout_ms); + +/** + * @brief Transport read function + * + * @param t The transport handle + * @param buffer The buffer + * @param[in] len The length + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - Number of bytes was read + * - (-1) if there are any errors, should check errno + */ +int transport_read(transport_handle_t t, char *buffer, int len, int timeout_ms); + +/** + * @brief Poll the transport until readable or timeout + * + * @param[in] t The transport handle + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - 0 Timeout + * - (-1) If there are any errors, should check errno + * - other The transport can read + */ +int transport_poll_read(transport_handle_t t, int timeout_ms); + +/** + * @brief Transport write function + * + * @param t The transport handle + * @param buffer The buffer + * @param[in] len The length + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - Number of bytes was written + * - (-1) if there are any errors, should check errno + */ +int transport_write(transport_handle_t t, const char *buffer, int len, int timeout_ms); + +/** + * @brief Poll the transport until writeable or timeout + * + * @param[in] t The transport handle + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - 0 Timeout + * - (-1) If there are any errors, should check errno + * - other The transport can write + */ +int transport_poll_write(transport_handle_t t, int timeout_ms); + +/** + * @brief Transport close + * + * @param t The transport handle + * + * @return + * - 0 if ok + * - (-1) if there are any errors, should check errno + */ +int transport_close(transport_handle_t t); + +/** + * @brief Get user data context of this transport + * + * @param[in] t The transport handle + * + * @return The user data context + */ +void *transport_get_context_data(transport_handle_t t); + +/** + * @brief Set the user context data for this transport + * + * @param[in] t The transport handle + * @param data The user data context + * + * @return + * - ESP_OK + */ +esp_err_t transport_set_context_data(transport_handle_t t, void *data); + +/** + * @brief Set transport functions for the transport handle + * + * @param[in] t The transport handle + * @param[in] _connect The connect function pointer + * @param[in] _read The read function pointer + * @param[in] _write The write function pointer + * @param[in] _close The close function pointer + * @param[in] _poll_read The poll read function pointer + * @param[in] _poll_write The poll write function pointer + * @param[in] _destroy The destroy function pointer + * + * @return + * - ESP_OK + */ +esp_err_t transport_set_func(transport_handle_t t, + connect_func _connect, + io_read_func _read, + io_func _write, + trans_func _close, + poll_func _poll_read, + poll_func _poll_write, + trans_func _destroy); +#ifdef __cplusplus +} +#endif +#endif diff --git a/MicroPython_BUILD/components/espmqtt/lib/include/transport_ssl.h b/MicroPython_BUILD/components/espmqtt/lib/include/transport_ssl.h new file mode 100644 index 00000000..2469aa55 --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/include/transport_ssl.h @@ -0,0 +1,39 @@ +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ +#ifndef _TRANSPORT_SSL_H_ +#define _TRANSPORT_SSL_H_ + +#include "transport.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Create new SSL transport, the transport handle must be release transport_destroy callback + * + * @return the allocated transport_handle_t, or NULL if the handle can not be allocated + */ +transport_handle_t transport_ssl_init(); + +/** + * @brief Set SSL certificate data (as PEM format). + * Note that, this function stores the pointer to data, rather than making a copy. + * So we need to make sure to keep the data lifetime before cleanup the connection + * + * @param t ssl transport + * @param[in] data The pem data + * @param[in] len The length + */ +void transport_ssl_set_cert_data(transport_handle_t t, const char *data, int len); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/MicroPython_BUILD/components/espmqtt/lib/include/transport_tcp.h b/MicroPython_BUILD/components/espmqtt/lib/include/transport_tcp.h new file mode 100644 index 00000000..99160f30 --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/include/transport_tcp.h @@ -0,0 +1,27 @@ +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ +#ifndef _TRANSPORT_TCP_H_ +#define _TRANSPORT_TCP_H_ + +#include "transport.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create TCP transport, the transport handle must be release transport_destroy callback + * + * @return the allocated transport_handle_t, or NULL if the handle can not be allocated + */ +transport_handle_t transport_tcp_init(); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MicroPython_BUILD/components/espmqtt/lib/include/transport_ws.h b/MicroPython_BUILD/components/espmqtt/lib/include/transport_ws.h new file mode 100644 index 00000000..7393088d --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/include/transport_ws.h @@ -0,0 +1,46 @@ +/* + * This file is subject to the terms and conditions defined in + * file 'LICENSE', which is part of this source code package. + * Tuan PM + */ + +#ifndef _TRANSPORT_WS_H_ +#define _TRANSPORT_WS_H_ + +#include "transport.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WS_FIN 0x80 +#define WS_OPCODE_TEXT 0x01 +#define WS_OPCODE_BINARY 0x02 +#define WS_OPCODE_CLOSE 0x08 +#define WS_OPCODE_PING 0x09 +#define WS_OPCODE_PONG 0x0a +// Second byte +#define WS_MASK 0x80 +#define WS_SIZE16 126 +#define WS_SIZE64 127 +#define MAX_WEBSOCKET_HEADER_SIZE 10 +#define WS_RESPONSE_OK 101 + +/** + * @brief Create TCP transport + * + * @return + * - transport + * - NULL + */ +transport_handle_t transport_ws_init(transport_handle_t parent_handle); + +void transport_ws_set_path(transport_handle_t t, const char *path); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MicroPython_BUILD/components/espmqtt/mqtt_msg.c b/MicroPython_BUILD/components/espmqtt/lib/mqtt_msg.c similarity index 97% rename from MicroPython_BUILD/components/espmqtt/mqtt_msg.c rename to MicroPython_BUILD/components/espmqtt/lib/mqtt_msg.c index 54f187db..eb978472 100644 --- a/MicroPython_BUILD/components/espmqtt/mqtt_msg.c +++ b/MicroPython_BUILD/components/espmqtt/lib/mqtt_msg.c @@ -31,6 +31,8 @@ #include #include #include "mqtt_msg.h" +#include "mqtt_config.h" +#include "platform.h" #define MQTT_MAX_FIXED_HEADER_SIZE 3 @@ -47,7 +49,7 @@ struct __attribute((__packed__)) mqtt_connect_variable_header { uint8_t lengthMsb; uint8_t lengthLsb; -#if defined(CONFIG_MQTT_PROTOCOL_311) +#if defined(MQTT_PROTOCOL_311) uint8_t magic[4]; #else uint8_t magic[6]; @@ -75,8 +77,9 @@ static uint16_t append_message_id(mqtt_connection_t* connection, uint16_t messag { // If message_id is zero then we should assign one, otherwise // we'll use the one supplied by the caller - while (message_id == 0) - message_id = ++connection->message_id; + while (message_id == 0) { + message_id = platform_random(65535); + } if (connection->message.length + 2 > connection->buffer_length) return 0; @@ -130,10 +133,10 @@ void mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buff connection->buffer_length = buffer_length; } -int mqtt_get_total_length(uint8_t* buffer, uint16_t length) +uint32_t mqtt_get_total_length(uint8_t* buffer, uint16_t length) { int i; - int totlen = 0; + uint32_t totlen = 0; for (i = 1; i < length; ++i) { @@ -145,11 +148,11 @@ int mqtt_get_total_length(uint8_t* buffer, uint16_t length) } } totlen += i; - + return totlen; } -const char* mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length) +const char* mqtt_get_publish_topic(uint8_t* buffer, uint32_t* length) { int i; int totlen = 0; @@ -176,9 +179,9 @@ const char* mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length) *length = topiclen; return (const char*)(buffer + i); -} +} -const char* mqtt_get_publish_data(uint8_t* buffer, uint16_t* length) +const char* mqtt_get_publish_data(uint8_t* buffer, uint32_t* length) { int i; int totlen = 0; diff --git a/MicroPython_BUILD/components/espmqtt/lib/mqtt_outbox.c b/MicroPython_BUILD/components/espmqtt/lib/mqtt_outbox.c new file mode 100644 index 00000000..8175475f --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/mqtt_outbox.c @@ -0,0 +1,151 @@ +#include "mqtt_outbox.h" +#include +#include +#include "rom/queue.h" +#include "esp_log.h" + +static const char *TAG = "OUTBOX"; + +outbox_handle_t outbox_init() +{ + outbox_handle_t outbox = calloc(1, sizeof(struct outbox_list_t)); + ESP_MEM_CHECK(TAG, outbox, return NULL); + STAILQ_INIT(outbox); + return outbox; +} + +outbox_item_handle_t outbox_enqueue(outbox_handle_t outbox, uint8_t *data, int len, int msg_id, int msg_type, int tick) +{ + outbox_item_handle_t item = calloc(1, sizeof(outbox_item_t)); + ESP_MEM_CHECK(TAG, item, return NULL); + item->msg_id = msg_id; + item->msg_type = msg_type; + item->tick = tick; + item->len = len; + item->buffer = malloc(len); + ESP_MEM_CHECK(TAG, item->buffer, { + free(item); + return NULL; + }); + memcpy(item->buffer, data, len); + STAILQ_INSERT_TAIL(outbox, item, next); + ESP_LOGD(TAG, "ENQUEUE msgid=%d, msg_type=%d, len=%d, size=%d", msg_id, msg_type, len, outbox_get_size(outbox)); + return item; +} + +outbox_item_handle_t outbox_get(outbox_handle_t outbox, int msg_id) +{ + outbox_item_handle_t item; + STAILQ_FOREACH(item, outbox, next) { + if (item->msg_id == msg_id) { + return item; + } + } + return NULL; +} + +outbox_item_handle_t outbox_dequeue(outbox_handle_t outbox) +{ + outbox_item_handle_t item; + STAILQ_FOREACH(item, outbox, next) { + if (!item->pending) { + return item; + } + } + return NULL; +} +esp_err_t outbox_delete(outbox_handle_t outbox, int msg_id, int msg_type) +{ + outbox_item_handle_t item, tmp; + STAILQ_FOREACH_SAFE(item, outbox, next, tmp) { + if (item->msg_id == msg_id && item->msg_type == msg_type) { + STAILQ_REMOVE(outbox, item, outbox_item, next); + free(item->buffer); + free(item); + ESP_LOGD(TAG, "DELETED msgid=%d, msg_type=%d, remain size=%d", msg_id, msg_type, outbox_get_size(outbox)); + return ESP_OK; + } + + } + return ESP_FAIL; +} +esp_err_t outbox_delete_msgid(outbox_handle_t outbox, int msg_id) +{ + outbox_item_handle_t item, tmp; + STAILQ_FOREACH_SAFE(item, outbox, next, tmp) { + if (item->msg_id == msg_id) { + STAILQ_REMOVE(outbox, item, outbox_item, next); + free(item->buffer); + free(item); + } + + } + return ESP_OK; +} +esp_err_t outbox_set_pending(outbox_handle_t outbox, int msg_id) +{ + outbox_item_handle_t item = outbox_get(outbox, msg_id); + if (item) { + item->pending = true; + return ESP_OK; + } + return ESP_FAIL; +} + +esp_err_t outbox_delete_msgtype(outbox_handle_t outbox, int msg_type) +{ + outbox_item_handle_t item, tmp; + STAILQ_FOREACH_SAFE(item, outbox, next, tmp) { + if (item->msg_type == msg_type) { + STAILQ_REMOVE(outbox, item, outbox_item, next); + free(item->buffer); + free(item); + } + + } + return ESP_OK; +} + +esp_err_t outbox_delete_expired(outbox_handle_t outbox, int current_tick, int timeout) +{ + outbox_item_handle_t item, tmp; + STAILQ_FOREACH_SAFE(item, outbox, next, tmp) { + if (current_tick - item->tick > timeout) { + STAILQ_REMOVE(outbox, item, outbox_item, next); + free(item->buffer); + free(item); + } + + } + return ESP_OK; +} + +int outbox_get_size(outbox_handle_t outbox) +{ + int siz = 0; + outbox_item_handle_t item; + STAILQ_FOREACH(item, outbox, next) { + siz += item->len; + } + return siz; +} + +esp_err_t outbox_cleanup(outbox_handle_t outbox, int max_size) +{ + while(outbox_get_size(outbox) > max_size) { + outbox_item_handle_t item = outbox_dequeue(outbox); + if (item == NULL) { + return ESP_FAIL; + } + STAILQ_REMOVE(outbox, item, outbox_item, next); + free(item->buffer); + free(item); + } + return ESP_OK; +} + +void outbox_destroy(outbox_handle_t outbox) +{ + outbox_cleanup(outbox, 0); + free(outbox); +} diff --git a/MicroPython_BUILD/components/espmqtt/lib/platform.c b/MicroPython_BUILD/components/espmqtt/lib/platform.c new file mode 100644 index 00000000..73247f0b --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/platform.c @@ -0,0 +1,36 @@ +#include "platform.h" + +#include "esp_system.h" +#include + +#define MAX_ID_STRING (32) + +char *platform_create_id_string() +{ + uint8_t mac[6]; + char *id_string = calloc(1, MAX_ID_STRING); + ESP_MEM_CHECK("MQTT_CLIENT", id_string, return NULL); + esp_read_mac(mac, ESP_MAC_WIFI_STA); + sprintf(id_string, "ESP32_%02x%02X%02X", mac[3], mac[4], mac[5]); + return id_string; +} + +int platform_random(int max) +{ + return esp_random()%max; +} + +long long platform_tick_get_ms() +{ + struct timeval te; + gettimeofday(&te, NULL); // get current time + long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds + // printf("milliseconds: %lld\n", milliseconds); + return milliseconds; +} + +void ms_to_timeval(int timeout_ms, struct timeval *tv) +{ + tv->tv_sec = timeout_ms / 1000; + tv->tv_usec = (timeout_ms - (tv->tv_sec * 1000)) * 1000; +} diff --git a/MicroPython_BUILD/components/espmqtt/lib/transport.c b/MicroPython_BUILD/components/espmqtt/lib/transport.c new file mode 100644 index 00000000..04f3939e --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/transport.c @@ -0,0 +1,218 @@ +#include +#include + +#include "rom/queue.h" +#include "esp_log.h" + +#include "transport.h" +#include "platform.h" + + +static const char *TAG = "TRANSPORT"; + +/** + * Transport layer structure, which will provide functions, basic properties for transport types + */ +struct transport_item_t { + int port; + int socket; /*!< Socket to use in this transport */ + char *scheme; /*!< Tag name */ + void *context; /*!< Context data */ + void *data; /*!< Additional transport data */ + connect_func _connect; /*!< Connect function of this transport */ + io_read_func _read; /*!< Read */ + io_func _write; /*!< Write */ + trans_func _close; /*!< Close */ + poll_func _poll_read; /*!< Poll and read */ + poll_func _poll_write; /*!< Poll and write */ + trans_func _destroy; /*!< Destroy and free transport */ + STAILQ_ENTRY(transport_item_t) next; +}; + + +/** + * This list will hold all transport available + */ +STAILQ_HEAD(transport_list_t, transport_item_t); + + +transport_list_handle_t transport_list_init() +{ + transport_list_handle_t list = calloc(1, sizeof(struct transport_list_t)); + ESP_MEM_CHECK(TAG, list, return NULL); + STAILQ_INIT(list); + return list; +} + +esp_err_t transport_list_add(transport_list_handle_t list, transport_handle_t t, const char *scheme) +{ + if (list == NULL || t == NULL) { + return ESP_ERR_INVALID_ARG; + } + t->scheme = calloc(1, strlen(scheme) + 1); + ESP_MEM_CHECK(TAG, t->scheme, return ESP_ERR_NO_MEM); + strcpy(t->scheme, scheme); + STAILQ_INSERT_TAIL(list, t, next); + return ESP_OK; +} + +transport_handle_t transport_list_get_transport(transport_list_handle_t list, const char *scheme) +{ + if (!list) { + return NULL; + } + if (scheme == NULL) { + return STAILQ_FIRST(list); + } + transport_handle_t item; + STAILQ_FOREACH(item, list, next) { + if (strcasecmp(item->scheme, scheme) == 0) { + return item; + } + } + return NULL; +} + +esp_err_t transport_list_destroy(transport_list_handle_t list) +{ + transport_list_clean(list); + free(list); + return ESP_OK; +} + +esp_err_t transport_list_clean(transport_list_handle_t list) +{ + transport_handle_t item = STAILQ_FIRST(list); + transport_handle_t tmp; + while (item != NULL) { + tmp = STAILQ_NEXT(item, next); + if (item->_destroy) { + item->_destroy(item); + } + transport_destroy(item); + item = tmp; + } + STAILQ_INIT(list); + return ESP_OK; +} + +transport_handle_t transport_init() +{ + transport_handle_t t = calloc(1, sizeof(struct transport_item_t)); + ESP_MEM_CHECK(TAG, t, return NULL); + return t; +} + +esp_err_t transport_destroy(transport_handle_t t) +{ + if (t->scheme) { + free(t->scheme); + } + free(t); + return ESP_OK; +} + +int transport_connect(transport_handle_t t, const char *host, int port, int timeout_ms) +{ + int ret = -1; + if (t && t->_connect) { + return t->_connect(t, host, port, timeout_ms); + } + return ret; +} + +int transport_read(transport_handle_t t, char *buffer, int len, int timeout_ms) +{ + if (t && t->_read) { + return t->_read(t, buffer, len, timeout_ms); + } + return -1; +} + +int transport_write(transport_handle_t t, const char *buffer, int len, int timeout_ms) +{ + if (t && t->_write) { + return t->_write(t, buffer, len, timeout_ms); + } + return -1; +} + +int transport_poll_read(transport_handle_t t, int timeout_ms) +{ + if (t && t->_poll_read) { + return t->_poll_read(t, timeout_ms); + } + return -1; +} + +int transport_poll_write(transport_handle_t t, int timeout_ms) +{ + if (t && t->_poll_write) { + return t->_poll_write(t, timeout_ms); + } + return -1; +} + +int transport_close(transport_handle_t t) +{ + if (t && t->_close) { + return t->_close(t); + } + return 0; +} + +void *transport_get_context_data(transport_handle_t t) +{ + if (t) { + return t->data; + } + return NULL; +} + +esp_err_t transport_set_context_data(transport_handle_t t, void *data) +{ + if (t) { + t->data = data; + return ESP_OK; + } + return ESP_FAIL; +} + +esp_err_t transport_set_func(transport_handle_t t, + connect_func _connect, + io_read_func _read, + io_func _write, + trans_func _close, + poll_func _poll_read, + poll_func _poll_write, + trans_func _destroy) +{ + if (t == NULL) { + return ESP_FAIL; + } + t->_connect = _connect; + t->_read = _read; + t->_write = _write; + t->_close = _close; + t->_poll_read = _poll_read; + t->_poll_write = _poll_write; + t->_destroy = _destroy; + return ESP_OK; +} + +int transport_get_default_port(transport_handle_t t) +{ + if (t == NULL) { + return -1; + } + return t->port; +} + +esp_err_t transport_set_default_port(transport_handle_t t, int port) +{ + if (t == NULL) { + return ESP_FAIL; + } + t->port = port; + return ESP_OK; +} diff --git a/MicroPython_BUILD/components/espmqtt/lib/transport_ssl.c b/MicroPython_BUILD/components/espmqtt/lib/transport_ssl.c new file mode 100644 index 00000000..da0a1794 --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/transport_ssl.c @@ -0,0 +1,253 @@ +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" + +#include "mbedtls/platform.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/esp_debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + + +#include "esp_log.h" +#include "esp_system.h" +#include "platform.h" + +#include "transport.h" +#include "transport_ssl.h" + +static const char *TAG = "TRANS_SSL"; +/** + * mbedtls specific transport data + */ +typedef struct { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ctx; + mbedtls_x509_crt cacert; + mbedtls_ssl_config conf; + mbedtls_net_context client_fd; + void *cert_pem_data; + int cert_pem_len; + bool ssl_initialized; + bool verify_server; +} transport_ssl_t; + +static int ssl_close(transport_handle_t t); + +static int ssl_connect(transport_handle_t t, const char *host, int port, int timeout_ms) +{ + int ret = -1, flags; + struct timeval tv; + transport_ssl_t *ssl = transport_get_context_data(t); + + if (!ssl) { + return -1; + } + ssl->ssl_initialized = true; + mbedtls_ssl_init(&ssl->ctx); + mbedtls_ctr_drbg_init(&ssl->ctr_drbg); + mbedtls_ssl_config_init(&ssl->conf); + mbedtls_entropy_init(&ssl->entropy); + + if ((ret = mbedtls_ssl_config_defaults(&ssl->conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); + goto exit; + } + + if ((ret = mbedtls_ctr_drbg_seed(&ssl->ctr_drbg, mbedtls_entropy_func, &ssl->entropy, NULL, 0)) != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); + goto exit; + } + + if (ssl->cert_pem_data) { + mbedtls_x509_crt_init(&ssl->cacert); + ssl->verify_server = true; + if ((ret = mbedtls_x509_crt_parse(&ssl->cacert, ssl->cert_pem_data, ssl->cert_pem_len + 1)) < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\nDATA=%s,len=%d", -ret, (char*)ssl->cert_pem_data, ssl->cert_pem_len); + goto exit; + } + mbedtls_ssl_conf_ca_chain(&ssl->conf, &ssl->cacert, NULL); + mbedtls_ssl_conf_authmode(&ssl->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + + if ((ret = mbedtls_ssl_set_hostname(&ssl->ctx, host)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); + goto exit; + } + } else { + mbedtls_ssl_conf_authmode(&ssl->conf, MBEDTLS_SSL_VERIFY_NONE); + } + + + mbedtls_ssl_conf_rng(&ssl->conf, mbedtls_ctr_drbg_random, &ssl->ctr_drbg); + +#ifdef CONFIG_MBEDTLS_DEBUG + mbedtls_esp_enable_debug_log(&ssl->conf, 4); +#endif + + if ((ret = mbedtls_ssl_setup(&ssl->ctx, &ssl->conf)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); + goto exit; + } + + mbedtls_net_init(&ssl->client_fd); + + ms_to_timeval(timeout_ms, &tv); + + setsockopt(ssl->client_fd.fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + ESP_LOGD(TAG, "Connect to %s:%d", host, port); + char port_str[8] = {0}; + sprintf(port_str, "%d", port); + if ((ret = mbedtls_net_connect(&ssl->client_fd, host, port_str, MBEDTLS_NET_PROTO_TCP)) != 0) { + ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret); + goto exit; + } + + mbedtls_ssl_set_bio(&ssl->ctx, &ssl->client_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + + if((ret = mbedtls_ssl_set_hostname(&ssl->ctx, host)) != 0) { + ESP_LOGE(TAG, " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); + goto exit; + } + + ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); + + while ((ret = mbedtls_ssl_handshake(&ssl->ctx)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); + goto exit; + } + } + + ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); + + if ((flags = mbedtls_ssl_get_verify_result(&ssl->ctx)) != 0) { + /* In real life, we probably want to close connection if ret != 0 */ + ESP_LOGW(TAG, "Failed to verify peer certificate!"); + if (ssl->cert_pem_data) { + goto exit; + } + } else { + ESP_LOGD(TAG, "Certificate verified."); + } + + ESP_LOGD(TAG, "Cipher suite is %s", mbedtls_ssl_get_ciphersuite(&ssl->ctx)); + return ret; +exit: + ssl_close(t); + return ret; +} + +static int ssl_poll_read(transport_handle_t t, int timeout_ms) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + fd_set readset; + FD_ZERO(&readset); + FD_SET(ssl->client_fd.fd, &readset); + struct timeval timeout; + ms_to_timeval(timeout_ms, &timeout); + + return select(ssl->client_fd.fd + 1, &readset, NULL, NULL, &timeout); +} + +static int ssl_poll_write(transport_handle_t t, int timeout_ms) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + fd_set writeset; + FD_ZERO(&writeset); + FD_SET(ssl->client_fd.fd, &writeset); + struct timeval timeout; + ms_to_timeval(timeout_ms, &timeout); + return select(ssl->client_fd.fd + 1, NULL, &writeset, NULL, &timeout); +} + +static int ssl_write(transport_handle_t t, const char *buffer, int len, int timeout_ms) +{ + int poll, ret; + transport_ssl_t *ssl = transport_get_context_data(t); + + if ((poll = transport_poll_write(t, timeout_ms)) <= 0) { + ESP_LOGW(TAG, "Poll timeout or error, errno=%s, fd=%d, timeout_ms=%d", strerror(errno), ssl->client_fd.fd, timeout_ms); + return poll; + } + ret = mbedtls_ssl_write(&ssl->ctx, (const unsigned char *) buffer, len); + if (ret <= 0) { + ESP_LOGE(TAG, "mbedtls_ssl_write error, errno=%s", strerror(errno)); + } + return ret; +} + +static int ssl_read(transport_handle_t t, char *buffer, int len, int timeout_ms) +{ + int ret; + transport_ssl_t *ssl = transport_get_context_data(t); + ret = mbedtls_ssl_read(&ssl->ctx, (unsigned char *)buffer, len); + if (ret == 0) { + return -1; + } + return ret; +} + +static int ssl_close(transport_handle_t t) +{ + int ret = -1; + transport_ssl_t *ssl = transport_get_context_data(t); + if (ssl->ssl_initialized) { + ESP_LOGD(TAG, "Cleanup mbedtls"); + mbedtls_ssl_close_notify(&ssl->ctx); + mbedtls_ssl_session_reset(&ssl->ctx); + mbedtls_net_free(&ssl->client_fd); + mbedtls_ssl_config_free(&ssl->conf); + if (ssl->verify_server) { + mbedtls_x509_crt_free(&ssl->cacert); + } + mbedtls_ctr_drbg_free(&ssl->ctr_drbg); + mbedtls_entropy_free(&ssl->entropy); + mbedtls_ssl_free(&ssl->ctx); + ssl->ssl_initialized = false; + ssl->verify_server = false; + } + return ret; +} + +static int ssl_destroy(transport_handle_t t) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + transport_close(t); + free(ssl); + return 0; +} + +void transport_ssl_set_cert_data(transport_handle_t t, const char *data, int len) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + if (t && ssl) { + ssl->cert_pem_data = (void *)data; + ssl->cert_pem_len = len; + } +} + +transport_handle_t transport_ssl_init() +{ + transport_handle_t t = transport_init(); + transport_ssl_t *ssl = calloc(1, sizeof(transport_ssl_t)); + ESP_MEM_CHECK(TAG, ssl, return NULL); + mbedtls_net_init(&ssl->client_fd); + transport_set_context_data(t, ssl); + transport_set_func(t, ssl_connect, ssl_read, ssl_write, ssl_close, ssl_poll_read, ssl_poll_write, ssl_destroy); + return t; +} + diff --git a/MicroPython_BUILD/components/espmqtt/lib/transport_tcp.c b/MicroPython_BUILD/components/espmqtt/lib/transport_tcp.c new file mode 100644 index 00000000..e98ce939 --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/transport_tcp.c @@ -0,0 +1,152 @@ +#include +#include + +#include "lwip/sockets.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" + +#include "esp_log.h" +#include "esp_system.h" +#include "esp_err.h" + +#include "platform.h" +#include "transport.h" + +static const char *TAG = "TRANS_TCP"; + +typedef struct { + int sock; +} transport_tcp_t; + +static int resolve_dns(const char *host, struct sockaddr_in *ip) { + + struct hostent *he; + struct in_addr **addr_list; + he = gethostbyname(host); + if (he == NULL) { + return ESP_FAIL; + } + addr_list = (struct in_addr **)he->h_addr_list; + if (addr_list[0] == NULL) { + return ESP_FAIL; + } + ip->sin_family = AF_INET; + memcpy(&ip->sin_addr, addr_list[0], sizeof(ip->sin_addr)); + return ESP_OK; +} + +static int tcp_connect(transport_handle_t t, const char *host, int port, int timeout_ms) +{ + struct sockaddr_in remote_ip; + struct timeval tv; + transport_tcp_t *tcp = transport_get_context_data(t); + + bzero(&remote_ip, sizeof(struct sockaddr_in)); + + //if stream_host is not ip address, resolve it AF_INET,servername,&serveraddr.sin_addr + if (inet_pton(AF_INET, host, &remote_ip.sin_addr) != 1) { + if (resolve_dns(host, &remote_ip) < 0) { + return -1; + } + } + + tcp->sock = socket(PF_INET, SOCK_STREAM, 0); + + if (tcp->sock < 0) { + ESP_LOGE(TAG, "Error create socket"); + return -1; + } + + remote_ip.sin_family = AF_INET; + remote_ip.sin_port = htons(port); + + ms_to_timeval(timeout_ms, &tv); + + setsockopt(tcp->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + ESP_LOGD(TAG, "[sock=%d],connecting to server IP:%s,Port:%d...", + tcp->sock, ipaddr_ntoa((const ip_addr_t*)&remote_ip.sin_addr.s_addr), port); + if (connect(tcp->sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) != 0) { + close(tcp->sock); + tcp->sock = -1; + return -1; + } + return tcp->sock; +} + +static int tcp_write(transport_handle_t t, const char *buffer, int len, int timeout_ms) +{ + int poll; + transport_tcp_t *tcp = transport_get_context_data(t); + if ((poll = transport_poll_write(t, timeout_ms)) <= 0) { + return poll; + } + return write(tcp->sock, buffer, len); +} + +static int tcp_read(transport_handle_t t, char *buffer, int len, int timeout_ms) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + int poll = -1; + if ((poll = transport_poll_read(t, timeout_ms)) <= 0) { + return poll; + } + int read_len = read(tcp->sock, buffer, len); + if (read_len == 0) { + return -1; + } + return read_len; +} + +static int tcp_poll_read(transport_handle_t t, int timeout_ms) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + fd_set readset; + FD_ZERO(&readset); + FD_SET(tcp->sock, &readset); + struct timeval timeout; + ms_to_timeval(timeout_ms, &timeout); + return select(tcp->sock + 1, &readset, NULL, NULL, &timeout); +} + +static int tcp_poll_write(transport_handle_t t, int timeout_ms) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + fd_set writeset; + FD_ZERO(&writeset); + FD_SET(tcp->sock, &writeset); + struct timeval timeout; + ms_to_timeval(timeout_ms, &timeout); + return select(tcp->sock + 1, NULL, &writeset, NULL, &timeout); +} + +static int tcp_close(transport_handle_t t) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + int ret = -1; + if (tcp->sock >= 0) { + ret = close(tcp->sock); + tcp->sock = -1; + } + return ret; +} + +static esp_err_t tcp_destroy(transport_handle_t t) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + transport_close(t); + free(tcp); + return 0; +} + +transport_handle_t transport_tcp_init() +{ + transport_handle_t t = transport_init(); + transport_tcp_t *tcp = calloc(1, sizeof(transport_tcp_t)); + ESP_MEM_CHECK(TAG, tcp, return NULL); + tcp->sock = -1; + transport_set_func(t, tcp_connect, tcp_read, tcp_write, tcp_close, tcp_poll_read, tcp_poll_write, tcp_destroy); + transport_set_context_data(t, tcp); + + return t; +} diff --git a/MicroPython_BUILD/components/espmqtt/lib/transport_ws.c b/MicroPython_BUILD/components/espmqtt/lib/transport_ws.c new file mode 100644 index 00000000..df0ae1b7 --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/lib/transport_ws.c @@ -0,0 +1,251 @@ +#include +#include +#include + +#include "platform.h" +#include "transport.h" +#include "transport_tcp.h" +#include "transport_ws.h" +#include "mbedtls/base64.h" +#include "mbedtls/sha1.h" + +static const char *TAG = "TRANSPORT_WS"; + +#define DEFAULT_WS_BUFFER (1024) + +typedef struct { + char *path; + char *buffer; + transport_handle_t parent; +} transport_ws_t; + +static char *trimwhitespace(const char *str) +{ + char *end; + + // Trim leading space + while (isspace((unsigned char)*str)) str++; + + if (*str == 0) { + return (char *)str; + } + + // Trim trailing space + end = (char *)(str + strlen(str) - 1); + while (end > str && isspace((unsigned char)*end)) end--; + + // Write new null terminator + *(end + 1) = 0; + + return (char *)str; +} + + +static char *get_http_header(const char *buffer, const char *key) +{ + char *found = strstr(buffer, key); + if (found) { + found += strlen(key); + char *found_end = strstr(found, "\r\n"); + if (found_end) { + found_end[0] = 0;//terminal string + + return trimwhitespace(found); + } + } + return NULL; +} + +static int ws_connect(transport_handle_t t, const char *host, int port, int timeout_ms) +{ + transport_ws_t *ws = transport_get_context_data(t); + if (transport_connect(ws->parent, host, port, timeout_ms) < 0) { + ESP_LOGE(TAG, "Error connect to ther server"); + } + unsigned char random_key[16] = { 0 }, client_key[32] = {0}; + int i; + for (i = 0; i < sizeof(random_key); i++) { + random_key[i] = rand() & 0xFF; + } + size_t outlen = 0; + mbedtls_base64_encode(client_key, 32, &outlen, random_key, 16); + int len = snprintf(ws->buffer, DEFAULT_WS_BUFFER, + "GET %s HTTP/1.1\r\n" + "Connection: Upgrade\r\n" + "Host: %s:%d\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Protocol: mqtt\r\n" + "Sec-WebSocket-Key: %s\r\n" + "User-Agent: ESP32 MQTT Client\r\n\r\n", + ws->path, + host, port, + client_key); + ESP_LOGD(TAG, "Write upgrate request\r\n%s", ws->buffer); + if (transport_write(ws->parent, ws->buffer, len, timeout_ms) <= 0) { + ESP_LOGE(TAG, "Error write Upgrade header %s", ws->buffer); + return -1; + } + if ((len = transport_read(ws->parent, ws->buffer, DEFAULT_WS_BUFFER, timeout_ms)) <= 0) { + ESP_LOGE(TAG, "Error read response for Upgrade header %s", ws->buffer); + return -1; + } + char *server_key = get_http_header(ws->buffer, "Sec-WebSocket-Accept:"); + if (server_key == NULL) { + ESP_LOGE(TAG, "Sec-WebSocket-Accept not found"); + return -1; + } + + unsigned char client_key_b64[64], valid_client_key[20], accept_key[32] = {0}; + int key_len = sprintf((char*)client_key_b64, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", (char*)client_key); + mbedtls_sha1(client_key_b64, (size_t)key_len, valid_client_key); + mbedtls_base64_encode(accept_key, 32, &outlen, valid_client_key, 20); + accept_key[outlen] = 0; + ESP_LOGD(TAG, "server key=%s, send_key=%s, accept_key=%s", (char *)server_key, (char*)client_key, accept_key); + if (strcmp((char*)accept_key, (char*)server_key) != 0) { + ESP_LOGE(TAG, "Invalid websocket key"); + return -1; + } + return 0; +} + +static int ws_write(transport_handle_t t, const char *buff, int len, int timeout_ms) +{ + transport_ws_t *ws = transport_get_context_data(t); + char ws_header[MAX_WEBSOCKET_HEADER_SIZE]; + char *mask; + int header_len = 0, i; + char *buffer = (char *)buff; + int poll_write; + if ((poll_write = transport_poll_write(ws->parent, timeout_ms)) <= 0) { + return poll_write; + } + + ws_header[header_len++] = WS_OPCODE_BINARY | WS_FIN; + + // NOTE: no support for > 16-bit sized messages + if (len > 125) { + ws_header[header_len++] = WS_SIZE16 | WS_MASK; + ws_header[header_len++] = (uint8_t)(len >> 8); + ws_header[header_len++] = (uint8_t)(len & 0xFF); + } else { + ws_header[header_len++] = (uint8_t)(len | WS_MASK); + } + mask = &ws_header[header_len]; + ws_header[header_len++] = rand() & 0xFF; + ws_header[header_len++] = rand() & 0xFF; + ws_header[header_len++] = rand() & 0xFF; + ws_header[header_len++] = rand() & 0xFF; + + for (i = 0; i < len; ++i) { + buffer[i] = (buffer[i] ^ mask[i % 4]); + } + if (transport_write(ws->parent, ws_header, header_len, timeout_ms) != header_len) { + ESP_LOGE(TAG, "Error write header"); + return -1; + } + return transport_write(ws->parent, buffer, len, timeout_ms); +} + +static int ws_read(transport_handle_t t, char *buffer, int len, int timeout_ms) +{ + transport_ws_t *ws = transport_get_context_data(t); + int payload_len; + char *data_ptr = buffer, opcode, mask, *mask_key = NULL; + int rlen; + int poll_read; + if ((poll_read = transport_poll_read(ws->parent, timeout_ms)) <= 0) { + return poll_read; + } + if ((rlen = transport_read(ws->parent, buffer, len, timeout_ms)) <= 0) { + ESP_LOGE(TAG, "Error read data"); + return rlen; + } + + opcode = (*data_ptr & 0x0F); + data_ptr ++; + mask = ((*data_ptr >> 7) & 0x01); + payload_len = (*data_ptr & 0x7F); + data_ptr++; + ESP_LOGD(TAG, "Opcode: %d, mask: %d, len: %d\r\n", opcode, mask, payload_len); + if (payload_len == 126) { + // headerLen += 2; + payload_len = data_ptr[0] << 8 | data_ptr[1]; + data_ptr += 2; + } else if (payload_len == 127) { + // headerLen += 8; + + if (data_ptr[0] != 0 || data_ptr[1] != 0 || data_ptr[2] != 0 || data_ptr[3] != 0) { + // really too big! + payload_len = 0xFFFFFFFF; + } else { + payload_len = data_ptr[4] << 24 | data_ptr[5] << 16 | data_ptr[6] << 8 | data_ptr[7]; + } + data_ptr += 8; + } + + if (mask) { + mask_key = data_ptr; + data_ptr += 4; + for (int i = 0; i < payload_len; i++) { + buffer[i] = (data_ptr[i] ^ mask_key[i % 4]); + } + } else { + memmove(buffer, data_ptr, payload_len); + } + return payload_len; +} + +static int ws_poll_read(transport_handle_t t, int timeout_ms) +{ + transport_ws_t *ws = transport_get_context_data(t); + return transport_poll_read(ws->parent, timeout_ms); +} + +static int ws_poll_write(transport_handle_t t, int timeout_ms) +{ + transport_ws_t *ws = transport_get_context_data(t); + return transport_poll_write(ws->parent, timeout_ms);; +} + +static int ws_close(transport_handle_t t) +{ + transport_ws_t *ws = transport_get_context_data(t); + return transport_close(ws->parent); +} + +static esp_err_t ws_destroy(transport_handle_t t) +{ + transport_ws_t *ws = transport_get_context_data(t); + free(ws->buffer); + free(ws->path); + free(ws); + return 0; +} +void transport_ws_set_path(transport_handle_t t, const char *path) +{ + transport_ws_t *ws = transport_get_context_data(t); + ws->path = realloc(ws->path, strlen(path) + 1); + strcpy(ws->path, path); +} +transport_handle_t transport_ws_init(transport_handle_t parent_handle) +{ + transport_handle_t t = transport_init(); + transport_ws_t *ws = calloc(1, sizeof(transport_ws_t)); + ESP_MEM_CHECK(TAG, ws, return NULL); + ws->parent = parent_handle; + + ws->path = strdup("/"); + ESP_MEM_CHECK(TAG, ws->path, return NULL); + ws->buffer = malloc(DEFAULT_WS_BUFFER); + ESP_MEM_CHECK(TAG, ws->buffer, { + free(ws->path); + free(ws); + return NULL; + }); + + transport_set_func(t, ws_connect, ws_read, ws_write, ws_close, ws_poll_read, ws_poll_write, ws_destroy); + transport_set_context_data(t, ws); + return t; +} + diff --git a/MicroPython_BUILD/components/espmqtt/mqtt.c b/MicroPython_BUILD/components/espmqtt/mqtt.c deleted file mode 100644 index fa8cb13a..00000000 --- a/MicroPython_BUILD/components/espmqtt/mqtt.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Boris Lovosevic (https://github.com/loboris) - * - * 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. - */ - -/* - * Mqtt Module using MQTT task. - * Based on ESP32 MQTT Library by Tuan PM, https://github.com/tuanpmt/espmqtt - * Adapted for MicroPython by Boris Lovosevic, https://github.com/loboris - * - */ - -#include "sdkconfig.h" - -#ifdef CONFIG_MICROPY_USE_MQTT - -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "esp_log.h" - -#include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" -#include "ringbuf.h" -#include "mqtt.h" - -#include "esp_wifi_types.h" -#include "tcpip_adapter.h" -#include "libs/libGSM.h" - -const char *MQTT_TAG = "[Mqtt client]"; -static char *subs_last_topic = NULL; -static char *unsubs_last_topic = NULL; - -//---------------------------------------------------------------- -static int resolve_dns(const char *host, struct sockaddr_in *ip) { - struct hostent *he; - struct in_addr **addr_list; - he = gethostbyname(host); - if (he == NULL) return 0; - addr_list = (struct in_addr **)he->h_addr_list; - if (addr_list[0] == NULL) return 0; - ip->sin_family = AF_INET; - memcpy(&ip->sin_addr, addr_list[0], sizeof(ip->sin_addr)); - return 1; -} - -//----------------------------------------- -static void mqtt_queue(mqtt_client *client) -{ - int msg_len; - while (rb_available(&client->send_rb) < client->mqtt_state.outbound_message->length) { - xQueueReceive(client->xSendingQueue, &msg_len, 1000 / portTICK_RATE_MS); - rb_read(&client->send_rb, client->mqtt_state.out_buffer, msg_len); - } - rb_write(&client->send_rb, - client->mqtt_state.outbound_message->data, - client->mqtt_state.outbound_message->length); - xQueueSend(client->xSendingQueue, &client->mqtt_state.outbound_message->length, 0); -} - -//--------------------------------------------- -static bool client_connect(mqtt_client *client) -{ - struct sockaddr_in remote_ip; - - client->status = MQTT_STATUS_DISCONNECTED; - while (1) { - bzero(&remote_ip, sizeof(struct sockaddr_in)); - remote_ip.sin_family = AF_INET; - remote_ip.sin_port = htons(client->settings->port); - - //if host is not ip address, resolve it - if (inet_aton( client->settings->host, &(remote_ip.sin_addr)) == 0) { - ESP_LOGI(MQTT_TAG, "Resolve dns for domain: %s", client->settings->host); - - if (!resolve_dns(client->settings->host, &remote_ip)) { - ESP_LOGE(MQTT_TAG, "Resolve dns for domain: %s failed", client->settings->host); - return false; - } - } - - if (client->settings->use_ssl) { - client->ctx = NULL; - client->ssl = NULL; - - client->ctx = SSL_CTX_new(TLSv1_2_client_method()); - if (!client->ctx) { - ESP_LOGE(MQTT_TAG, "Failed to create SSL CTX"); - goto failed1; - } - } - - client->socket = socket(PF_INET, SOCK_STREAM, 0); - if (client->socket == -1) { - ESP_LOGE(MQTT_TAG, "Failed to create socket"); - goto failed2; - } - - ESP_LOGI(MQTT_TAG, "Connecting to server %s:%d,%d", inet_ntoa((remote_ip.sin_addr)), client->settings->port, remote_ip.sin_port); - - if (connect(client->socket, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) != 00) { - ESP_LOGE(MQTT_TAG, "Connect failed"); - goto failed3; - } - - if (client->settings->use_ssl) { - ESP_LOGI(MQTT_TAG, "Creating SSL object..."); - client->ssl = SSL_new(client->ctx); - if (!client->ssl) { - ESP_LOGE(MQTT_TAG, "Unable to create new SSL object"); - goto failed3; - } - - if (!SSL_set_fd(client->ssl, client->socket)) { - ESP_LOGE(MQTT_TAG, "SSL set_fd failed"); - goto failed3; - } - - ESP_LOGI(MQTT_TAG, "Start SSL connect.."); - if (!SSL_connect(client->ssl)) { - ESP_LOGE(MQTT_TAG, "SSL Connect FAILED"); - goto failed4; - } - } - ESP_LOGI(MQTT_TAG, "Connected!"); - - client->status = MQTT_STATUS_CONNECTED; - return true; - - //failed5: - // SSL_shutdown(client->ssl); - -failed4: // SSL_CTX_new failed - if (client->settings->use_ssl) { - SSL_free(client->ssl); - client->ssl = NULL; - } - -failed3: // Connect failed - close(client->socket); - client->socket = -1; - -failed2: // Failed to create socket - if (client->settings->use_ssl) { - SSL_CTX_free(client->ctx); - } - -failed1: - if (client->settings->use_ssl) { - client->ctx = NULL; - } - return false; - } -} - - -// Close client socket -// including SSL objects if enabled -//----------------------------------- -void closeclient(mqtt_client *client) -{ - if (client->socket != -1) { - close(client->socket); - client->socket = -1; - ESP_LOGI(MQTT_TAG, "Closing client socket"); - } - - if (client->settings->use_ssl) { - if (client->ssl != NULL) { - SSL_shutdown(client->ssl); - SSL_free(client->ssl); - client->ssl = NULL; - } - - if (client->ctx != NULL) { - SSL_CTX_free(client->ctx); - client->ctx = NULL; - } - } - client->status = MQTT_STATUS_DISCONNECTED; -} - -//----------------------------------------------------------------------- -int mqtt_read(mqtt_client *client, void *buffer, int len, int timeout_ms) -{ - int result; - struct timeval tv; - if (timeout_ms > 0) { - tv.tv_sec = 0; - tv.tv_usec = timeout_ms * 1000; - while (tv.tv_usec > 1000 * 1000) { - tv.tv_usec -= 1000 * 1000; - tv.tv_sec++; - } - setsockopt(client->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - } - - if (client->settings->use_ssl) result = SSL_read(client->ssl, buffer, len); - else result = read(client->socket, buffer, len); - - if (timeout_ms > 0) { - tv.tv_sec = 0; - tv.tv_usec = 0; - setsockopt(client->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); - } - - return result; -} - -//------------------------------------------------------------------------------ -int mqtt_write(mqtt_client *client, const void *buffer, int len, int timeout_ms) -{ - int result; - struct timeval tv; - if (timeout_ms > 0) { - tv.tv_sec = 0; - tv.tv_usec = timeout_ms * 1000; - while (tv.tv_usec > 1000 * 1000) { - tv.tv_usec -= 1000 * 1000; - tv.tv_sec++; - } - setsockopt(client->socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - } - - if (client->settings->use_ssl) result = SSL_write(client->ssl, buffer, len); - else result = write(client->socket, buffer, len); - - if (timeout_ms > 0) { - tv.tv_sec = 0; - tv.tv_usec = 0; - setsockopt(client->socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - } - - return result; -} - -/* - * mqtt_connect - * input - client - * return 1: success, 0: fail - */ -//------------------------------------------- -static bool mqtt_connect(mqtt_client *client) -{ - int write_len, read_len, connect_rsp_code; - - mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length); - client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info); - client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); - client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length); - - ESP_LOGI(MQTT_TAG, "Sending MQTT CONNECT message, type: %d, id: %04X", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id); - - write_len = client->settings->write_cb(client, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length, 0); - if(write_len < 0) { - ESP_LOGE(MQTT_TAG, "Writing failed: %d", errno); - return false; - } - - ESP_LOGI(MQTT_TAG, "Reading MQTT CONNECT response message"); - - read_len = client->settings->read_cb(client, client->mqtt_state.in_buffer, CONFIG_MQTT_BUFFER_SIZE_BYTE, 10 * 1000); - - if (read_len < 0) { - ESP_LOGE(MQTT_TAG, "Error network response"); - return false; - } - if (mqtt_get_type(client->mqtt_state.in_buffer) != MQTT_MSG_TYPE_CONNACK) { - ESP_LOGE(MQTT_TAG, "Invalid MSG_TYPE response: %d, read_len: %d", mqtt_get_type(client->mqtt_state.in_buffer), read_len); - return false; - } - connect_rsp_code = mqtt_get_connect_return_code(client->mqtt_state.in_buffer); - switch (connect_rsp_code) { - case CONNECTION_ACCEPTED: - ESP_LOGI(MQTT_TAG, "Connected"); - return true; - case CONNECTION_REFUSE_PROTOCOL: - ESP_LOGW(MQTT_TAG, "Connection refused, bad protocol"); - return false; - case CONNECTION_REFUSE_SERVER_UNAVAILABLE: - ESP_LOGW(MQTT_TAG, "Connection refused, server unavailable"); - return false; - case CONNECTION_REFUSE_BAD_USERNAME: - ESP_LOGW(MQTT_TAG, "Connection refused, bad username or password"); - return false; - case CONNECTION_REFUSE_NOT_AUTHORIZED: - ESP_LOGW(MQTT_TAG, "Connection refused, not authorized"); - return false; - default: - ESP_LOGW(MQTT_TAG, "Connection refused, Unknown reason"); - return false; - } - return false; -} - -//======================================== -void mqtt_sending_task(void *pvParameters) -{ - mqtt_client *client = (mqtt_client *)pvParameters; - uint32_t msg_len; - int send_len, sent_len = 0; - bool connected = true; - ESP_LOGI(MQTT_TAG, "Sending task started"); - - while (connected) { - if (client->terminate_mqtt) { - ESP_LOGI(MQTT_TAG, "Terminate, sending task exit."); - client->status = MQTT_STATUS_STOPPING; - break; - } - if (xQueueReceive(client->xSendingQueue, &msg_len, 1000 / portTICK_RATE_MS)) { - //queue available - while (msg_len > 0) { - send_len = msg_len; - if (send_len > CONFIG_MQTT_BUFFER_SIZE_BYTE) send_len = CONFIG_MQTT_BUFFER_SIZE_BYTE; - ESP_LOGD(MQTT_TAG, "Sending %d bytes", send_len); - - rb_read(&client->send_rb, client->mqtt_state.out_buffer, send_len); - client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.out_buffer); - client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.out_buffer, send_len); - send_len = client->settings->write_cb(client, client->mqtt_state.out_buffer, send_len, 5 * 1000); - if (send_len <= 0) { - ESP_LOGE(MQTT_TAG, "Write error: %d", errno); - connected = false; - break; - } - - //TODO: Check sending type, to callback publish message - msg_len -= send_len; - sent_len += send_len; - } - //invalidate keepalive timer - client->keepalive_tick = client->settings->keepalive / 2; - if (client->mqtt_state.sending_msg_type == MQTT_SENDING_TYPE_PUBLISH) { - client->mqtt_state.sending_msg_type = MQTT_SENDING_TYPE_NONE; - ESP_LOGI(MQTT_TAG, "Published %d bytes", sent_len); - if (client->settings->publish_cb) { - client->settings->publish_cb(client, (void *)"Sent"); - } - } - } - else { - if (client->keepalive_tick > 0) client->keepalive_tick --; - else { - client->keepalive_tick = client->settings->keepalive / 2; - client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); - client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); - client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, - client->mqtt_state.outbound_message->length); - ESP_LOGD(MQTT_TAG, "Sending ping request"); - send_len = client->settings->write_cb(client, - client->mqtt_state.outbound_message->data, - client->mqtt_state.outbound_message->length, 0); - if(send_len <= 0) { - ESP_LOGE(MQTT_TAG, "Write error: %d", errno); - connected = false; - break; - } - } - } - } - closeclient(client); - client->settings->xMqttSendingTask = NULL; - vTaskDelete(NULL); -} - -//--------------------------------------------------------------------- -void deliver_publish(mqtt_client *client, uint8_t *message, int length) -{ - mqtt_event_data_t event_data; - int len_read, total_mqtt_len = 0, mqtt_len = 0, mqtt_offset = 0; - uint8_t do_cb = (client->settings->data_cb != NULL); - do - { - if(total_mqtt_len == 0){ - event_data.topic_length = length; - event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length); - event_data.data_length = length; - event_data.data = mqtt_get_publish_data(message, &event_data.data_length); - total_mqtt_len = client->mqtt_state.message_length - client->mqtt_state.message_length_read + event_data.data_length; - if (total_mqtt_len > CONFIG_MQTT_MAX_PAYLOAD_SIZE) event_data.data_total_length = CONFIG_MQTT_MAX_PAYLOAD_SIZE; - else event_data.data_total_length = total_mqtt_len; - mqtt_len = event_data.data_length; - } else { - mqtt_len = len_read; - event_data.data = (const char*)client->mqtt_state.in_buffer; - } - - event_data.data_offset = mqtt_offset; - event_data.data_length = mqtt_len; - - ESP_LOGD(MQTT_TAG, "Data received: %d/%d bytes ", mqtt_len, total_mqtt_len); - if (do_cb) { - if ((mqtt_offset+mqtt_len) > CONFIG_MQTT_MAX_PAYLOAD_SIZE) { - event_data.data_length = CONFIG_MQTT_MAX_PAYLOAD_SIZE - mqtt_offset; - do_cb = 0; - } - client->settings->data_cb(client, &event_data); - } - mqtt_offset += mqtt_len; - if (client->mqtt_state.message_length_read >= client->mqtt_state.message_length) - break; - - len_read = client->settings->read_cb(client, client->mqtt_state.in_buffer, CONFIG_MQTT_BUFFER_SIZE_BYTE, 0); - if(len_read < 0) { - ESP_LOGE(MQTT_TAG, "Read error: %d", errno); - break; - } - client->mqtt_state.message_length_read += len_read; - } while (1); - -} - -//--------------------------------------------------- -void mqtt_start_receive_schedule(mqtt_client *client) -{ - int read_len; - uint8_t msg_type; - uint8_t msg_qos; - uint16_t msg_id; - - while (1) { - if (client->terminate_mqtt) { - ESP_LOGI(MQTT_TAG, "Terminate, receive schedule exit."); - client->status = MQTT_STATUS_STOPPING; - break; - } - if (client->settings->xMqttSendingTask == NULL) break; - - read_len = client->settings->read_cb(client, client->mqtt_state.in_buffer, CONFIG_MQTT_BUFFER_SIZE_BYTE, 0); - - ESP_LOGD(MQTT_TAG, "Read length %d", read_len); - if (read_len <= 0) { - if (client->terminate_mqtt) { - ESP_LOGI(MQTT_TAG, "Terminate, receive schedule exit."); - client->status = MQTT_STATUS_STOPPING; - } - else { - ESP_LOGE(MQTT_TAG, "Socket error (%d), exit Receive schedule", errno); - } - break; - } - - msg_type = mqtt_get_type(client->mqtt_state.in_buffer); - msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); - msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); - // ESP_LOGI(MQTT_TAG, "msg_type %d, msg_id: %d, pending_id: %d", msg_type, msg_id, client->mqtt_state.pending_msg_type); - switch (msg_type) - { - case MQTT_MSG_TYPE_SUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) { - ESP_LOGI(MQTT_TAG, "Subscribe successful"); - client->subs_flag = 1; - if (client->settings->subscribe_cb) { - client->settings->subscribe_cb(client, (void *)subs_last_topic); - } - } - break; - case MQTT_MSG_TYPE_UNSUBACK: - //if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id) { - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE) { - ESP_LOGI(MQTT_TAG, "UnSubscribe successful"); - client->unsubs_flag = 1; - client->subs_flag = 1; - if (client->settings->unsubscribe_cb) { - client->settings->unsubscribe_cb(client, (void *)unsubs_last_topic); - } - } - break; - case MQTT_MSG_TYPE_PUBLISH: - if (msg_qos == 1) - client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); - else if (msg_qos == 2) - client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); - - if (msg_qos == 1 || msg_qos == 2) { - ESP_LOGI(MQTT_TAG, "Queue response QoS: %d", msg_qos); - mqtt_queue(client); - // if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) { - // ESP_LOGI(MQTT_TAG, "MQTT: Queue full"); - // } - } - client->mqtt_state.message_length_read = read_len; - client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - ESP_LOGI(MQTT_TAG, "deliver_publish"); - - deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); - break; - case MQTT_MSG_TYPE_PUBACK: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) { - ESP_LOGI(MQTT_TAG, "received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish"); - if (client->settings->publish_cb) { - client->settings->publish_cb(client, (void *)"QoS1 acknowledged"); - } - } - break; - case MQTT_MSG_TYPE_PUBREC: - client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); - mqtt_queue(client); - break; - case MQTT_MSG_TYPE_PUBREL: - client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); - mqtt_queue(client); - break; - case MQTT_MSG_TYPE_PUBCOMP: - if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBREL && client->mqtt_state.pending_msg_id == msg_id) { - ESP_LOGI(MQTT_TAG, "Receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish"); - if (client->settings->publish_cb) { - client->settings->publish_cb(client, (void *)"QoS2 acknowledged"); - } - } - break; - case MQTT_MSG_TYPE_PINGREQ: - client->mqtt_state.sending_msg_type = MQTT_SENDING_TYPE_PING; - client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); - mqtt_queue(client); - break; - case MQTT_MSG_TYPE_PINGRESP: - ESP_LOGD(MQTT_TAG, "MQTT_MSG_TYPE_PINGRESP"); - // Ignore - break; - } - } -} - -//--------------------------------- -void mqtt_free(mqtt_client *client) -{ - if (client == NULL) return; - - vQueueDelete(client->xSendingQueue); - - free(client->mqtt_state.in_buffer); - free(client->mqtt_state.out_buffer); - free(client->send_rb.p_o); - - ESP_LOGI(MQTT_TAG, "Client freed"); -} - -//================================ -void mqtt_task(void *pvParameters) -{ - ESP_LOGI(MQTT_TAG, "Starting Mqtt task"); - - mqtt_client *client = (mqtt_client *)pvParameters; - - while (1) { - if (client->terminate_mqtt) { - client->status = MQTT_STATUS_STOPPING; - break; - } - - if (client->settings->connect_cb(client) == false) { - ESP_LOGE(MQTT_TAG, "Connection to server %s:%d failed!", client->settings->host, client->settings->port); - client->status = MQTT_STATUS_STOPPING; - break; - } - - ESP_LOGI(MQTT_TAG, "Connected to server %s:%d", client->settings->host, client->settings->port); - if (!mqtt_connect(client)) { - client->settings->disconnect_cb(client); - - if (client->settings->disconnected_cb) { - client->settings->disconnected_cb(client, NULL); - } - - if (!client->settings->auto_reconnect) { - client->status = MQTT_STATUS_STOPPING; - break; - } - else continue; - } - - ESP_LOGI(MQTT_TAG, "Connected to MQTT broker, creating sending thread before calling connected callback"); - xTaskCreate(&mqtt_sending_task, "mqtt_sending_task", client->settings->xMqttSendingTask_stacksize, client, CONFIG_MQTT_PRIORITY + 1, &(client->settings->xMqttSendingTask)); - if (client->settings->xMqttSendingTask == NULL) break; - if (client->settings->connected_cb) { - client->settings->connected_cb(client, NULL); - } - - ESP_LOGI(MQTT_TAG, "mqtt_start_receive_schedule"); - mqtt_start_receive_schedule(client); - - client->settings->disconnect_cb(client); - if (client->settings->disconnected_cb) { - client->settings->disconnected_cb(client, NULL); - } - - if (client->settings->xMqttSendingTask != NULL) { - vTaskDelete(client->settings->xMqttSendingTask); - } - if (!client->settings->auto_reconnect) { - client->status = MQTT_STATUS_STOPPING; - break; - } - vTaskDelay(1000 / portTICK_RATE_MS); - - } - - mqtt_free(client); - client->settings->xMqttTask = NULL; - client->status = MQTT_STATUS_STOPPED; - vTaskDelete(NULL); -} - -// ================================= -int mqtt_start(mqtt_client *client) -{ - // ==== Check for Internet connection first ==== - tcpip_adapter_ip_info_t info; - tcpip_adapter_get_ip_info(WIFI_IF_STA, &info); - if (info.ip.addr == 0) { - #ifdef CONFIG_MICROPY_USE_GSM - if (ppposStatus() != GSM_STATE_CONNECTED) { - return -9; - } - #else - return -9; - #endif - } - // ============================================= - - client->terminate_mqtt = false; - - uint8_t *rb_buf; - if (client->settings->xMqttTask != NULL) return -1; - - client->status = MQTT_STATUS_DISCONNECTED; - client->settings->xMqttSendingTask = NULL; - client->settings->xMqttSendingTask_stacksize = 2048; - client->settings->xMqttTask_stacksize = 2048; - - client->connect_info.client_id = client->settings->client_id; - client->connect_info.username = client->settings->username; - client->connect_info.password = client->settings->password; - client->connect_info.will_topic = client->settings->lwt_topic; - client->connect_info.will_message = client->settings->lwt_msg; - client->connect_info.will_qos = client->settings->lwt_qos; - client->connect_info.will_retain = client->settings->lwt_retain; - client->connect_info.will_length = client->settings->lwt_msg_len; - - client->keepalive_tick = client->settings->keepalive / 2; - - client->connect_info.keepalive = client->settings->keepalive; - client->connect_info.clean_session = client->settings->clean_session; - - client->mqtt_state.in_buffer = (uint8_t *)malloc(CONFIG_MQTT_BUFFER_SIZE_BYTE); - client->mqtt_state.in_buffer_length = CONFIG_MQTT_BUFFER_SIZE_BYTE; - client->mqtt_state.out_buffer = (uint8_t *)malloc(CONFIG_MQTT_BUFFER_SIZE_BYTE); - client->mqtt_state.out_buffer_length = CONFIG_MQTT_BUFFER_SIZE_BYTE; - client->mqtt_state.connect_info = &client->connect_info; - - client->socket = -1; - - if (!client->settings->connect_cb) - client->settings->connect_cb = client_connect; - if (!client->settings->disconnect_cb) - client->settings->disconnect_cb = closeclient; - if (!client->settings->read_cb) - client->settings->read_cb = mqtt_read; - if (!client->settings->write_cb) - client->settings->write_cb = mqtt_write; - - client->ctx = NULL; - client->ssl = NULL; - if (client->settings->use_ssl) client->settings->xMqttTask_stacksize = 10240; // Need more stack to handle SSL handshake - - /* Create a queue capable of containing 64 unsigned long values. */ - client->xSendingQueue = xQueueCreate(64, sizeof( uint32_t )); - if (client->xSendingQueue == 0) return -3; - - rb_buf = (uint8_t*) malloc(CONFIG_MQTT_BUFFER_SIZE_BYTE * 4); - - if (rb_buf == NULL) { - ESP_LOGE(MQTT_TAG, "Error allocating ring buffer"); - return -2; - } - - rb_init(&client->send_rb, rb_buf, CONFIG_MQTT_BUFFER_SIZE_BYTE * 4, 1); - - mqtt_msg_init(&client->mqtt_state.mqtt_connection, - client->mqtt_state.out_buffer, - client->mqtt_state.out_buffer_length); - - xTaskCreate(&mqtt_task, "mqtt_task", client->settings->xMqttTask_stacksize, client, CONFIG_MQTT_PRIORITY, &client->settings->xMqttTask); - if (client->settings->xMqttTask == NULL) return -4; - - return 0; -} - -//---------------------------------------------------------------------- -void mqtt_subscribe(mqtt_client *client, const char *topic, uint8_t qos) -{ - if (subs_last_topic) free(subs_last_topic); - subs_last_topic = malloc(strlen(topic)+1); - if (subs_last_topic) strcpy(subs_last_topic, topic); - - client->subs_flag = 0; - client->mqtt_state.sending_msg_type = MQTT_SENDING_TYPE_SUBSCRIBE; - client->mqtt_state.outbound_message = mqtt_msg_subscribe(&client->mqtt_state.mqtt_connection, - topic, qos, - &client->mqtt_state.pending_msg_id); - ESP_LOGI(MQTT_TAG, "Queue subscribe, topic \"%s\", id: %d", topic, client->mqtt_state.pending_msg_id); - mqtt_queue(client); -} - -//----------------------------------------------------------- -void mqtt_unsubscribe(mqtt_client *client, const char *topic) -{ - if (unsubs_last_topic) free(unsubs_last_topic); - unsubs_last_topic = malloc(strlen(topic)+1); - if (unsubs_last_topic) strcpy(unsubs_last_topic, topic); - - client->unsubs_flag = 0; - client->mqtt_state.sending_msg_type = MQTT_SENDING_TYPE_UNSUBSCRIBE; - client->mqtt_state.outbound_message = mqtt_msg_unsubscribe(&client->mqtt_state.mqtt_connection, - topic, - &client->mqtt_state.pending_msg_id); - ESP_LOGI(MQTT_TAG, "Queue unsubscribe, topic \"%s\", id: %d", topic, client->mqtt_state.pending_msg_id); - mqtt_queue(client); -} - -//------------------------------------------------------------------------------------------------------ -int mqtt_publish(mqtt_client* client, const char *topic, const char *data, int len, int qos, int retain) -{ - client->mqtt_state.outbound_message = mqtt_msg_publish(&client->mqtt_state.mqtt_connection, - topic, data, len, - qos, retain, - &client->mqtt_state.pending_msg_id); - if (client->mqtt_state.outbound_message->length == 0) return -1; - - client->mqtt_state.sending_msg_type = MQTT_SENDING_TYPE_PUBLISH; - mqtt_queue(client); - ESP_LOGI(MQTT_TAG, "Queuing publish, length: %d, queue size(%d/%d)", - client->mqtt_state.outbound_message->length, - client->send_rb.fill_cnt, - client->send_rb.size); - return 0; -} - -//--------------------------------- -void mqtt_stop(mqtt_client* client) -{ - client->terminate_mqtt = true; - client->status = MQTT_STATUS_STOPPING; -} - -#endif diff --git a/MicroPython_BUILD/components/espmqtt/mqtt_client.c b/MicroPython_BUILD/components/espmqtt/mqtt_client.c new file mode 100644 index 00000000..9783e5da --- /dev/null +++ b/MicroPython_BUILD/components/espmqtt/mqtt_client.c @@ -0,0 +1,820 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * Apache License Version 2.0 + * + * Slightly modified mqtt library from https://github.com/tuanpmt/espmqtt + * + * Copyright (c) 2018 tuanpm (https://github.com/tuanpmt/espmqtt) + * Copyright (c) 2018 LoBo (https://github.com/loboris) +*/ + +#include + +#include "mqtt_client.h" + +/* using uri parser */ +#include "http_parser.h" +#include "sdkconfig.h" + +const char *MQTT_TAG = "MQTT_CLIENT"; + +const static int STOPPED_BIT = BIT0; + +extern int MainTaskCore; + +static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client); +static esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config); +static esp_err_t esp_mqtt_destroy_config(esp_mqtt_client_handle_t client); +static esp_err_t esp_mqtt_connect(esp_mqtt_client_handle_t client, int timeout_ms); +static esp_err_t esp_mqtt_abort_connection(esp_mqtt_client_handle_t client); +static esp_err_t esp_mqtt_client_ping(esp_mqtt_client_handle_t client); +static char *create_string(const char *ptr, int len); + +static esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config) +{ + //Copy user configurations to client context + esp_err_t err = ESP_OK; + mqtt_config_storage_t *cfg = calloc(1, sizeof(mqtt_config_storage_t)); + ESP_MEM_CHECK(MQTT_TAG, cfg, return ESP_ERR_NO_MEM); + + client->config = cfg; + + cfg->task_prio = config->task_prio; + if (cfg->task_prio <= 0) { + cfg->task_prio = MQTT_TASK_PRIORITY; + } + + cfg->task_stack = config->task_stack; + if (cfg->task_stack == 0) { + cfg->task_stack = MQTT_TASK_STACK; + } + + err = ESP_ERR_NO_MEM; + if (config->host[0]) { + cfg->host = strdup(config->host); + ESP_MEM_CHECK(MQTT_TAG, cfg->host, goto _mqtt_set_config_failed); + } + cfg->port = config->port; + + if (config->username[0]) { + client->connect_info.username = strdup(config->username); + ESP_MEM_CHECK(MQTT_TAG, client->connect_info.username, goto _mqtt_set_config_failed); + } + + if (config->password[0]) { + client->connect_info.password = strdup(config->password); + ESP_MEM_CHECK(MQTT_TAG, client->connect_info.password, goto _mqtt_set_config_failed); + } + + if (config->client_id[0]) { + client->connect_info.client_id = strdup(config->client_id); + } else { + client->connect_info.client_id = platform_create_id_string(); + } + ESP_MEM_CHECK(MQTT_TAG, client->connect_info.client_id, goto _mqtt_set_config_failed); + ESP_LOGD(MQTT_TAG, "MQTT client_id=%s", client->connect_info.client_id); + + if (config->uri[0]) { + cfg->uri = strdup(config->uri); + ESP_MEM_CHECK(MQTT_TAG, cfg->uri, goto _mqtt_set_config_failed); + } + + if (config->lwt_topic[0]) { + client->connect_info.will_topic = strdup(config->lwt_topic); + ESP_MEM_CHECK(MQTT_TAG, client->connect_info.will_topic, goto _mqtt_set_config_failed); + } + + if (config->lwt_msg_len) { + client->connect_info.will_message = malloc(config->lwt_msg_len); + ESP_MEM_CHECK(MQTT_TAG, client->connect_info.will_message, goto _mqtt_set_config_failed); + memcpy(client->connect_info.will_message, config->lwt_msg, config->lwt_msg_len); + client->connect_info.will_length = config->lwt_msg_len; + } else if (config->lwt_msg[0]) { + client->connect_info.will_message = strdup(config->lwt_msg); + ESP_MEM_CHECK(MQTT_TAG, client->connect_info.will_message, goto _mqtt_set_config_failed); + client->connect_info.will_length = strlen(config->lwt_msg); + } + + client->connect_info.will_qos = config->lwt_qos; + client->connect_info.will_retain = config->lwt_retain; + + client->connect_info.clean_session = 1; + if (config->disable_clean_session) { + client->connect_info.clean_session = false; + } + client->connect_info.keepalive = config->keepalive; + if (client->connect_info.keepalive == 0) { + client->connect_info.keepalive = MQTT_KEEPALIVE_TICK; + } + cfg->network_timeout_ms = MQTT_NETWORK_TIMEOUT_MS; + cfg->user_context = config->user_context; + cfg->event_handle = config->event_handle; + cfg->auto_reconnect = true; + if (config->disable_auto_reconnect) { + cfg->auto_reconnect = false; + } + + return ESP_OK; + +_mqtt_set_config_failed: + esp_mqtt_destroy_config(client); + return err; +} + +static esp_err_t esp_mqtt_destroy_config(esp_mqtt_client_handle_t client) +{ + mqtt_config_storage_t *cfg = client->config; + if (cfg->host) free(cfg->host); + if (cfg->uri) free(cfg->uri); + if (cfg->path) free(cfg->path); + if (cfg->scheme) free(cfg->scheme); + if (client->connect_info.will_topic) free(client->connect_info.will_topic); + if (client->connect_info.will_message) free(client->connect_info.will_message); + if (client->connect_info.client_id) free(client->connect_info.client_id); + if (client->connect_info.username) free(client->connect_info.username); + if (client->connect_info.password) free(client->connect_info.password); + free(client->config); + return ESP_OK; +} + +static esp_err_t esp_mqtt_connect(esp_mqtt_client_handle_t client, int timeout_ms) +{ + int write_len, read_len, connect_rsp_code; + mqtt_msg_init(&client->mqtt_state.mqtt_connection, + client->mqtt_state.out_buffer, + client->mqtt_state.out_buffer_length); + client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, + client->mqtt_state.connect_info); + client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); + client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, + client->mqtt_state.outbound_message->length); + ESP_LOGI(MQTT_TAG, "Sending MQTT CONNECT message, type: %d, id: %04X", + client->mqtt_state.pending_msg_type, + client->mqtt_state.pending_msg_id); + + write_len = transport_write(client->transport, + (char *)client->mqtt_state.outbound_message->data, + client->mqtt_state.outbound_message->length, + client->config->network_timeout_ms); + if (write_len < 0) { + ESP_LOGE(MQTT_TAG, "Writing failed, errno= %d", errno); + return ESP_FAIL; + } + read_len = transport_read(client->transport, + (char *)client->mqtt_state.in_buffer, + client->mqtt_state.outbound_message->length, + client->config->network_timeout_ms); + if (read_len < 0) { + ESP_LOGE(MQTT_TAG, "Error network response"); + return ESP_FAIL; + } + + if (mqtt_get_type(client->mqtt_state.in_buffer) != MQTT_MSG_TYPE_CONNACK) { + ESP_LOGE(MQTT_TAG, "Invalid MSG_TYPE response: %d, read_len: %d", mqtt_get_type(client->mqtt_state.in_buffer), read_len); + return ESP_FAIL; + } + connect_rsp_code = mqtt_get_connect_return_code(client->mqtt_state.in_buffer); + switch (connect_rsp_code) { + case CONNECTION_ACCEPTED: + ESP_LOGD(MQTT_TAG, "Connected"); + return ESP_OK; + case CONNECTION_REFUSE_PROTOCOL: + ESP_LOGW(MQTT_TAG, "Connection refused, bad protocol"); + return ESP_FAIL; + case CONNECTION_REFUSE_SERVER_UNAVAILABLE: + ESP_LOGW(MQTT_TAG, "Connection refused, server unavailable"); + return ESP_FAIL; + case CONNECTION_REFUSE_BAD_USERNAME: + ESP_LOGW(MQTT_TAG, "Connection refused, bad username or password"); + return ESP_FAIL; + case CONNECTION_REFUSE_NOT_AUTHORIZED: + ESP_LOGW(MQTT_TAG, "Connection refused, not authorized"); + return ESP_FAIL; + default: + ESP_LOGW(MQTT_TAG, "Connection refused, Unknow reason"); + return ESP_FAIL; + } + return ESP_OK; +} + +static esp_err_t esp_mqtt_abort_connection(esp_mqtt_client_handle_t client) +{ + transport_close(client->transport); + client->wait_timeout_ms = MQTT_RECONNECT_TIMEOUT_MS; + client->reconnect_tick = platform_tick_get_ms(); + client->state = MQTT_STATE_WAIT_TIMEOUT; + ESP_LOGI(MQTT_TAG, "Reconnect after %d ms", client->wait_timeout_ms); + client->event.event_id = MQTT_EVENT_DISCONNECTED; + esp_mqtt_dispatch_event(client); + return ESP_OK; +} + +esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config) +{ + esp_mqtt_client_handle_t client = calloc(1, sizeof(struct esp_mqtt_client)); + ESP_MEM_CHECK(MQTT_TAG, client, return NULL); + + if (esp_mqtt_set_config(client, config) != ESP_OK) { + ESP_LOGE(MQTT_TAG, "Setting configuration failed"); + return NULL; + } + + client->transport_list = transport_list_init(); + ESP_MEM_CHECK(MQTT_TAG, client->transport_list, goto _mqtt_init_failed); + + transport_handle_t tcp = transport_tcp_init(); + ESP_MEM_CHECK(MQTT_TAG, tcp, goto _mqtt_init_failed); + transport_set_default_port(tcp, MQTT_TCP_DEFAULT_PORT); + transport_list_add(client->transport_list, tcp, "mqtt"); + if (config->transport == MQTT_TRANSPORT_OVER_TCP) { + client->config->scheme = create_string("mqtt", 4); + ESP_MEM_CHECK(MQTT_TAG, client->config->scheme, goto _mqtt_init_failed); + } + +#if MQTT_ENABLE_WS + transport_handle_t ws = transport_ws_init(tcp); + ESP_MEM_CHECK(MQTT_TAG, ws, goto _mqtt_init_failed); + transport_set_default_port(ws, MQTT_WS_DEFAULT_PORT); + transport_list_add(client->transport_list, ws, "ws"); + if (config->transport == MQTT_TRANSPORT_OVER_WS) { + client->config->scheme = create_string("ws", 2); + ESP_MEM_CHECK(MQTT_TAG, client->config->scheme, goto _mqtt_init_failed); + } +#endif + +#if MQTT_ENABLE_SSL + transport_handle_t ssl = transport_ssl_init(); + ESP_MEM_CHECK(MQTT_TAG, ssl, goto _mqtt_init_failed); + transport_set_default_port(ssl, MQTT_SSL_DEFAULT_PORT); + if (config->cert_pem) { + transport_ssl_set_cert_data(ssl, config->cert_pem, strlen(config->cert_pem)); + } + transport_list_add(client->transport_list, ssl, "mqtts"); + if (config->transport == MQTT_TRANSPORT_OVER_SSL) { + client->config->scheme = create_string("mqtts", 5); + ESP_MEM_CHECK(MQTT_TAG, client->config->scheme, goto _mqtt_init_failed); + } +#endif + +#if MQTT_ENABLE_WSS + transport_handle_t wss = transport_ws_init(ssl); + ESP_MEM_CHECK(MQTT_TAG, wss, goto _mqtt_init_failed); + transport_set_default_port(wss, MQTT_WSS_DEFAULT_PORT); + transport_list_add(client->transport_list, wss, "wss"); + if (config->transport == MQTT_TRANSPORT_OVER_WSS) { + client->config->scheme = create_string("wss", 3); + ESP_MEM_CHECK(MQTT_TAG, client->config->scheme, goto _mqtt_init_failed); + } +#endif + if (client->config->uri) { + if (esp_mqtt_client_set_uri(client, client->config->uri) != ESP_OK) { + goto _mqtt_init_failed; + } + } + + if (client->config->scheme == NULL) { + client->config->scheme = create_string("mqtt", 4); + ESP_MEM_CHECK(MQTT_TAG, client->config->scheme, goto _mqtt_init_failed); + } + + client->keepalive_tick = platform_tick_get_ms(); + client->reconnect_tick = platform_tick_get_ms(); + + int buffer_size = config->buffer_size; + if (buffer_size <= 0) { + buffer_size = MQTT_BUFFER_SIZE_BYTE; + } + + client->mqtt_state.in_buffer = (uint8_t *)malloc(buffer_size); + ESP_MEM_CHECK(MQTT_TAG, client->mqtt_state.in_buffer, goto _mqtt_init_failed); + client->mqtt_state.in_buffer_length = buffer_size; + client->mqtt_state.out_buffer = (uint8_t *)malloc(buffer_size); + ESP_MEM_CHECK(MQTT_TAG, client->mqtt_state.out_buffer, goto _mqtt_init_failed); + + client->mqtt_state.out_buffer_length = buffer_size; + client->mqtt_state.connect_info = &client->connect_info; + client->outbox = outbox_init(); + ESP_MEM_CHECK(MQTT_TAG, client->outbox, goto _mqtt_init_failed); + client->status_bits = xEventGroupCreate(); + ESP_MEM_CHECK(MQTT_TAG, client->status_bits, goto _mqtt_init_failed); + return client; + +_mqtt_init_failed: + esp_mqtt_client_destroy(client); + return NULL; +} + +esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client) +{ + esp_mqtt_client_stop(client); + esp_mqtt_destroy_config(client); + transport_list_destroy(client->transport_list); + outbox_destroy(client->outbox); + vEventGroupDelete(client->status_bits); + free(client->mqtt_state.in_buffer); + free(client->mqtt_state.out_buffer); + free(client); + return ESP_OK; +} + +static char *create_string(const char *ptr, int len) +{ + char *ret; + if (len <= 0) { + return NULL; + } + ret = calloc(1, len + 1); + ESP_MEM_CHECK(MQTT_TAG, ret, return NULL); + memcpy(ret, ptr, len); + return ret; +} + +esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client, const char *uri) +{ + struct http_parser_url puri; + http_parser_url_init(&puri); + int parser_status = http_parser_parse_url(uri, strlen(uri), 0, &puri); + if (parser_status != 0) { + ESP_LOGE(MQTT_TAG, "Error parse uri = %s", uri); + return ESP_FAIL; + } + + if (client->config->scheme == NULL) { + client->config->scheme = create_string(uri + puri.field_data[UF_SCHEMA].off, puri.field_data[UF_SCHEMA].len); + } + + if (client->config->host == NULL) { + client->config->host = create_string(uri + puri.field_data[UF_HOST].off, puri.field_data[UF_HOST].len); + } + + if (client->config->path == NULL) { + client->config->path = create_string(uri + puri.field_data[UF_PATH].off, puri.field_data[UF_PATH].len); + } + if (client->config->path) { + transport_handle_t trans = transport_list_get_transport(client->transport_list, "ws"); + if (trans) { + transport_ws_set_path(trans, client->config->path); + } + trans = transport_list_get_transport(client->transport_list, "wss"); + if (trans) { + transport_ws_set_path(trans, client->config->path); + } + } + + if (puri.field_data[UF_PORT].len) { + client->config->port = strtol((const char*)(uri + puri.field_data[UF_PORT].off), NULL, 10); + } + + char *user_info = create_string(uri + puri.field_data[UF_USERINFO].off, puri.field_data[UF_USERINFO].len); + if (user_info) { + char *pass = strchr(user_info, ':'); + if (pass) { + pass[0] = 0; //terminal username + pass ++; + client->connect_info.password = strdup(pass); + } + client->connect_info.username = strdup(user_info); + + free(user_info); + } + + return ESP_OK; +} + +static esp_err_t mqtt_write_data(esp_mqtt_client_handle_t client) +{ + int write_len = transport_write(client->transport, + (char *)client->mqtt_state.outbound_message->data, + client->mqtt_state.outbound_message->length, + client->config->network_timeout_ms); + // client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); + if (write_len <= 0) { + ESP_LOGE(MQTT_TAG, "Error write data or timeout, written len = %d", write_len); + return ESP_FAIL; + } + return ESP_OK; +} + +static esp_err_t esp_mqtt_dispatch_event(esp_mqtt_client_handle_t client) +{ + client->event.msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); + client->event.user_context = client->config->user_context; + client->event.client = client; + + if (client->config->event_handle) { + return client->config->event_handle(&client->event); + } + return ESP_FAIL; +} + + + +static void deliver_publish(esp_mqtt_client_handle_t client, uint8_t *message, int length) +{ + const char *mqtt_topic, *mqtt_data; + uint32_t mqtt_topic_length, mqtt_data_length; + uint32_t mqtt_len, mqtt_offset = 0, total_mqtt_len = 0; + int len_read; + + do + { + mqtt_topic_length = length; + mqtt_topic = mqtt_get_publish_topic(message, &mqtt_topic_length); + mqtt_data_length = length; + mqtt_data = mqtt_get_publish_data(message, &mqtt_data_length); + + if(total_mqtt_len == 0){ + mqtt_topic_length = length; + mqtt_topic = mqtt_get_publish_topic(message, &mqtt_topic_length); + mqtt_data_length = length; + mqtt_data = mqtt_get_publish_data(message, &mqtt_data_length); + total_mqtt_len = client->mqtt_state.message_length - client->mqtt_state.message_length_read + mqtt_data_length; + mqtt_len = mqtt_data_length; + } else { + mqtt_len = len_read; + mqtt_data = (const char*)client->mqtt_state.in_buffer; + } + + ESP_LOGD(MQTT_TAG, "Get data len= %d, topic len=%d", mqtt_data_length, mqtt_topic_length); + client->event.event_id = MQTT_EVENT_DATA; + client->event.data = (char *)mqtt_data; + client->event.data_len = mqtt_len; + client->event.total_data_len = total_mqtt_len; + client->event.current_data_offset = mqtt_offset; + client->event.topic = (char *)mqtt_topic; + client->event.topic_len = mqtt_topic_length; + esp_mqtt_dispatch_event(client); + + mqtt_offset += mqtt_len; + if (client->mqtt_state.message_length_read >= client->mqtt_state.message_length) { + break; + } + + /*len_read = transport_read(client->transport, + (char *)client->mqtt_state.in_buffer, + client->mqtt_state.in_buffer_length, + client->config->network_timeout_ms);*/ + len_read = transport_read(client->transport, + (char *)client->mqtt_state.in_buffer, + client->mqtt_state.message_length - client->mqtt_state.message_length_read > client->mqtt_state.in_buffer_length ? + client->mqtt_state.in_buffer_length : client->mqtt_state.message_length - client->mqtt_state.message_length_read, + client->config->network_timeout_ms); + if (len_read <= 0) { + ESP_LOGE(MQTT_TAG, "Read error or timeout: %d", errno); + break; + } + client->mqtt_state.message_length_read += len_read; + } while (1); + + +} + +static bool is_valid_mqtt_msg(esp_mqtt_client_handle_t client, int msg_type, int msg_id) +{ + ESP_LOGD(MQTT_TAG, "pending_id=%d, pending_msg_count = %d", client->mqtt_state.pending_msg_id, client->mqtt_state.pending_msg_count); + if (client->mqtt_state.pending_msg_count == 0) { + return false; + } + if (outbox_delete(client->outbox, msg_id, msg_type) == ESP_OK) { + client->mqtt_state.pending_msg_count --; + return true; + } + if (client->mqtt_state.pending_msg_type == msg_type && client->mqtt_state.pending_msg_id == msg_id) { + client->mqtt_state.pending_msg_count --; + return true; + } + + return false; +} + +static void mqtt_enqueue(esp_mqtt_client_handle_t client) +{ + ESP_LOGD(MQTT_TAG, "mqtt_enqueue id: %d, type=%d successful", + client->mqtt_state.pending_msg_id, client->mqtt_state.pending_msg_type); + //lock mutex + if (client->mqtt_state.pending_msg_count > 0) { + //Copy to queue buffer + outbox_enqueue(client->outbox, + client->mqtt_state.outbound_message->data, + client->mqtt_state.outbound_message->length, + client->mqtt_state.pending_msg_id, + client->mqtt_state.pending_msg_type, + platform_tick_get_ms()); + } + //unlock +} + +static esp_err_t mqtt_process_receive(esp_mqtt_client_handle_t client) +{ + int read_len; + uint8_t msg_type; + uint8_t msg_qos; + uint16_t msg_id; + + read_len = transport_read(client->transport, (char *)client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length, 1000); + + if (read_len < 0) { + ESP_LOGE(MQTT_TAG, "Read error or end of stream"); + return ESP_FAIL; + } + + if (read_len == 0) { + return ESP_OK; + } + + msg_type = mqtt_get_type(client->mqtt_state.in_buffer); + msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer); + msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length); + + ESP_LOGD(MQTT_TAG, "msg_type=%d, msg_id=%d", msg_type, msg_id); + switch (msg_type) + { + case MQTT_MSG_TYPE_SUBACK: + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_SUBSCRIBE, msg_id)) { + ESP_LOGD(MQTT_TAG, "Subscribe successful"); + client->event.event_id = MQTT_EVENT_SUBSCRIBED; + client->event.type = MQTT_MSG_TYPE_SUBSCRIBE; + esp_mqtt_dispatch_event(client); + } + break; + case MQTT_MSG_TYPE_UNSUBACK: + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_UNSUBSCRIBE, msg_id)) { + ESP_LOGD(MQTT_TAG, "UnSubscribe successful"); + client->event.event_id = MQTT_EVENT_UNSUBSCRIBED; + client->event.type = MQTT_MSG_TYPE_UNSUBSCRIBE; + esp_mqtt_dispatch_event(client); + } + break; + case MQTT_MSG_TYPE_PUBLISH: + if (msg_qos == 1) { + client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id); + } + else if (msg_qos == 2) { + client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id); + } + + if (msg_qos == 1 || msg_qos == 2) { + ESP_LOGD(MQTT_TAG, "Queue response QoS: %d", msg_qos); + + if (mqtt_write_data(client) != ESP_OK) { + ESP_LOGE(MQTT_TAG, "Error write qos msg repsonse, qos = %d", msg_qos); + // TODO: Shoule reconnect? + // return ESP_FAIL; + } + } + client->mqtt_state.message_length_read = read_len; + client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); + ESP_LOGI(MQTT_TAG, "deliver_publish, message_length_read=%d, message_length=%d", read_len, client->mqtt_state.message_length); + + deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read); + break; + case MQTT_MSG_TYPE_PUBACK: + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_PUBLISH, msg_id)) { + ESP_LOGD(MQTT_TAG, "received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish"); + client->event.event_id = MQTT_EVENT_PUBLISHED; + client->event.type = MQTT_MSG_TYPE_PUBACK; + esp_mqtt_dispatch_event(client); + } + + break; + case MQTT_MSG_TYPE_PUBREC: + ESP_LOGD(MQTT_TAG, "received MQTT_MSG_TYPE_PUBREC"); + client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id); + mqtt_write_data(client); + break; + case MQTT_MSG_TYPE_PUBREL: + ESP_LOGD(MQTT_TAG, "received MQTT_MSG_TYPE_PUBREL"); + client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id); + mqtt_write_data(client); + + break; + case MQTT_MSG_TYPE_PUBCOMP: + ESP_LOGD(MQTT_TAG, "received MQTT_MSG_TYPE_PUBCOMP"); + if (is_valid_mqtt_msg(client, MQTT_MSG_TYPE_PUBREL, msg_id)) { + ESP_LOGD(MQTT_TAG, "Receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish"); + client->event.event_id = MQTT_EVENT_PUBLISHED; + client->event.type = MQTT_MSG_TYPE_PUBCOMP; + esp_mqtt_dispatch_event(client); + } + break; + case MQTT_MSG_TYPE_PINGREQ: + client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection); + mqtt_write_data(client); + break; + case MQTT_MSG_TYPE_PINGRESP: + ESP_LOGD(MQTT_TAG, "MQTT_MSG_TYPE_PINGRESP"); + // Ignore + break; + } + + return ESP_OK; +} + +static void esp_mqtt_task(void *pv) +{ + esp_mqtt_client_handle_t client = (esp_mqtt_client_handle_t) pv; + client->run = true; + + //get transport by scheme + client->transport = transport_list_get_transport(client->transport_list, client->config->scheme); + + if (client->transport == NULL) { + ESP_LOGE(MQTT_TAG, "There are no transports valid, stop mqtt client, config scheme = %s", client->config->scheme); + client->run = false; + } + //default port + if (client->config->port == 0) { + client->config->port = transport_get_default_port(client->transport); + } + + client->state = MQTT_STATE_INIT; + xEventGroupClearBits(client->status_bits, STOPPED_BIT); + while (client->run) { + + switch ((int)client->state) { + case MQTT_STATE_INIT: + if (client->transport == NULL) { + ESP_LOGE(MQTT_TAG, "There are no transport"); + client->run = false; + } + + if (transport_connect(client->transport, + client->config->host, + client->config->port, + client->config->network_timeout_ms) < 0) { + ESP_LOGE(MQTT_TAG, "Error transport connect"); + esp_mqtt_abort_connection(client); + break; + } + ESP_LOGD(MQTT_TAG, "Transport connected to %s://%s:%d", client->config->scheme, client->config->host, client->config->port); + if (esp_mqtt_connect(client, client->config->network_timeout_ms) != ESP_OK) { + ESP_LOGI(MQTT_TAG, "Error MQTT Connected"); + esp_mqtt_abort_connection(client); + break; + } + client->event.event_id = MQTT_EVENT_CONNECTED; + client->state = MQTT_STATE_CONNECTED; + esp_mqtt_dispatch_event(client); + + break; + case MQTT_STATE_CONNECTED: + // receive and process data + if (mqtt_process_receive(client) == ESP_FAIL) { + esp_mqtt_abort_connection(client); + break; + } + + if (platform_tick_get_ms() - client->keepalive_tick > client->connect_info.keepalive * 1000 / 2) { + if (esp_mqtt_client_ping(client) == ESP_FAIL) { + esp_mqtt_abort_connection(client); + break; + } + client->keepalive_tick = platform_tick_get_ms(); + } + + //Delete mesaage after 30 senconds + outbox_delete_expired(client->outbox, platform_tick_get_ms(), OUTBOX_EXPIRED_TIMEOUT_MS); + // + outbox_cleanup(client->outbox, OUTBOX_MAX_SIZE); + break; + case MQTT_STATE_WAIT_TIMEOUT: + + if (!client->config->auto_reconnect) { + client->run = false; + break; + } + if (platform_tick_get_ms() - client->reconnect_tick > client->wait_timeout_ms) { + client->state = MQTT_STATE_INIT; + client->reconnect_tick = platform_tick_get_ms(); + ESP_LOGD(MQTT_TAG, "Reconnecting..."); + } + vTaskDelay(client->wait_timeout_ms / 2 / portTICK_RATE_MS); + break; + } + } + transport_close(client->transport); + xEventGroupSetBits(client->status_bits, STOPPED_BIT); + + vTaskDelete(NULL); +} + +esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client) +{ + if (client->state >= MQTT_STATE_INIT) { + ESP_LOGE(MQTT_TAG, "Client has started"); + return ESP_FAIL; + } + #if CONFIG_MICROPY_USE_BOTH_CORES + int tres = xTaskCreate(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL); + #else + int tres = xTaskCreatePinnedToCore(esp_mqtt_task, "mqtt_task", client->config->task_stack, client, client->config->task_prio, NULL, MainTaskCore); + #endif + if (tres != pdTRUE) { + ESP_LOGE(MQTT_TAG, "Error creating mqtt task"); + return ESP_FAIL; + } + xEventGroupClearBits(client->status_bits, STOPPED_BIT); + return ESP_OK; +} + + +esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client) +{ + client->run = false; + xEventGroupWaitBits(client->status_bits, STOPPED_BIT, false, true, portMAX_DELAY); + client->state = MQTT_STATE_UNKNOWN; + return ESP_OK; +} + +static esp_err_t esp_mqtt_client_ping(esp_mqtt_client_handle_t client) +{ + client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection); + + if (mqtt_write_data(client) != ESP_OK) { + ESP_LOGE(MQTT_TAG, "Error sending ping"); + return ESP_FAIL; + } + ESP_LOGD(MQTT_TAG, "Sent PING successful"); + return ESP_OK; +} + +int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos) +{ + if (client->state != MQTT_STATE_CONNECTED) { + ESP_LOGE(MQTT_TAG, "Client has not connected"); + return -1; + } + mqtt_enqueue(client); //move pending msg to outbox (if have) + client->mqtt_state.outbound_message = mqtt_msg_subscribe(&client->mqtt_state.mqtt_connection, + topic, qos, + &client->mqtt_state.pending_msg_id); + + client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); + client->mqtt_state.pending_msg_count ++; + + if (mqtt_write_data(client) != ESP_OK) { + ESP_LOGE(MQTT_TAG, "Error to subscribe topic=%s, qos=%d", topic, qos); + return -1; + } + + ESP_LOGD(MQTT_TAG, "Sent subscribe topic=%s, id: %d, type=%d successful", topic, client->mqtt_state.pending_msg_id, client->mqtt_state.pending_msg_type); + return client->mqtt_state.pending_msg_id; +} + +int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic) +{ + if (client->state != MQTT_STATE_CONNECTED) { + ESP_LOGE(MQTT_TAG, "Client has not connected"); + return -1; + } + mqtt_enqueue(client); + client->mqtt_state.outbound_message = mqtt_msg_unsubscribe(&client->mqtt_state.mqtt_connection, + topic, + &client->mqtt_state.pending_msg_id); + ESP_LOGD(MQTT_TAG, "unsubscribe, topic\"%s\", id: %d", topic, client->mqtt_state.pending_msg_id); + + client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); + client->mqtt_state.pending_msg_count ++; + + if (mqtt_write_data(client) != ESP_OK) { + ESP_LOGE(MQTT_TAG, "Error to unsubscribe topic=%s", topic); + return -1; + } + + ESP_LOGD(MQTT_TAG, "Sent Unsubscribe topic=%s, id: %d, successful", topic, client->mqtt_state.pending_msg_id); + return client->mqtt_state.pending_msg_id; +} + +int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain) +{ + uint16_t pending_msg_id = 0; + if (client->state != MQTT_STATE_CONNECTED) { + ESP_LOGE(MQTT_TAG, "Client has not connected"); + return -1; + } + if (len <= 0) { + len = strlen(data); + } + if (qos > 0) { + mqtt_enqueue(client); + } + + client->mqtt_state.outbound_message = mqtt_msg_publish(&client->mqtt_state.mqtt_connection, + topic, data, len, + qos, retain, + &pending_msg_id); + if (qos > 0) { + client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data); + client->mqtt_state.pending_msg_id = pending_msg_id; + client->mqtt_state.pending_msg_count ++; + } + + if (mqtt_write_data(client) != ESP_OK) { + ESP_LOGE(MQTT_TAG, "Error publishing data to topic=%s, qos=%d", topic, qos); + return -1; + } + return pending_msg_id; +} + + diff --git a/MicroPython_BUILD/components/espmqtt/ringbuf.c b/MicroPython_BUILD/components/espmqtt/ringbuf.c deleted file mode 100644 index 5bb4adbe..00000000 --- a/MicroPython_BUILD/components/espmqtt/ringbuf.c +++ /dev/null @@ -1,106 +0,0 @@ -/** -* \file -* Ring Buffer library -*/ -#include -#include -#include "ringbuf.h" - -/** -* \brief init a RINGBUF object -* \param r pointer to a RINGBUF object -* \param buf pointer to a byte array -* \param size size of buf -* \param block_size is size of data as block -* \return 0 if successfull, otherwise failed -*/ -int32_t rb_init(RINGBUF *r, uint8_t* buf, int32_t size, int32_t block_size) -{ - if (r == 0 || buf == 0 || size < 2) return -1; - - if (size % block_size != 0) return -1; - - r->p_o = r->p_r = r->p_w = buf; - r->fill_cnt = 0; - r->size = size; - r->block_size = block_size; - return 0; -} -/** -* \brief put a character into ring buffer -* \param r pointer to a ringbuf object -* \param c character to be put -* \return 0 if successfull, otherwise failed -*/ -int32_t rb_put(RINGBUF *r, uint8_t *c) -{ - int32_t i; - uint8_t *data = c; - if (r->fill_cnt >= r->size) - return -1; // ring buffer is full, this should be atomic operation - - - r->fill_cnt += r->block_size; // increase filled slots count, this should be atomic operation - - for (i = 0; i < r->block_size; i++) { - *r->p_w = *data; // put character into buffer - - r->p_w ++; - data ++; - } - - if (r->p_w >= r->p_o + r->size) // rollback if write pointer go pass - r->p_w = r->p_o; // the physical boundary - - return 0; -} -/** -* \brief get a character from ring buffer -* \param r pointer to a ringbuf object -* \param c read character -* \return 0 if successfull, otherwise failed -*/ -int32_t rb_get(RINGBUF *r, uint8_t *c) -{ - int32_t i; - uint8_t *data = c; - if (r->fill_cnt <= 0)return -1; // ring buffer is empty, this should be atomic operation - - r->fill_cnt -= r->block_size; // decrease filled slots count - - for (i = 0; i < r->block_size; i++) - *data++ = *r->p_r++; // get the character out - - if (r->p_r >= r->p_o + r->size) // rollback if write pointer go pass - r->p_r = r->p_o; // the physical boundary - - return 0; -} - -int32_t rb_available(RINGBUF *r) -{ - return (r->size - r->fill_cnt); -} - -uint32_t rb_read(RINGBUF *r, uint8_t *buf, int len) -{ - int n = 0; - uint8_t data; - while (len > 0) { - while (rb_get(r, &data) != 0); - *buf++ = data; - n ++; - len --; - } - - return n; -} - -uint32_t rb_write(RINGBUF *r, uint8_t *buf, int len) -{ - uint32_t wi; - for (wi = 0; wi < len; wi++) { - while (rb_put(r, &buf[wi]) != 0); - } - return 0; -} diff --git a/MicroPython_BUILD/components/libnmea/.gitignore b/MicroPython_BUILD/components/libnmea/.gitignore new file mode 100644 index 00000000..bbf313b2 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/.gitignore @@ -0,0 +1,32 @@ +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ diff --git a/MicroPython_BUILD/components/libnmea/LICENSE b/MicroPython_BUILD/components/libnmea/LICENSE new file mode 100644 index 00000000..8e4bbc83 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Jack Engqvist Johansson + +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/MicroPython_BUILD/components/libnmea/README.md b/MicroPython_BUILD/components/libnmea/README.md new file mode 100644 index 00000000..9d5868a0 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/README.md @@ -0,0 +1,9 @@ +C Library for Parsing NMEA 0183 Sentences +========================================= + +### This library was modified by LoBo (https://github.com/loboris) + +as part of the [MicroPython ESP32 project](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo) + +from the original [libnmea](https://github.com/jacketizer/libnmea) GitHub repository. + diff --git a/MicroPython_BUILD/components/libnmea/component.mk b/MicroPython_BUILD/components/libnmea/component.mk new file mode 100644 index 00000000..9fbaf871 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/component.mk @@ -0,0 +1,39 @@ +COMPONENT_SUBMODULES := src +COMPONENT_SRCDIRS := src/nmea src/parsers +COMPONENT_ADD_INCLUDEDIRS := src/nmea src/parsers +PARSER_OBJS := $(addprefix src/parsers/,\ + gpgga.o \ + gpgll.o \ + gprmc.o \ + gpgst.o \ + gpvtg.o \ + ) + +COMPONENT_OBJS := $(addprefix src/,\ + nmea/nmea.o \ + nmea/parser_static.o \ + parsers/parse.o \ + ) \ + $(PARSER_OBJS) + +define RENAME_SYMBOLS + $(OBJCOPY) \ + --redefine-sym init=nmea_$(1)_init \ + --redefine-sym parse=nmea_$(1)_parse \ + --redefine-sym set_default=nmea_$(1)_set_default \ + --redefine-sym allocate_data=nmea_$(1)_allocate_data \ + --redefine-sym free_data=nmea_$(1)_free_data \ + src/parsers/$(1).o +endef + +$(COMPONENT_LIBRARY): | rename_symbols + +.PHONY: rename_symbols + +rename_symbols: | $(PARSER_OBJS) + $(call RENAME_SYMBOLS,gpgga) + $(call RENAME_SYMBOLS,gpgll) + $(call RENAME_SYMBOLS,gprmc) + $(call RENAME_SYMBOLS,gpgst) + $(call RENAME_SYMBOLS,gpvtg) + diff --git a/MicroPython_BUILD/components/libnmea/src/nmea/nmea.c b/MicroPython_BUILD/components/libnmea/src/nmea/nmea.c new file mode 100644 index 00000000..b47c2fb6 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/nmea/nmea.c @@ -0,0 +1,303 @@ +#include "nmea.h" +#include "parser.h" +#include "parser_types.h" +#include "esp_log.h" + +#define ARRAY_LENGTH(a) (sizeof a / sizeof (a[0])) + +const char *NMEA_TAG = "NMEA"; + +/** + * Check if a value is not NULL and not empty. + * + * Returns 0 if set, otherwise -1. + */ +//----------------------------------------- +static int _is_value_set(const char *value) +{ + if (NULL == value || '\0' == *value) { + return -1; + } + + return 0; +} + +/** + * Crop a sentence from the type word and checksum. + * + * The type word at the beginning along with the dollar sign ($) will be + * removed. If there is a checksum, it will also be removed. The two end + * characters (usually ) will not be included in the new string. + * + * sentence is a validated NMEA sentence string. + * length is the char length of the sentence string. + * + * Returns pointer (char *) to the new string. + */ +//-------------------------------------------------------- +static char *_crop_sentence(char *sentence, size_t length) +{ + /* Skip type word, 7 characters (including $ and ,) */ + sentence += NMEA_PREFIX_LENGTH + NMEA_ID_LENGTH + 2; + + /* Null terminate before end of line/sentence, 2 characters */ + sentence[length - 9] = '\0'; + + /* Remove checksum, if there is one */ + if ('*' == sentence[length - 12]) { + sentence[length - 12] = '\0'; + } + + return sentence; +} + +/** + * Splits a string by comma. + * + * string is the string to split, will be manipulated. Needs to be + * null-terminated. + * values is a char pointer array that will be filled with pointers to the + * splitted values in the string. + * max_values is the maximum number of values to be parsed. + * + * Returns the number of values found in string. + */ +//---------------------------------------------------------------------------- +static int _split_string_by_comma(char *string, char **values, int max_values) +{ + int i = 0; + + values[i++] = string; + while (i < max_values && NULL != (string = strchr(string, ','))) { + *string = '\0'; + values[i++] = ++string; + } + + return i; +} + +/** + * Initiate the NMEA library and load the parser modules. + * + * This function will be called before the main() function. + */ +void __attribute__ ((constructor)) nmea_init(void); +//-------------- +void nmea_init() +{ + nmea_load_parsers(); +} + +/** + * Unload the parser modules. + * + * This function will be called after the exit() function. + */ +void __attribute__ ((destructor)) nmea_cleanup(void); +//----------------- +void nmea_cleanup() +{ + nmea_unload_parsers(); +} + +//---------------------------------------- +nmea_t nmea_get_type(const char *sentence) +{ + nmea_parser_module_s *parser = nmea_get_parser_by_sentence(sentence); + if (NULL == parser) { + return NMEA_UNKNOWN; + } + + return parser->parser.type; +} + +//--------------------------------------------- +uint8_t nmea_get_checksum(const char *sentence) +{ + const char *n = sentence + 1; + uint8_t chk = 0; + + /* While current char isn't '*' or sentence ending (newline) */ + while ('*' != *n && NMEA_END_CHAR_1 != *n && '\0' != *n) { + chk ^= (uint8_t) *n; + n++; + } + + return chk; +} + +//-------------------------------------------------------- +int nmea_has_checksum(const char *sentence, size_t length) +{ + if ('*' == sentence[length - 5]) { + return 0; + } + + return -1; +} + +//------------------------------------------------------------------------ +int nmea_validate(const char *sentence, size_t length, int check_checksum) +{ + const char *n; + + /* should have atleast 9 characters */ + if (9 > length) { + ESP_LOGD(NMEA_TAG, "Sentence too short (%d)", length); + return -1; + } + + /* should be less or equal to NMEA_MAX_LENGTH characters */ + if (NMEA_MAX_LENGTH < length) { + ESP_LOGD(NMEA_TAG, "Sentence too long (%d)", length); + return -2; + } + + /* should start with $ */ + if ('$' != *sentence) { + ESP_LOGD(NMEA_TAG, "Sentence not starting with '$'"); + return -3; + } + + /* should end with \r\n, or other... */ + if (NMEA_END_CHAR_2 != sentence[length - 1] || NMEA_END_CHAR_1 != sentence[length - 2]) { + ESP_LOGD(NMEA_TAG, "Sentence does not end with 'CRLF'"); + return -4; + } + + /* should have a 5 letter, upper case word */ + n = sentence; + while (++n < sentence + 6) { + if (*n < 'A' || *n > 'Z') { + /* not upper case letter */ + ESP_LOGD(NMEA_TAG, "Wrong sentence header"); + return -5; + } + } + + /* should have a comma after the type word */ + if (',' != sentence[6]) { + ESP_LOGD(NMEA_TAG, "Wrong sentence header, no comma"); + return -6; + } + + /* test for not allowed characters */ + n = sentence+6; + while (++n < (sentence + length - 2)) { + if ((*n < ' ') || (*n > 'z') || (*n == '$')) { + /* not allowed character */ + ESP_LOGD(NMEA_TAG, "Sentence contains invalid characters"); + return -7; + } + } + + /* check for checksum */ + if (1 == check_checksum && 0 == nmea_has_checksum(sentence, length)) { + uint8_t actual_chk; + uint8_t expected_chk; + char checksum[3]; + + checksum[0] = sentence[length - 4]; + checksum[1] = sentence[length - 3]; + checksum[2] = '\0'; + actual_chk = nmea_get_checksum(sentence); + expected_chk = (uint8_t) strtol(checksum, NULL, 16); + if (expected_chk != actual_chk) { + ESP_LOGD(NMEA_TAG, "Wrong sentence checksum"); + return -8; + } + } + + return 0; +} + +//-------------------------- +void nmea_free(nmea_s *data) +{ + nmea_parser_module_s *parser; + + if (NULL == data) { + return; + } + + parser = nmea_get_parser_by_type(data->type); + if (NULL == parser) { + return; + } + + parser->free_data(data); +} + +//------------------------------------------------------------------- +nmea_s *nmea_parse(char *sentence, size_t length, int check_checksum) +{ + unsigned int n_vals, val_index; + char *value, *val_string; + char *values[255]; + nmea_parser_module_s *parser; + nmea_t type; + int res; + + /* Validate sentence string */ + res = nmea_validate(sentence, length, check_checksum); + if (res < 0) { + ESP_LOGD(NMEA_TAG, "Validate error (%d)", res); + return (nmea_s *) NULL; + } + + type = nmea_get_type(sentence); + if (NMEA_UNKNOWN == type) { + ESP_LOGD(NMEA_TAG, "Get type error"); + return (nmea_s *) NULL; + } + + /* Crop sentence from type word and checksum */ + val_string = _crop_sentence(sentence, length); + if (NULL == val_string) { + ESP_LOGD(NMEA_TAG, "Sentence crop error"); + return (nmea_s *) NULL; + } + + /* Split the sentence into values */ + n_vals = _split_string_by_comma(val_string, values, ARRAY_LENGTH(values)); + if (0 == n_vals) { + ESP_LOGD(NMEA_TAG, "Sentence split error"); + return (nmea_s *) NULL; + } + + /* Get the right parser */ + parser = nmea_get_parser_by_type(type); + if (NULL == parser) { + ESP_LOGD(NMEA_TAG, "Get parser error"); + return (nmea_s *) NULL; + } + + /* Allocate memory for parsed data */ + parser->allocate_data((nmea_parser_s *) parser); + if (NULL == parser->parser.data) { + ESP_LOGD(NMEA_TAG, "Error allocating parser data"); + return (nmea_s *) NULL; + } + + /* Set default values */ + parser->set_default((nmea_parser_s *) parser); + parser->errors = 0; + + /* Loop through the values and parse them... */ + for (val_index = 0; val_index < n_vals; val_index++) { + value = values[val_index]; + if (-1 == _is_value_set(value)) { + continue; + } + + if (-1 == parser->parse((nmea_parser_s *) parser, value, val_index)) { + parser->errors++; + ESP_LOGD(NMEA_TAG, "Parser error at index %d",val_index); + } + } + + parser->parser.data->type = type; + parser->parser.data->errors = parser->errors; + + return parser->parser.data; +} diff --git a/MicroPython_BUILD/components/libnmea/src/nmea/nmea.h b/MicroPython_BUILD/components/libnmea/src/nmea/nmea.h new file mode 100644 index 00000000..4995d220 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/nmea/nmea.h @@ -0,0 +1,127 @@ +#ifndef INC_NMEA_H +#define INC_NMEA_H + +#include +#include +#include + +/* NMEA sentence types */ +typedef enum { + NMEA_UNKNOWN, + NMEA_GGA, + NMEA_GLL, + NMEA_RMC, + NMEA_GST, + NMEA_VTG +} nmea_t; + +/* NMEA cardinal direction types */ +typedef char nmea_cardinal_t; +#define NMEA_CARDINAL_DIR_NORTH (nmea_cardinal_t) 'N' +#define NMEA_CARDINAL_DIR_EAST (nmea_cardinal_t) 'E' +#define NMEA_CARDINAL_DIR_SOUTH (nmea_cardinal_t) 'S' +#define NMEA_CARDINAL_DIR_WEST (nmea_cardinal_t) 'W' +#define NMEA_CARDINAL_DIR_UNKNOWN (nmea_cardinal_t) '\0' + +extern const char *NMEA_TAG; + +/** + * NMEA data base struct + * + * This struct will be extended by the parser data structs (ex: nmea_gpgll_s). + */ +typedef struct { + nmea_t type; + int errors; +} nmea_s; + +/* GPS position struct */ +typedef struct { + double minutes; + int degrees; + nmea_cardinal_t cardinal; +} nmea_position; + +/* NMEA sentence max length, including \r\n (chars) */ +#define NMEA_MAX_LENGTH 83 + +/* NMEA sentence endings, should be \r\n according the NMEA 0183 standard */ +#define NMEA_END_CHAR_1 '\r' +#define NMEA_END_CHAR_2 '\n' + +/* NMEA sentence prefix length (num chars), Ex: GPGLL */ +#define NMEA_PREFIX_LENGTH 3 +#define NMEA_IDS_LENGTH 6 +#define NMEA_ID_LENGTH 2 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the sentence type. + * + * sentence needs to be a validated NMEA sentence string. + * + * Returns nmea_t (int). + */ +extern nmea_t nmea_get_type(const char *sentence); + +/** + * Calculate the checksum of the sentence. + * + * sentence needs to be a validated NMEA sentence string. + * + * Returns the calculated checksum (uint8_t). + */ +extern uint8_t nmea_get_checksum(const char *sentence); + +/** + * Check if the sentence contains a precalculated checksum. + * + * sentence needs to be a validated NMEA sentence string. + * length is the character length of the sentence string. + * + * Return 0 if checksum exists, otherwise -1. + */ +extern int nmea_has_checksum(const char *sentence, size_t length); + +/** + * Validate the sentence according to NMEA 0183. + * + * Criterias: + * - Should be between the correct length. + * - Should start with a dollar sign. + * - The next five characters should be uppercase letters. + * - If it has a checksum, check it. + * - Ends with the correct 2 characters. + * + * length is the character length of the sentence string. + * + * Returns 0 if sentence is valid, otherwise error code (< 0). + */ +extern int nmea_validate(const char *sentence, size_t length, int check_checksum); + +/** + * Free an nmea data struct. + * + * data should be a pointer to a struct of type nmea_s. + */ +extern void nmea_free(nmea_s *data); + +/** + * Parse an NMEA sentence string to a struct. + * + * sentence needs to be a validated NMEA sentence string. + * length is the character length of the sentence string. + * check_checksum, if 1 and there is a checksum, validate it. + * + * Returns a pointer to an NMEA data struct, or (nmea_s *) NULL if an error occurs. + */ +extern nmea_s *nmea_parse(char *sentence, size_t length, int check_checksum); + +#ifdef __cplusplus +} +#endif + +#endif /* INC_NMEA_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/nmea/parser.h b/MicroPython_BUILD/components/libnmea/src/nmea/parser.h new file mode 100644 index 00000000..0b42c096 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/nmea/parser.h @@ -0,0 +1,68 @@ +#ifndef INC_NMEA_PARSER_H +#define INC_NMEA_PARSER_H + +#include +#include +#include "nmea.h" +#include "parser_types.h" + +typedef int (*allocate_data_f) (nmea_parser_s *); +typedef int (*set_default_f) (nmea_parser_s *); +typedef int (*free_data_f) (nmea_s *); +typedef int (*parse_f) (nmea_parser_s *, char *, int); +typedef int (*init_f) (nmea_parser_s *); + +typedef struct { + nmea_parser_s parser; + int errors; + void *handle; + + /* Functions */ + allocate_data_f allocate_data; + set_default_f set_default; + free_data_f free_data; + parse_f parse; +} nmea_parser_module_s; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Load the parser libs into array. + * + * Returns 0 on success, or -1 if an error occurs. + */ +int nmea_load_parsers(); + +/** + * Unload all the parser libs. + */ +void nmea_unload_parsers(); + +/** + * Initiate a parser. + * + * Returns a sentence parser struct, or (nmea_parser_module_s *) NULL if an error occurs. + */ +nmea_parser_module_s * nmea_init_parser(const char *filename); + +/** + * Get a parser for a sentence type. + * + * Returns the sentence parser struct, should be checked for NULL. + */ +nmea_parser_module_s * nmea_get_parser_by_type(nmea_t type); + +/** + * Get a parser for a sentence type by a sentence string. + * + * Returns the sentence parser struct, should be checked for NULL. + */ +nmea_parser_module_s * nmea_get_parser_by_sentence(const char *sentence); + +#ifdef __cplusplus +} +#endif + +#endif /* INC_NMEA_PARSER_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/nmea/parser_static.c b/MicroPython_BUILD/components/libnmea/src/nmea/parser_static.c new file mode 100644 index 00000000..686ba2e4 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/nmea/parser_static.c @@ -0,0 +1,93 @@ +#include "nmea.h" +#include "parser.h" + +#define PARSER_COUNT 5 + +#define DECLARE_PARSER_API(modname) \ + extern int nmea_##modname##_init(nmea_parser_s *parser); \ + extern int nmea_##modname##_allocate_data(nmea_parser_s *parser); \ + extern int nmea_##modname##_set_default(nmea_parser_s *parser); \ + extern int nmea_##modname##_free_data(nmea_s *data); \ + extern int nmea_##modname##_parse(nmea_parser_s *parser, char *value, int val_index); + +#define PARSER_LOAD(modname) \ + parser = &(parsers[i]); \ + parser->handle = NULL; \ + parser->allocate_data = nmea_##modname##_allocate_data; \ + parser->set_default = nmea_##modname##_set_default; \ + parser->free_data = nmea_##modname##_free_data; \ + parser->parse = nmea_##modname##_parse; \ + if (-1 == nmea_##modname##_init((nmea_parser_s *) parser)) { \ + return -1; \ + } \ + i++; + +DECLARE_PARSER_API(gpgll) +DECLARE_PARSER_API(gpgga) +DECLARE_PARSER_API(gprmc) +DECLARE_PARSER_API(gpgst) +DECLARE_PARSER_API(gpvtg) + +nmea_parser_module_s parsers[PARSER_COUNT]; + +//---------------------------------------------------------- +nmea_parser_module_s *nmea_init_parser(const char *filename) +{ + /* This function intentionally returns NULL */ + return NULL; +} + +//--------------------- +int nmea_load_parsers() +{ + int i = 0; + nmea_parser_module_s *parser; + + PARSER_LOAD(gpgll); + PARSER_LOAD(gpgga); + PARSER_LOAD(gprmc); + PARSER_LOAD(gpgst); + PARSER_LOAD(gpvtg); + + return PARSER_COUNT; +} + +//------------------------ +void nmea_unload_parsers() +{ + /* This function body is intentionally left empty, + because there is no dynamic memory allocations. */ +} + +//-------------------------------------------------------- +nmea_parser_module_s *nmea_get_parser_by_type(nmea_t type) +{ + int i; + + for (i = 0; i < PARSER_COUNT; i++) { + if (type == parsers[i].parser.type) { + return &(parsers[i]); + } + } + + return (nmea_parser_module_s *) NULL; +} + +//--------------------------------------------------------------------- +nmea_parser_module_s *nmea_get_parser_by_sentence(const char *sentence) +{ + int i; + + char type_prefix[NMEA_ID_LENGTH+1] = {'\0'}; + memcpy(type_prefix, sentence+1, NMEA_ID_LENGTH); + for (i = 0; i < PARSER_COUNT; i++) { + if (strstr(parsers[i].parser.type_prefixes, type_prefix) == NULL) { + continue; + } + if (0 == strncmp(sentence + NMEA_ID_LENGTH + 1, parsers[i].parser.type_word, NMEA_PREFIX_LENGTH)) { + return &(parsers[i]); + } + } + + return (nmea_parser_module_s *) NULL; +} diff --git a/MicroPython_BUILD/components/libnmea/src/nmea/parser_types.h b/MicroPython_BUILD/components/libnmea/src/nmea/parser_types.h new file mode 100644 index 00000000..19196b0b --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/nmea/parser_types.h @@ -0,0 +1,17 @@ +#ifndef INC_NMEA_PARSER_TYPES_H +#define INC_NMEA_PARSER_TYPES_H + +#include "nmea.h" + +typedef struct { + nmea_t type; + char type_word[4]; + char type_prefixes[7]; + nmea_s *data; +} nmea_parser_s; + +#define NMEA_PARSER_PREFIX(parser, type_prefix) strncpy(parser->type_word, type_prefix, NMEA_PREFIX_LENGTH) +#define NMEA_PARSER_IDS(parser, type_ids) strncpy(parser->type_prefixes, type_ids, NMEA_IDS_LENGTH) +#define NMEA_PARSER_TYPE(parser, nmea_type) parser->type = nmea_type + +#endif /* INC_NMEA_PARSER_TYPES_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpgga.c b/MicroPython_BUILD/components/libnmea/src/parsers/gpgga.c new file mode 100644 index 00000000..192c5525 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpgga.c @@ -0,0 +1,148 @@ +/* ----------------------------- GGA Data Struct ------------------------------ */ + +//GGA - essential fix data which provide 3D location and accuracy data. +// +// $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 +// +//Where: +// GGA Global Positioning System Fix Data +// 123519 Fix taken at 12:35:19 UTC +// 4807.038,N Latitude 48 deg 07.038' N +// 01131.000,E Longitude 11 deg 31.000' E +// 1 Fix quality: 0 = invalid +// 1 = GPS fix (SPS) +// 2 = DGPS fix +// 3 = PPS fix +// 4 = Real Time Kinematic +// 5 = Float RTK +// 6 = estimated (dead reckoning) (2.3 feature) +// 7 = Manual input mode +// 8 = Simulation mode +// 08 Number of satellites being tracked +// 0.9 Horizontal dilution of position +// 545.4,M Altitude, Meters, above mean sea level +// 46.9,M Height of geoid (mean sea level) above WGS84 +// ellipsoid +// (empty field) time in seconds since last DGPS update +// (empty field) DGPS station ID number +// *47 the checksum data, always begins with * +// +// If the height of geoid is missing then the altitude should be suspect. Some non-standard +// implementations report altitude with respect to the ellipsoid rather than geoid altitude. +// Some units do not report negative altitudes at alUART driver interface. This is the only +// sentence that reports altitude. + +#include "../nmea/parser_types.h" +#include "gpgga.h" +#include "parse.h" + +//----------------------------- +int init(nmea_parser_s *parser) +{ + /* Declare what sentence type to parse */ + NMEA_PARSER_TYPE(parser, NMEA_GGA); + NMEA_PARSER_PREFIX(parser, "GGA"); + NMEA_PARSER_IDS(parser, "GPGNGL"); + return 0; +} + +//-------------------------------------- +int allocate_data(nmea_parser_s *parser) +{ + parser->data = malloc(sizeof (nmea_gpgga_s)); + if (NULL == parser->data) { + return -1; + } + + return 0; +} + +//------------------------------------ +int set_default(nmea_parser_s *parser) +{ + memset(parser->data, 0, sizeof (nmea_gpgga_s)); + return 0; +} + +//------------------------- +int free_data(nmea_s *data) +{ + free(data); + return 0; +} + +// Parse Global Positioning System Fix Data sentence +//---------------------------------------------------------- +int parse(nmea_parser_s *parser, char *value, int val_index) +{ + nmea_gpgga_s *data = (nmea_gpgga_s *) parser->data; + + switch (val_index) { + case NMEA_GPGGA_TIME: + /* Parse time */ + if (-1 == nmea_time_parse(value, &data->time)) { + return -1; + } + break; + + case NMEA_GPGGA_LATITUDE: + /* Parse latitude */ + if (-1 == nmea_position_parse(value, &data->latitude)) { + return -1; + } + break; + + case NMEA_GPGGA_LATITUDE_CARDINAL: + /* Parse cardinal direction */ + data->latitude.cardinal = nmea_cardinal_direction_parse(value); + if (NMEA_CARDINAL_DIR_UNKNOWN == data->latitude.cardinal) { + return -1; + } + break; + + case NMEA_GPGGA_LONGITUDE: + /* Parse longitude */ + if (-1 == nmea_position_parse(value, &data->longitude)) { + return -1; + } + break; + + case NMEA_GPGGA_LONGITUDE_CARDINAL: + /* Parse cardinal direction */ + data->longitude.cardinal = nmea_cardinal_direction_parse(value); + if (NMEA_CARDINAL_DIR_UNKNOWN == data->longitude.cardinal) { + return -1; + } + break; + + case NMEA_GPGGA_N_SATELLITES: + /* Parse number of satellies */ + data->n_satellites = atoi(value); + break; + + case NMEA_GPGGA_ALTITUDE: + /* Parse altitude */ + data->altitude = strtof(value, NULL); + break; + + case NMEA_GPGGA_ALTITUDE_UNIT: + /* Parse altitude unit */ + data->altitude_unit = *value; + break; + + case NMEA_GPGGA_QUALITY: + /* GPS Quality Indicator */ + data->quality = (int)strtol(value, NULL, 0); + break; + + case NMEA_GPGGA_DOP: + /* Horizontal Dilution of precision */ + data->dop = strtof(value, NULL); + break; + + default: + break; + } + + return 0; +} diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpgga.h b/MicroPython_BUILD/components/libnmea/src/parsers/gpgga.h new file mode 100644 index 00000000..ef9d8fbf --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpgga.h @@ -0,0 +1,33 @@ +#ifndef INC_NMEA_GPGGA_H +#define INC_NMEA_GPGGA_H + +#include +#include +#include +#include + +typedef struct { + nmea_s base; + struct tm time; + nmea_position longitude; + nmea_position latitude; + int n_satellites; + float altitude; + char altitude_unit; + int quality; + float dop; +} nmea_gpgga_s; + +/* Value indexes */ +#define NMEA_GPGGA_TIME 0 +#define NMEA_GPGGA_LATITUDE 1 +#define NMEA_GPGGA_LATITUDE_CARDINAL 2 +#define NMEA_GPGGA_LONGITUDE 3 +#define NMEA_GPGGA_LONGITUDE_CARDINAL 4 +#define NMEA_GPGGA_QUALITY 5 +#define NMEA_GPGGA_N_SATELLITES 6 +#define NMEA_GPGGA_DOP 7 +#define NMEA_GPGGA_ALTITUDE 8 +#define NMEA_GPGGA_ALTITUDE_UNIT 9 + +#endif /* INC_NMEA_GPGGA_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpgll.c b/MicroPython_BUILD/components/libnmea/src/parsers/gpgll.c new file mode 100644 index 00000000..55177311 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpgll.c @@ -0,0 +1,94 @@ +#include "../nmea/parser_types.h" +#include "gpgll.h" +#include "parse.h" + +//----------------------------- +int init(nmea_parser_s *parser) +{ + /* Declare what sentence type to parse */ + NMEA_PARSER_TYPE(parser, NMEA_GLL); + NMEA_PARSER_PREFIX(parser, "GLL"); + NMEA_PARSER_IDS(parser, "GPGNGL"); + return 0; +} + +//-------------------------------------- +int allocate_data(nmea_parser_s *parser) +{ + parser->data = malloc(sizeof (nmea_gpgll_s)); + if (NULL == parser->data) { + return -1; + } + + return 0; +} + +//------------------------------------ +int set_default(nmea_parser_s *parser) +{ + memset(parser->data, 0, sizeof (nmea_gpgll_s)); + return 0; +} + +//------------------------- +int free_data(nmea_s *data) +{ + free(data); + return 0; +} + +// Parse Geographic Position – Latitude/Longitude sentence +//---------------------------------------------------------- +int parse(nmea_parser_s *parser, char *value, int val_index) +{ + nmea_gpgll_s *data = (nmea_gpgll_s *) parser->data; + + switch (val_index) { + case NMEA_GPGLL_TIME: + /* Parse time */ + if (-1 == nmea_time_parse(value, &data->time)) { + return -1; + } + break; + + case NMEA_GPGLL_LATITUDE: + /* Parse latitude */ + if (-1 == nmea_position_parse(value, &data->latitude)) { + return -1; + } + break; + + case NMEA_GPGLL_LATITUDE_CARDINAL: + /* Parse cardinal direction */ + data->latitude.cardinal = nmea_cardinal_direction_parse(value); + if (NMEA_CARDINAL_DIR_UNKNOWN == data->latitude.cardinal) { + return -1; + } + break; + + case NMEA_GPGLL_LONGITUDE: + /* Parse longitude */ + if (-1 == nmea_position_parse(value, &data->longitude)) { + return -1; + } + break; + + case NMEA_GPGLL_LONGITUDE_CARDINAL: + /* Parse cardinal direction */ + data->longitude.cardinal = nmea_cardinal_direction_parse(value); + if (NMEA_CARDINAL_DIR_UNKNOWN == data->longitude.cardinal) { + return -1; + } + break; + + case NMEA_GPGLL_VALID: + /* Status A - Data Valid, V - Data Invalid */ + data->valid = (strcmp(value, "A") == 0); + break; + + default: + break; + } + + return 0; +} diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpgll.h b/MicroPython_BUILD/components/libnmea/src/parsers/gpgll.h new file mode 100644 index 00000000..fd484683 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpgll.h @@ -0,0 +1,25 @@ +#ifndef INC_NMEA_GPGLL_H +#define INC_NMEA_GPGLL_H + +#include +#include +#include +#include + +typedef struct { + nmea_s base; + nmea_position longitude; + nmea_position latitude; + struct tm time; + uint8_t valid; +} nmea_gpgll_s; + +/* Value indexes */ +#define NMEA_GPGLL_LATITUDE 0 +#define NMEA_GPGLL_LATITUDE_CARDINAL 1 +#define NMEA_GPGLL_LONGITUDE 2 +#define NMEA_GPGLL_LONGITUDE_CARDINAL 3 +#define NMEA_GPGLL_TIME 4 +#define NMEA_GPGLL_VALID 5 + +#endif /* INC_NMEA_GPGLL_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpgst.c b/MicroPython_BUILD/components/libnmea/src/parsers/gpgst.c new file mode 100644 index 00000000..5c3e5caf --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpgst.c @@ -0,0 +1,94 @@ +#include "../nmea/parser_types.h" +#include "gpgst.h" +#include "parse.h" + +//----------------------------- +int init(nmea_parser_s *parser) +{ + /* Declare what sentence type to parse */ + NMEA_PARSER_TYPE(parser, NMEA_GST); + NMEA_PARSER_PREFIX(parser, "GST"); + NMEA_PARSER_IDS(parser, "GPGNGL"); + return 0; +} + +//-------------------------------------- +int allocate_data(nmea_parser_s *parser) +{ + parser->data = malloc(sizeof (nmea_gpgst_s)); + if (NULL == parser->data) { + return -1; + } + + return 0; +} + +//------------------------------------ +int set_default(nmea_parser_s *parser) +{ + memset(parser->data, 0, sizeof (nmea_gpgst_s)); + return 0; +} + +//------------------------- +int free_data(nmea_s *data) +{ + free(data); + return 0; +} + +// Parse Global Positioning System Fix Data sentence +//---------------------------------------------------------- +int parse(nmea_parser_s *parser, char *value, int val_index) +{ + nmea_gpgst_s *data = (nmea_gpgst_s *) parser->data; + + switch (val_index) { + case NMEA_GPGST_TIME: + /* Parse time */ + if (-1 == nmea_time_parse(value, &data->time)) { + return -1; + } + break; + + case NMEA_GPGST_RMSSD: + /* Parse RMS value of the standard deviation of the range inputs */ + data->rmssd = strtof(value, NULL); + break; + + case NMEA_GPGST_SDMAJ: + /* Parse Standard deviation of semi-major axis of error ellipse */ + data->sdmaj = strtof(value, NULL); + break; + + case NMEA_GPGST_SDMIN: + /* Parse Standard deviation of semi-minor axis of error ellipse */ + data->sdmin = strtof(value, NULL); + break; + + case NMEA_GPGST_ORI: + /* Parse Orientation of semi-major axis of error ellipse */ + data->ori = strtof(value, NULL); + break; + + case NMEA_GPGST_LATSD: + /* Parse Standard deviation of latitude error, in meters */ + data->latsd = strtof(value, NULL); + break; + + case NMEA_GPGST_LONSD: + /* Parse Standard deviation of longitude error, in meters */ + data->lonsd = strtof(value, NULL); + break; + + case NMEA_GPGST_ALTSD: + /* Parse Standard deviation of altitude error, in meters */ + data->altsd = strtof(value, NULL); + break; + + default: + break; + } + + return 0; +} diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpgst.h b/MicroPython_BUILD/components/libnmea/src/parsers/gpgst.h new file mode 100644 index 00000000..880be8c2 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpgst.h @@ -0,0 +1,31 @@ +#ifndef INC_NMEA_GPGST_H +#define INC_NMEA_GPGST_H + +#include +#include +#include +#include + +typedef struct { + nmea_s base; + struct tm time; + float rmssd; + float sdmaj; + float sdmin; + float ori; + float latsd; + float lonsd; + float altsd; +} nmea_gpgst_s; + +/* Value indexes */ +#define NMEA_GPGST_TIME 0 +#define NMEA_GPGST_RMSSD 1 +#define NMEA_GPGST_SDMAJ 2 +#define NMEA_GPGST_SDMIN 3 +#define NMEA_GPGST_ORI 4 +#define NMEA_GPGST_LATSD 5 +#define NMEA_GPGST_LONSD 6 +#define NMEA_GPGST_ALTSD 7 + +#endif /* INC_NMEA_GPGGA_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gprmc.c b/MicroPython_BUILD/components/libnmea/src/parsers/gprmc.c new file mode 100644 index 00000000..6add622c --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gprmc.c @@ -0,0 +1,129 @@ +/* ----------------------------- RMC Data Struct ------------------------------ */ + +//RMC - NMEA has its own version of essential gps pvt (position, velocity, time) data. +//It is called RMC, The Recommended Minimum, which will look similar to: +// +//$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A +// +//Where: +// RMC Recommended Minimum sentence C +// 123519 Fix taken at 12:35:19 UTC +// A Status A=active or V=Void. +// 4807.038,N Latitude 48 deg 07.038' N +// 01131.000,E Longitude 11 deg 31.000' E +// 022.4 Speed over the ground in knots +// 084.4 Track angle in degrees True +// 230394 Date - 23rd of March 1994 +// 003.1,W Magnetic Variation +// *6A The checksum data, always begins with * + +#include "../nmea/parser_types.h" +#include "gprmc.h" +#include "parse.h" + +//----------------------------- +int init(nmea_parser_s *parser) +{ + /* Declare what sentence type to parse */ + NMEA_PARSER_TYPE(parser, NMEA_RMC); + NMEA_PARSER_PREFIX(parser, "RMC"); + NMEA_PARSER_IDS(parser, "GPGNGL"); + return 0; +} + +//-------------------------------------- +int allocate_data(nmea_parser_s *parser) +{ + parser->data = malloc(sizeof (nmea_gprmc_s)); + if (NULL == parser->data) { + return -1; + } + + return 0; +} + +//------------------------------------ +int set_default(nmea_parser_s *parser) +{ + memset(parser->data, 0, sizeof (nmea_gprmc_s)); + return 0; +} + +//------------------------- +int free_data(nmea_s *data) +{ + free(data); + return 0; +} + +// Parse Recommended Minimum Navigation Information sentence +//---------------------------------------------------------- +int parse(nmea_parser_s *parser, char *value, int val_index) +{ + nmea_gprmc_s *data = (nmea_gprmc_s *) parser->data; + switch (val_index) { + case NMEA_GPRMC_TIME: + /* Parse time */ + if (-1 == nmea_time_parse(value, &data->time)) { + return -1; + } + break; + + case NMEA_GPRMC_LATITUDE: + /* Parse latitude */ + if (-1 == nmea_position_parse(value, &data->latitude)) { + return -1; + } + break; + + case NMEA_GPRMC_LATITUDE_CARDINAL: + /* Parse cardinal direction */ + data->latitude.cardinal = nmea_cardinal_direction_parse(value); + if (NMEA_CARDINAL_DIR_UNKNOWN == data->latitude.cardinal) { + return -1; + } + break; + + case NMEA_GPRMC_LONGITUDE: + /* Parse longitude */ + if (-1 == nmea_position_parse(value, &data->longitude)) { + return -1; + } + break; + + case NMEA_GPRMC_LONGITUDE_CARDINAL: + /* Parse cardinal direction */ + data->longitude.cardinal = nmea_cardinal_direction_parse(value); + if (NMEA_CARDINAL_DIR_UNKNOWN == data->longitude.cardinal) { + return -1; + } + break; + + case NMEA_GPRMC_DATE: + /* Parse date */ + if (-1 == nmea_date_parse(value, &data->time)) { + return -1; + } + break; + + case NMEA_GPRMC_VALID: + /* Status, V = Navigation receiver warning */ + data->valid = (strcmp(value, "A") == 0); + break; + + case NMEA_GPRMC_SPEED: + /* Speed over ground, knots */ + data->speed = strtof(value, NULL); + break; + + case NMEA_GPRMC_COURSE: + /* Track made good, degrees true */ + data->course = strtof(value, NULL); + break; + + default: + break; + } + + return 0; +} diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gprmc.h b/MicroPython_BUILD/components/libnmea/src/parsers/gprmc.h new file mode 100644 index 00000000..e4804728 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gprmc.h @@ -0,0 +1,30 @@ +#ifndef INC_NMEA_GPRMC_H +#define INC_NMEA_GPRMC_H + +#include +#include +#include +#include + +typedef struct { + nmea_s base; + nmea_position longitude; + nmea_position latitude; + struct tm time; + float speed; + float course; + uint8_t valid; +} nmea_gprmc_s; + +/* Value indexes */ +#define NMEA_GPRMC_TIME 0 +#define NMEA_GPRMC_VALID 1 +#define NMEA_GPRMC_LATITUDE 2 +#define NMEA_GPRMC_LATITUDE_CARDINAL 3 +#define NMEA_GPRMC_LONGITUDE 4 +#define NMEA_GPRMC_LONGITUDE_CARDINAL 5 +#define NMEA_GPRMC_SPEED 6 +#define NMEA_GPRMC_COURSE 7 +#define NMEA_GPRMC_DATE 8 + +#endif /* INC_NMEA_GPRMC_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpvtg.c b/MicroPython_BUILD/components/libnmea/src/parsers/gpvtg.c new file mode 100644 index 00000000..4202fe16 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpvtg.c @@ -0,0 +1,100 @@ +/* ----------------------------- VTG Data Struct ------------------------------ */ + +/* + Track Made Good and Ground Speed. + + eg1. $GPVTG,360.0,T,348.7,M,000.0,N,000.0,K*43 + eg2. $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K + + + 054.7,T True track made good + 034.4,M Magnetic track made good + 005.5,N Ground speed, knots + 010.2,K Ground speed, Kilometers per hour + + + eg3. $GPVTG,t,T,,,s.ss,N,s.ss,K*hh + 1 = Track made good + 2 = Fixed text 'T' indicates that track made good is relative to true north + 3 = not used + 4 = not used + 5 = Speed over ground in knots + 6 = Fixed text 'N' indicates that speed over ground in in knots + 7 = Speed over ground in kilometers/hour + 8 = Fixed text 'K' indicates that speed over ground is in kilometers/hour + 9 = Checksum + The actual track made good and speed relative to the ground. + + $--VTG,x.x,T,x.x,M,x.x,N,x.x,K + x.x,T = Track, degrees True + x.x,M = Track, degrees Magnetic + x.x,N = Speed, knots + x.x,K = Speed, Km/hr + */ + +#include "../nmea/parser_types.h" +#include "gpvtg.h" +#include "parse.h" + +//----------------------------- +int init(nmea_parser_s *parser) +{ + /* Declare what sentence type to parse */ + NMEA_PARSER_TYPE(parser, NMEA_VTG); + NMEA_PARSER_PREFIX(parser, "VTG"); + NMEA_PARSER_IDS(parser, "GPGNGL"); + return 0; +} + +//-------------------------------------- +int allocate_data(nmea_parser_s *parser) +{ + parser->data = malloc(sizeof (nmea_gpvtg_s)); + if (NULL == parser->data) { + return -1; + } + + return 0; +} + +//------------------------------------ +int set_default(nmea_parser_s *parser) +{ + memset(parser->data, 0, sizeof (nmea_gpvtg_s)); + return 0; +} + +//------------------------- +int free_data(nmea_s *data) +{ + free(data); + return 0; +} + +// Parse Recommended Minimum Navigation Information sentence +//---------------------------------------------------------- +int parse(nmea_parser_s *parser, char *value, int val_index) +{ + nmea_gpvtg_s *data = (nmea_gpvtg_s *) parser->data; + switch (val_index) { + case NMEA_GPVTG_COURSE: + /* Track made good */ + data->course = strtof(value, NULL); + break; + + case NMEA_GPVTG_SPEED_KNOTS: + /* Speed over ground in knots */ + data->speed_kn = strtof(value, NULL); + break; + + case NMEA_GPVTG_SPEED_KMH: + /* Speed over ground in km/h */ + data->speed_kmh = strtof(value, NULL); + break; + + default: + break; + } + + return 0; +} diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/gpvtg.h b/MicroPython_BUILD/components/libnmea/src/parsers/gpvtg.h new file mode 100644 index 00000000..ebf99db1 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/gpvtg.h @@ -0,0 +1,21 @@ +#ifndef INC_NMEA_GPVTG_H +#define INC_NMEA_GPVTG_H + +#include +#include +#include +#include + +typedef struct { + nmea_s base; + float course; + float speed_kn; + float speed_kmh; +} nmea_gpvtg_s; + +/* Value indexes */ +#define NMEA_GPVTG_COURSE 0 +#define NMEA_GPVTG_SPEED_KNOTS 4 +#define NMEA_GPVTG_SPEED_KMH 6 + +#endif /* INC_NMEA_GPVTG_H */ diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/parse.c b/MicroPython_BUILD/components/libnmea/src/parsers/parse.c new file mode 100644 index 00000000..0b119160 --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/parse.c @@ -0,0 +1,96 @@ +#include "parse.h" +#include + +//-------------------------------------------------- +int nmea_position_parse(char *s, nmea_position *pos) +{ + char *cursor; + + pos->degrees = 0; + pos->minutes = 0; + + if (s == NULL || *s == '\0') { + return -1; + } + + /* decimal minutes */ + if (NULL == (cursor = strchr(s, '.'))) { + return -1; + } + + /* minutes starts 2 digits before dot */ + cursor -= 2; + pos->minutes = atof(cursor); + *cursor = '\0'; + + /* integer degrees */ + cursor = s; + pos->degrees = atoi(cursor); + + return 0; +} + +//---------------------------------------------------- +nmea_cardinal_t nmea_cardinal_direction_parse(char *s) +{ + if (NULL == s || '\0'== *s) { + return NMEA_CARDINAL_DIR_UNKNOWN; + } + + switch (*s) { + case NMEA_CARDINAL_DIR_NORTH: + return NMEA_CARDINAL_DIR_NORTH; + case NMEA_CARDINAL_DIR_EAST: + return NMEA_CARDINAL_DIR_EAST; + case NMEA_CARDINAL_DIR_SOUTH: + return NMEA_CARDINAL_DIR_SOUTH; + case NMEA_CARDINAL_DIR_WEST: + return NMEA_CARDINAL_DIR_WEST; + default: + break; + } + + return NMEA_CARDINAL_DIR_UNKNOWN; +} + +//------------------------------------------- +int nmea_time_parse(char *s, struct tm *time) +{ + char *rv; + + memset(time, 0, sizeof (struct tm)); + + if (s == NULL || *s == '\0') { + return -1; + } + + char ss[NMEA_TIME_FORMAT_LEN+3]; + sprintf(ss, "%.2s:%.2s:%.2s", s, s+2, s+4); + rv = strptime(ss, "%H:%M:%S", time); + if (NULL == rv || (int) (rv - ss) != NMEA_TIME_FORMAT_LEN+2) { + return -1; + } + return 0; +} + +//------------------------------------------- +int nmea_date_parse(char *s, struct tm *time) +{ + char *rv; + + // Assume it has been already cleared + // memset(time, 0, sizeof (struct tm)); + + if (s == NULL || *s == '\0') { + return -1; + } + + char ss[NMEA_DATE_FORMAT_LEN+3]; + sprintf(ss, "%.2s/%.2s/%.2s", s, s+2, s+4); + rv = strptime(ss, "%d/%m/%y", time); + if (NULL == rv || (int) (rv - ss) != NMEA_DATE_FORMAT_LEN+2) { + return -1; + } + + return 0; +} diff --git a/MicroPython_BUILD/components/libnmea/src/parsers/parse.h b/MicroPython_BUILD/components/libnmea/src/parsers/parse.h new file mode 100644 index 00000000..f36037cb --- /dev/null +++ b/MicroPython_BUILD/components/libnmea/src/parsers/parse.h @@ -0,0 +1,65 @@ +#ifndef INC_NMEA_PARSE_H +#define INC_NMEA_PARSE_H + +#define _XOPEN_SOURCE /* glibc2 needs this */ +#include +#include +#include +#include "../nmea/nmea.h" + +#define NMEA_TIME_FORMAT "%H%M%S" +#define NMEA_TIME_FORMAT_LEN 6 + +#define NMEA_DATE_FORMAT "%d%m%y" +#define NMEA_DATE_FORMAT_LEN 6 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Parse GPS position longitude or latitude + * + * s string containing the position. Ex: "4712.55", 47 degrees and + * 12.55 minutes. Will be modified. + * pos is a pointer to a nmea_position struct where the result should be stored. + * + * Returns 0 on success, otherwise -1. + */ +int nmea_position_parse(char *s, nmea_position *pos); + +/** + * Parse cardinal direction + * + * s is a string containing the letter representing the cardinal direction. + * + * Returns the cardinal direction (nmea_cardinal_t). On failure, + * NMEA_CARDINAL_DIR_UNKNOWN is returned. + */ +nmea_cardinal_t nmea_cardinal_direction_parse(char *s); + +/** + * Parse time from a string + * + * s is a string containing the time in format "HHMMSS". + * time is a pointer to a tm struct where the parser time will be stored. + * + * Returns 0 on success, otherwise -1. + */ +int nmea_time_parse(char *s, struct tm *time); + +/** + * Parse date from a string + * + * s is a string containing the time in format "DDMMYY". + * time is a pointer to a tm struct where the parser date will be stored. + * + * Returns 0 on success, otherwise -1. + */ +int nmea_date_parse(char *s, struct tm *time); + +#ifdef __cplusplus +} +#endif + +#endif /* INC_NMEA_PARSE_H */ diff --git a/MicroPython_BUILD/components/littlefs/DESIGN.md b/MicroPython_BUILD/components/littlefs/DESIGN.md new file mode 100644 index 00000000..3afb0a20 --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/DESIGN.md @@ -0,0 +1,1226 @@ +## The design of the little filesystem + +A little fail-safe filesystem designed for embedded systems. + +``` + | | | .---._____ + .-----. | | +--|o |---| littlefs | +--| |---| | + '-----' '----------' + | | | +``` + +For a bit of backstory, the littlefs was developed with the goal of learning +more about filesystem design by tackling the relative unsolved problem of +managing a robust filesystem resilient to power loss on devices +with limited RAM and ROM. + +The embedded systems the littlefs is targeting are usually 32 bit +microcontrollers with around 32KB of RAM and 512KB of ROM. These are +often paired with SPI NOR flash chips with about 4MB of flash storage. + +Flash itself is a very interesting piece of technology with quite a bit of +nuance. Unlike most other forms of storage, writing to flash requires two +operations: erasing and programming. The programming operation is relatively +cheap, and can be very granular. For NOR flash specifically, byte-level +programs are quite common. Erasing, however, requires an expensive operation +that forces the state of large blocks of memory to reset in a destructive +reaction that gives flash its name. The [Wikipedia entry](https://en.wikipedia.org/wiki/Flash_memory) +has more information if you are interested in how this works. + +This leaves us with an interesting set of limitations that can be simplified +to three strong requirements: + +1. **Power-loss resilient** - This is the main goal of the littlefs and the + focus of this project. + + Embedded systems are usually designed without a shutdown routine and a + notable lack of user interface for recovery, so filesystems targeting + embedded systems must be prepared to lose power at any given time. + + Despite this state of things, there are very few embedded filesystems that + handle power loss in a reasonable manner, and most can become corrupted if + the user is unlucky enough. + +2. **Wear leveling** - Due to the destructive nature of flash, most flash + chips have a limited number of erase cycles, usually in the order of around + 100,000 erases per block for NOR flash. Filesystems that don't take wear + into account can easily burn through blocks used to store frequently updated + metadata. + + Consider the [FAT filesystem](https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system), + which stores a file allocation table (FAT) at a specific offset from the + beginning of disk. Every block allocation will update this table, and after + 100,000 updates, the block will likely go bad, rendering the filesystem + unusable even if there are many more erase cycles available on the storage + as a whole. + +3. **Bounded RAM/ROM** - Even with the design difficulties presented by the + previous two limitations, we have already seen several flash filesystems + developed on PCs that handle power loss just fine, such as the + logging filesystems. However, these filesystems take advantage of the + relatively cheap access to RAM, and use some rather... opportunistic... + techniques, such as reconstructing the entire directory structure in RAM. + These operations make perfect sense when the filesystem's only concern is + erase cycles, but the idea is a bit silly on embedded systems. + + To cater to embedded systems, the littlefs has the simple limitation of + using only a bounded amount of RAM and ROM. That is, no matter what is + written to the filesystem, and no matter how large the underlying storage + is, the littlefs will always use the same amount of RAM and ROM. This + presents a very unique challenge, and makes presumably simple operations, + such as iterating through the directory tree, surprisingly difficult. + +## Existing designs? + +There are of course, many different existing filesystem. Here is a very rough +summary of the general ideas behind some of them. + +Most of the existing filesystems fall into the one big category of filesystem +designed in the early days of spinny magnet disks. While there is a vast amount +of interesting technology and ideas in this area, the nature of spinny magnet +disks encourage properties, such as grouping writes near each other, that don't +make as much sense on recent storage types. For instance, on flash, write +locality is not important and can actually increase wear. + +One of the most popular designs for flash filesystems is called the +[logging filesystem](https://en.wikipedia.org/wiki/Log-structured_file_system). +The flash filesystems [jffs](https://en.wikipedia.org/wiki/JFFS) +and [yaffs](https://en.wikipedia.org/wiki/YAFFS) are good examples. In a +logging filesystem, data is not stored in a data structure on disk, but instead +the changes to the files are stored on disk. This has several neat advantages, +such as the fact that the data is written in a cyclic log format and naturally +wear levels as a side effect. And, with a bit of error detection, the entire +filesystem can easily be designed to be resilient to power loss. The +journaling component of most modern day filesystems is actually a reduced +form of a logging filesystem. However, logging filesystems have a difficulty +scaling as the size of storage increases. And most filesystems compensate by +caching large parts of the filesystem in RAM, a strategy that is inappropriate +for embedded systems. + +Another interesting filesystem design technique is that of [copy-on-write (COW)](https://en.wikipedia.org/wiki/Copy-on-write). +A good example of this is the [btrfs](https://en.wikipedia.org/wiki/Btrfs) +filesystem. COW filesystems can easily recover from corrupted blocks and have +natural protection against power loss. However, if they are not designed with +wear in mind, a COW filesystem could unintentionally wear down the root block +where the COW data structures are synchronized. + +## Metadata pairs + +The core piece of technology that provides the backbone for the littlefs is +the concept of metadata pairs. The key idea here is that any metadata that +needs to be updated atomically is stored on a pair of blocks tagged with +a revision count and checksum. Every update alternates between these two +pairs, so that at any time there is always a backup containing the previous +state of the metadata. + +Consider a small example where each metadata pair has a revision count, +a number as data, and the XOR of the block as a quick checksum. If +we update the data to a value of 9, and then to a value of 5, here is +what the pair of blocks may look like after each update: +``` + block 1 block 2 block 1 block 2 block 1 block 2 +.---------.---------. .---------.---------. .---------.---------. +| rev: 1 | rev: 0 | | rev: 1 | rev: 2 | | rev: 3 | rev: 2 | +| data: 3 | data: 0 | -> | data: 3 | data: 9 | -> | data: 5 | data: 9 | +| xor: 2 | xor: 0 | | xor: 2 | xor: 11 | | xor: 6 | xor: 11 | +'---------'---------' '---------'---------' '---------'---------' + let data = 9 let data = 5 +``` + +After each update, we can find the most up to date value of data by looking +at the revision count. + +Now consider what the blocks may look like if we suddenly lose power while +changing the value of data to 5: +``` + block 1 block 2 block 1 block 2 block 1 block 2 +.---------.---------. .---------.---------. .---------.---------. +| rev: 1 | rev: 0 | | rev: 1 | rev: 2 | | rev: 3 | rev: 2 | +| data: 3 | data: 0 | -> | data: 3 | data: 9 | -x | data: 3 | data: 9 | +| xor: 2 | xor: 0 | | xor: 2 | xor: 11 | | xor: 2 | xor: 11 | +'---------'---------' '---------'---------' '---------'---------' + let data = 9 let data = 5 + powerloss!!! +``` + +In this case, block 1 was partially written with a new revision count, but +the littlefs hadn't made it to updating the value of data. However, if we +check our checksum we notice that block 1 was corrupted. So we fall back to +block 2 and use the value 9. + +Using this concept, the littlefs is able to update metadata blocks atomically. +There are a few other tweaks, such as using a 32 bit CRC and using sequence +arithmetic to handle revision count overflow, but the basic concept +is the same. These metadata pairs define the backbone of the littlefs, and the +rest of the filesystem is built on top of these atomic updates. + +## Non-meta data + +Now, the metadata pairs do come with some drawbacks. Most notably, each pair +requires two blocks for each block of data. I'm sure users would be very +unhappy if their storage was suddenly cut in half! Instead of storing +everything in these metadata blocks, the littlefs uses a COW data structure +for files which is in turn pointed to by a metadata block. When +we update a file, we create copies of any blocks that are modified until +the metadata blocks are updated with the new copy. Once the metadata block +points to the new copy, we deallocate the old blocks that are no longer in use. + +Here is what updating a one-block file may look like: +``` + block 1 block 2 block 1 block 2 block 1 block 2 +.---------.---------. .---------.---------. .---------.---------. +| rev: 1 | rev: 0 | | rev: 1 | rev: 0 | | rev: 1 | rev: 2 | +| file: 4 | file: 0 | -> | file: 4 | file: 0 | -> | file: 4 | file: 5 | +| xor: 5 | xor: 0 | | xor: 5 | xor: 0 | | xor: 5 | xor: 7 | +'---------'---------' '---------'---------' '---------'---------' + | | | + v v v + block 4 block 4 block 5 block 4 block 5 +.--------. .--------. .--------. .--------. .--------. +| old | | old | | new | | old | | new | +| data | | data | | data | | data | | data | +| | | | | | | | | | +'--------' '--------' '--------' '--------' '--------' + update data in file update metadata pair +``` + +It doesn't matter if we lose power while writing new data to block 5, +since the old data remains unmodified in block 4. This example also +highlights how the atomic updates of the metadata blocks provide a +synchronization barrier for the rest of the littlefs. + +At this point, it may look like we are wasting an awfully large amount +of space on the metadata. Just looking at that example, we are using +three blocks to represent a file that fits comfortably in one! So instead +of giving each file a metadata pair, we actually store the metadata for +all files contained in a single directory in a single metadata block. + +Now we could just leave files here, copying the entire file on write +provides the synchronization without the duplicated memory requirements +of the metadata blocks. However, we can do a bit better. + +## CTZ skip-lists + +There are many different data structures for representing the actual +files in filesystems. Of these, the littlefs uses a rather unique [COW](https://upload.wikimedia.org/wikipedia/commons/0/0c/Cow_female_black_white.jpg) +data structure that allows the filesystem to reuse unmodified parts of the +file without additional metadata pairs. + +First lets consider storing files in a simple linked-list. What happens when we +append a block? We have to change the last block in the linked-list to point +to this new block, which means we have to copy out the last block, and change +the second-to-last block, and then the third-to-last, and so on until we've +copied out the entire file. + +``` +Exhibit A: A linked-list +.--------. .--------. .--------. .--------. .--------. .--------. +| data 0 |->| data 1 |->| data 2 |->| data 4 |->| data 5 |->| data 6 | +| | | | | | | | | | | | +| | | | | | | | | | | | +'--------' '--------' '--------' '--------' '--------' '--------' +``` + +To get around this, the littlefs, at its heart, stores files backwards. Each +block points to its predecessor, with the first block containing no pointers. +If you think about for a while, it starts to make a bit of sense. Appending +blocks just point to their predecessor and no other blocks need to be updated. +If we update a block in the middle, we will need to copy out the blocks that +follow, but can reuse the blocks before the modified block. Since most file +operations either reset the file each write or append to files, this design +avoids copying the file in the most common cases. + +``` +Exhibit B: A backwards linked-list +.--------. .--------. .--------. .--------. .--------. .--------. +| data 0 |<-| data 1 |<-| data 2 |<-| data 4 |<-| data 5 |<-| data 6 | +| | | | | | | | | | | | +| | | | | | | | | | | | +'--------' '--------' '--------' '--------' '--------' '--------' +``` + +However, a backwards linked-list does come with a rather glaring problem. +Iterating over a file _in order_ has a runtime cost of O(n^2). Gah! A quadratic +runtime to just _read_ a file? That's awful. Keep in mind reading files is +usually the most common filesystem operation. + +To avoid this problem, the littlefs uses a multilayered linked-list. For +every nth block where n is divisible by 2^x, the block contains a pointer +to block n-2^x. So each block contains anywhere from 1 to log2(n) pointers +that skip to various sections of the preceding list. If you're familiar with +data-structures, you may have recognized that this is a type of deterministic +skip-list. + +The name comes from the use of the +[count trailing zeros (CTZ)](https://en.wikipedia.org/wiki/Count_trailing_zeros) +instruction, which allows us to calculate the power-of-two factors efficiently. +For a given block n, the block contains ctz(n)+1 pointers. + +``` +Exhibit C: A backwards CTZ skip-list +.--------. .--------. .--------. .--------. .--------. .--------. +| data 0 |<-| data 1 |<-| data 2 |<-| data 3 |<-| data 4 |<-| data 5 | +| |<-| |--| |<-| |--| | | | +| |<-| |--| |--| |--| | | | +'--------' '--------' '--------' '--------' '--------' '--------' +``` + +The additional pointers allow us to navigate the data-structure on disk +much more efficiently than in a singly linked-list. + +Taking exhibit C for example, here is the path from data block 5 to data +block 1. You can see how data block 3 was completely skipped: +``` +.--------. .--------. .--------. .--------. .--------. .--------. +| data 0 | | data 1 |<-| data 2 | | data 3 | | data 4 |<-| data 5 | +| | | | | |<-| |--| | | | +| | | | | | | | | | | | +'--------' '--------' '--------' '--------' '--------' '--------' +``` + +The path to data block 0 is even more quick, requiring only two jumps: +``` +.--------. .--------. .--------. .--------. .--------. .--------. +| data 0 | | data 1 | | data 2 | | data 3 | | data 4 |<-| data 5 | +| | | | | | | | | | | | +| |<-| |--| |--| |--| | | | +'--------' '--------' '--------' '--------' '--------' '--------' +``` + +We can find the runtime complexity by looking at the path to any block from +the block containing the most pointers. Every step along the path divides +the search space for the block in half. This gives us a runtime of O(log n). +To get to the block with the most pointers, we can perform the same steps +backwards, which puts the runtime at O(2 log n) = O(log n). The interesting +part about this data structure is that this optimal path occurs naturally +if we greedily choose the pointer that covers the most distance without passing +our target block. + +So now we have a representation of files that can be appended trivially with +a runtime of O(1), and can be read with a worst case runtime of O(n log n). +Given that the the runtime is also divided by the amount of data we can store +in a block, this is pretty reasonable. + +Unfortunately, the CTZ skip-list comes with a few questions that aren't +straightforward to answer. What is the overhead? How do we handle more +pointers than we can store in a block? How do we store the skip-list in +a directory entry? + +One way to find the overhead per block is to look at the data structure as +multiple layers of linked-lists. Each linked-list skips twice as many blocks +as the previous linked-list. Another way of looking at it is that each +linked-list uses half as much storage per block as the previous linked-list. +As we approach infinity, the number of pointers per block forms a geometric +series. Solving this geometric series gives us an average of only 2 pointers +per block. + +![overhead_per_block](https://latex.codecogs.com/svg.latex?%5Clim_%7Bn%5Cto%5Cinfty%7D%5Cfrac%7B1%7D%7Bn%7D%5Csum_%7Bi%3D0%7D%5E%7Bn%7D%5Cleft%28%5Ctext%7Bctz%7D%28i%29+1%5Cright%29%20%3D%20%5Csum_%7Bi%3D0%7D%5Cfrac%7B1%7D%7B2%5Ei%7D%20%3D%202) + +Finding the maximum number of pointers in a block is a bit more complicated, +but since our file size is limited by the integer width we use to store the +size, we can solve for it. Setting the overhead of the maximum pointers equal +to the block size we get the following equation. Note that a smaller block size +results in more pointers, and a larger word width results in larger pointers. + +![maximum overhead](https://latex.codecogs.com/svg.latex?B%20%3D%20%5Cfrac%7Bw%7D%7B8%7D%5Cleft%5Clceil%5Clog_2%5Cleft%28%5Cfrac%7B2%5Ew%7D%7BB-2%5Cfrac%7Bw%7D%7B8%7D%7D%5Cright%29%5Cright%5Crceil) + +where: +B = block size in bytes +w = word width in bits + +Solving the equation for B gives us the minimum block size for various word +widths: +32 bit CTZ skip-list = minimum block size of 104 bytes +64 bit CTZ skip-list = minimum block size of 448 bytes + +Since littlefs uses a 32 bit word size, we are limited to a minimum block +size of 104 bytes. This is a perfectly reasonable minimum block size, with most +block sizes starting around 512 bytes. So we can avoid additional logic to +avoid overflowing our block's capacity in the CTZ skip-list. + +So, how do we store the skip-list in a directory entry? A naive approach would +be to store a pointer to the head of the skip-list, the length of the file +in bytes, the index of the head block in the skip-list, and the offset in the +head block in bytes. However this is a lot of information, and we can observe +that a file size maps to only one block index + offset pair. So it should be +sufficient to store only the pointer and file size. + +But there is one problem, calculating the block index + offset pair from a +file size doesn't have an obvious implementation. + +We can start by just writing down an equation. The first idea that comes to +mind is to just use a for loop to sum together blocks until we reach our +file size. We can write this equation as a summation: + +![summation1](https://latex.codecogs.com/svg.latex?N%20%3D%20%5Csum_i%5En%5Cleft%5BB-%5Cfrac%7Bw%7D%7B8%7D%5Cleft%28%5Ctext%7Bctz%7D%28i%29+1%5Cright%29%5Cright%5D) + +where: +B = block size in bytes +w = word width in bits +n = block index in skip-list +N = file size in bytes + +And this works quite well, but is not trivial to calculate. This equation +requires O(n) to compute, which brings the entire runtime of reading a file +to O(n^2 log n). Fortunately, the additional O(n) does not need to touch disk, +so it is not completely unreasonable. But if we could solve this equation into +a form that is easily computable, we can avoid a big slowdown. + +Unfortunately, the summation of the CTZ instruction presents a big challenge. +How would you even begin to reason about integrating a bitwise instruction? +Fortunately, there is a powerful tool I've found useful in these situations: +The [On-Line Encyclopedia of Integer Sequences (OEIS)](https://oeis.org/). +If we work out the first couple of values in our summation, we find that CTZ +maps to [A001511](https://oeis.org/A001511), and its partial summation maps +to [A005187](https://oeis.org/A005187), and surprisingly, both of these +sequences have relatively trivial equations! This leads us to a rather +unintuitive property: + +![mindblown](https://latex.codecogs.com/svg.latex?%5Csum_i%5En%5Cleft%28%5Ctext%7Bctz%7D%28i%29+1%5Cright%29%20%3D%202n-%5Ctext%7Bpopcount%7D%28n%29) + +where: +ctz(x) = the number of trailing bits that are 0 in x +popcount(x) = the number of bits that are 1 in x + +It's a bit bewildering that these two seemingly unrelated bitwise instructions +are related by this property. But if we start to dissect this equation we can +see that it does hold. As n approaches infinity, we do end up with an average +overhead of 2 pointers as we find earlier. And popcount seems to handle the +error from this average as it accumulates in the CTZ skip-list. + +Now we can substitute into the original equation to get a trivial equation +for a file size: + +![summation2](https://latex.codecogs.com/svg.latex?N%20%3D%20Bn%20-%20%5Cfrac%7Bw%7D%7B8%7D%5Cleft%282n-%5Ctext%7Bpopcount%7D%28n%29%5Cright%29) + +Unfortunately, we're not quite done. The popcount function is non-injective, +so we can only find the file size from the block index, not the other way +around. However, we can solve for an n' block index that is greater than n +with an error bounded by the range of the popcount function. We can then +repeatedly substitute this n' into the original equation until the error +is smaller than the integer division. As it turns out, we only need to +perform this substitution once. Now we directly calculate our block index: + +![formulaforn](https://latex.codecogs.com/svg.latex?n%20%3D%20%5Cleft%5Clfloor%5Cfrac%7BN-%5Cfrac%7Bw%7D%7B8%7D%5Cleft%28%5Ctext%7Bpopcount%7D%5Cleft%28%5Cfrac%7BN%7D%7BB-2%5Cfrac%7Bw%7D%7B8%7D%7D-1%5Cright%29+2%5Cright%29%7D%7BB-2%5Cfrac%7Bw%7D%7B8%7D%7D%5Cright%5Crfloor) + +Now that we have our block index n, we can just plug it back into the above +equation to find the offset. However, we do need to rearrange the equation +a bit to avoid integer overflow: + +![formulaforoff](https://latex.codecogs.com/svg.latex?%5Cmathit%7Boff%7D%20%3D%20N%20-%20%5Cleft%28B-2%5Cfrac%7Bw%7D%7B8%7D%5Cright%29n%20-%20%5Cfrac%7Bw%7D%7B8%7D%5Ctext%7Bpopcount%7D%28n%29) + +The solution involves quite a bit of math, but computers are very good at math. +Now we can solve for both the block index and offset from the file size in O(1). + +Here is what it might look like to update a file stored with a CTZ skip-list: +``` + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 0 | + | file: 6 | file: 0 | + | size: 4 | size: 0 | + | xor: 3 | xor: 0 | + '---------'---------' + | + v + block 3 block 4 block 5 block 6 +.--------. .--------. .--------. .--------. +| data 0 |<-| data 1 |<-| data 2 |<-| data 3 | +| |<-| |--| | | | +| | | | | | | | +'--------' '--------' '--------' '--------' + +| update data in file +v + + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 0 | + | file: 6 | file: 0 | + | size: 4 | size: 0 | + | xor: 3 | xor: 0 | + '---------'---------' + | + v + block 3 block 4 block 5 block 6 +.--------. .--------. .--------. .--------. +| data 0 |<-| data 1 |<-| old |<-| old | +| |<-| |--| data 2 | | data 3 | +| | | | | | | | +'--------' '--------' '--------' '--------' + ^ ^ ^ + | | | block 7 block 8 block 9 block 10 + | | | .--------. .--------. .--------. .--------. + | | '----| new |<-| new |<-| new |<-| new | + | '----------------| data 2 |<-| data 3 |--| data 4 | | data 5 | + '------------------| |--| |--| | | | + '--------' '--------' '--------' '--------' + +| update metadata pair +v + + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 2 | + | file: 6 | file: 10| + | size: 4 | size: 6 | + | xor: 3 | xor: 14 | + '---------'---------' + | + | + block 3 block 4 block 5 block 6 | +.--------. .--------. .--------. .--------. | +| data 0 |<-| data 1 |<-| old |<-| old | | +| |<-| |--| data 2 | | data 3 | | +| | | | | | | | | +'--------' '--------' '--------' '--------' | + ^ ^ ^ v + | | | block 7 block 8 block 9 block 10 + | | | .--------. .--------. .--------. .--------. + | | '----| new |<-| new |<-| new |<-| new | + | '----------------| data 2 |<-| data 3 |--| data 4 | | data 5 | + '------------------| |--| |--| | | | + '--------' '--------' '--------' '--------' +``` + +## Block allocation + +So those two ideas provide the grounds for the filesystem. The metadata pairs +give us directories, and the CTZ skip-lists give us files. But this leaves +one big [elephant](https://upload.wikimedia.org/wikipedia/commons/3/37/African_Bush_Elephant.jpg) +of a question. How do we get those blocks in the first place? + +One common strategy is to store unallocated blocks in a big free list, and +initially the littlefs was designed with this in mind. By storing a reference +to the free list in every single metadata pair, additions to the free list +could be updated atomically at the same time the replacement blocks were +stored in the metadata pair. During boot, every metadata pair had to be +scanned to find the most recent free list, but once the list was found the +state of all free blocks becomes known. + +However, this approach had several issues: + +- There was a lot of nuanced logic for adding blocks to the free list without + modifying the blocks, since the blocks remain active until the metadata is + updated. +- The free list had to support both additions and removals in FIFO order while + minimizing block erases. +- The free list had to handle the case where the file system completely ran + out of blocks and may no longer be able to add blocks to the free list. +- If we used a revision count to track the most recently updated free list, + metadata blocks that were left unmodified were ticking time bombs that would + cause the system to go haywire if the revision count overflowed. +- Every single metadata block wasted space to store these free list references. + +Actually, to simplify, this approach had one massive glaring issue: complexity. + +> Complexity leads to fallibility. +> Fallibility leads to unmaintainability. +> Unmaintainability leads to suffering. + +Or at least, complexity leads to increased code size, which is a problem +for embedded systems. + +In the end, the littlefs adopted more of a "drop it on the floor" strategy. +That is, the littlefs doesn't actually store information about which blocks +are free on the storage. The littlefs already stores which files _are_ in +use, so to find a free block, the littlefs just takes all of the blocks that +exist and subtract the blocks that are in use. + +Of course, it's not quite that simple. Most filesystems that adopt this "drop +it on the floor" strategy either rely on some properties inherent to the +filesystem, such as the cyclic-buffer structure of logging filesystems, +or use a bitmap or table stored in RAM to track free blocks, which scales +with the size of storage and is problematic when you have limited RAM. You +could iterate through every single block in storage and check it against +every single block in the filesystem on every single allocation, but that +would have an abhorrent runtime. + +So the littlefs compromises. It doesn't store a bitmap the size of the storage, +but it does store a little bit-vector that contains a fixed set lookahead +for block allocations. During a block allocation, the lookahead vector is +checked for any free blocks. If there are none, the lookahead region jumps +forward and the entire filesystem is scanned for free blocks. + +Here's what it might look like to allocate 4 blocks on a decently busy +filesystem with a 32bit lookahead and a total of +128 blocks (512Kbytes of storage if blocks are 4Kbyte): +``` +boot... lookahead: + fs blocks: fffff9fffffffffeffffffffffff0000 +scanning... lookahead: fffff9ff + fs blocks: fffff9fffffffffeffffffffffff0000 +alloc = 21 lookahead: fffffdff + fs blocks: fffffdfffffffffeffffffffffff0000 +alloc = 22 lookahead: ffffffff + fs blocks: fffffffffffffffeffffffffffff0000 +scanning... lookahead: fffffffe + fs blocks: fffffffffffffffeffffffffffff0000 +alloc = 63 lookahead: ffffffff + fs blocks: ffffffffffffffffffffffffffff0000 +scanning... lookahead: ffffffff + fs blocks: ffffffffffffffffffffffffffff0000 +scanning... lookahead: ffffffff + fs blocks: ffffffffffffffffffffffffffff0000 +scanning... lookahead: ffff0000 + fs blocks: ffffffffffffffffffffffffffff0000 +alloc = 112 lookahead: ffff8000 + fs blocks: ffffffffffffffffffffffffffff8000 +``` + +While this lookahead approach still has an asymptotic runtime of O(n^2) to +scan all of storage, the lookahead reduces the practical runtime to a +reasonable amount. Bit-vectors are surprisingly compact, given only 16 bytes, +the lookahead could track 128 blocks. For a 4Mbyte flash chip with 4Kbyte +blocks, the littlefs would only need 8 passes to scan the entire storage. + +The real benefit of this approach is just how much it simplified the design +of the littlefs. Deallocating blocks is as simple as simply forgetting they +exist, and there is absolutely no concern of bugs in the deallocation code +causing difficult to detect memory leaks. + +## Directories + +Now we just need directories to store our files. Since we already have +metadata blocks that store information about files, lets just use these +metadata blocks as the directories. Maybe turn the directories into linked +lists of metadata blocks so it isn't limited by the number of files that fit +in a single block. Add entries that represent other nested directories. +Drop "." and ".." entries, cause who needs them. Dust off our hands and +we now have a directory tree. + +``` + .--------. + |root dir| + | pair 0 | + | | + '--------' + .-' '-------------------------. + v v + .--------. .--------. .--------. + | dir A |------->| dir A | | dir B | + | pair 0 | | pair 1 | | pair 0 | + | | | | | | + '--------' '--------' '--------' + .-' '-. | .-' '-. + v v v v v +.--------. .--------. .--------. .--------. .--------. +| file C | | file D | | file E | | file F | | file G | +| | | | | | | | | | +| | | | | | | | | | +'--------' '--------' '--------' '--------' '--------' +``` + +Unfortunately it turns out it's not that simple. See, iterating over a +directory tree isn't actually all that easy, especially when you're trying +to fit in a bounded amount of RAM, which rules out any recursive solution. +And since our block allocator involves iterating over the entire filesystem +tree, possibly multiple times in a single allocation, iteration needs to be +efficient. + +So, as a solution, the littlefs adopted a sort of threaded tree. Each +directory not only contains pointers to all of its children, but also a +pointer to the next directory. These pointers create a linked-list that +is threaded through all of the directories in the filesystem. Since we +only use this linked list to check for existence, the order doesn't actually +matter. As an added plus, we can repurpose the pointer for the individual +directory linked-lists and avoid using any additional space. + +``` + .--------. + |root dir|-. + | pair 0 | | + .--------| |-' + | '--------' + | .-' '-------------------------. + | v v + | .--------. .--------. .--------. + '->| dir A |------->| dir A |------->| dir B | + | pair 0 | | pair 1 | | pair 0 | + | | | | | | + '--------' '--------' '--------' + .-' '-. | .-' '-. + v v v v v +.--------. .--------. .--------. .--------. .--------. +| file C | | file D | | file E | | file F | | file G | +| | | | | | | | | | +| | | | | | | | | | +'--------' '--------' '--------' '--------' '--------' +``` + +This threaded tree approach does come with a few tradeoffs. Now, anytime we +want to manipulate the directory tree, we find ourselves having to update two +pointers instead of one. For anyone familiar with creating atomic data +structures this should set off a whole bunch of red flags. + +But unlike the data structure guys, we can update a whole block atomically! So +as long as we're really careful (and cheat a little bit), we can still +manipulate the directory tree in a way that is resilient to power loss. + +Consider how we might add a new directory. Since both pointers that reference +it can come from the same directory, we only need a single atomic update to +finagle the directory into the filesystem: +``` + .--------. + |root dir|-. + | pair 0 | | +.--| |-' +| '--------' +| | +| v +| .--------. +'->| dir A | + | pair 0 | + | | + '--------' + +| create the new directory block +v + + .--------. + |root dir|-. + | pair 0 | | + .--| |-' + | '--------' + | | + | v + | .--------. +.--------. '->| dir A | +| dir B |---->| pair 0 | +| pair 0 | | | +| | '--------' +'--------' + +| update root to point to directory B +v + + .--------. + |root dir|-. + | pair 0 | | +.--------| |-' +| '--------' +| .-' '-. +| v v +| .--------. .--------. +'->| dir B |->| dir A | + | pair 0 | | pair 0 | + | | | | + '--------' '--------' +``` + +Note that even though directory B was added after directory A, we insert +directory B before directory A in the linked-list because it is convenient. + +Now how about removal: +``` + .--------. .--------. + |root dir|------->|root dir|-. + | pair 0 | | pair 1 | | +.--------| |--------| |-' +| '--------' '--------' +| .-' '-. | +| v v v +| .--------. .--------. .--------. +'->| dir A |->| dir B |->| dir C | + | pair 0 | | pair 0 | | pair 0 | + | | | | | | + '--------' '--------' '--------' + +| update root to no longer contain directory B +v + + .--------. .--------. + |root dir|------------->|root dir|-. + | pair 0 | | pair 1 | | +.--| |--------------| |-' +| '--------' '--------' +| | | +| v v +| .--------. .--------. .--------. +'->| dir A |->| dir B |->| dir C | + | pair 0 | | pair 0 | | pair 0 | + | | | | | | + '--------' '--------' '--------' + +| remove directory B from the linked-list +v + + .--------. .--------. + |root dir|->|root dir|-. + | pair 0 | | pair 1 | | +.--| |--| |-' +| '--------' '--------' +| | | +| v v +| .--------. .--------. +'->| dir A |->| dir C | + | pair 0 | | pair 0 | + | | | | + '--------' '--------' +``` + +Wait, wait, wait, that's not atomic at all! If power is lost after removing +directory B from the root, directory B is still in the linked-list. We've +just created a memory leak! + +And to be honest, I don't have a clever solution for this case. As a +side-effect of using multiple pointers in the threaded tree, the littlefs +can end up with orphan blocks that have no parents and should have been +removed. + +To keep these orphan blocks from becoming a problem, the littlefs has a +deorphan step that simply iterates through every directory in the linked-list +and checks it against every directory entry in the filesystem to see if it +has a parent. The deorphan step occurs on the first block allocation after +boot, so orphans should never cause the littlefs to run out of storage +prematurely. Note that the deorphan step never needs to run in a read-only +filesystem. + +## The move problem + +Now we have a real problem. How do we move things between directories while +remaining power resilient? Even looking at the problem from a high level, +it seems impossible. We can update directory blocks atomically, but atomically +updating two independent directory blocks is not an atomic operation. + +Here's the steps the filesystem may go through to move a directory: +``` + .--------. + |root dir|-. + | pair 0 | | +.--------| |-' +| '--------' +| .-' '-. +| v v +| .--------. .--------. +'->| dir A |->| dir B | + | pair 0 | | pair 0 | + | | | | + '--------' '--------' + +| update directory B to point to directory A +v + + .--------. + |root dir|-. + | pair 0 | | +.--------| |-' +| '--------' +| .-----' '-. +| | v +| | .--------. +| | .->| dir B | +| | | | pair 0 | +| | | | | +| | | '--------' +| | .-------' +| v v | +| .--------. | +'->| dir A |-' + | pair 0 | + | | + '--------' + +| update root to no longer contain directory A +v + .--------. + |root dir|-. + | pair 0 | | +.----| |-' +| '--------' +| | +| v +| .--------. +| .->| dir B | +| | | pair 0 | +| '--| |-. +| '--------' | +| | | +| v | +| .--------. | +'--->| dir A |-' + | pair 0 | + | | + '--------' +``` + +We can leave any orphans up to the deorphan step to collect, but that doesn't +help the case where dir A has both dir B and the root dir as parents if we +lose power inconveniently. + +Initially, you might think this is fine. Dir A _might_ end up with two parents, +but the filesystem will still work as intended. But then this raises the +question of what do we do when the dir A wears out? For other directory blocks +we can update the parent pointer, but for a dir with two parents we would need +work out how to update both parents. And the check for multiple parents would +need to be carried out for every directory, even if the directory has never +been moved. + +It also presents a bad user-experience, since the condition of ending up with +two parents is rare, it's unlikely user-level code will be prepared. Just think +about how a user would recover from a multi-parented directory. They can't just +remove one directory, since remove would report the directory as "not empty". + +Other atomic filesystems simple COW the entire directory tree. But this +introduces a significant bit of complexity, which leads to code size, along +with a surprisingly expensive runtime cost during what most users assume is +a single pointer update. + +Another option is to update the directory block we're moving from to point +to the destination with a sort of predicate that we have moved if the +destination exists. Unfortunately, the omnipresent concern of wear could +cause any of these directory entries to change blocks, and changing the +entry size before a move introduces complications if it spills out of +the current directory block. + +So how do we go about moving a directory atomically? + +We rely on the improbableness of power loss. + +Power loss during a move is certainly possible, but it's actually relatively +rare. Unless a device is writing to a filesystem constantly, it's unlikely that +a power loss will occur during filesystem activity. We still need to handle +the condition, but runtime during a power loss takes a back seat to the runtime +during normal operations. + +So what littlefs does is inelegantly simple. When littlefs moves a file, it +marks the file as "moving". This is stored as a single bit in the directory +entry and doesn't take up much space. Then littlefs moves the directory, +finishing with the complete remove of the "moving" directory entry. + +``` + .--------. + |root dir|-. + | pair 0 | | +.--------| |-' +| '--------' +| .-' '-. +| v v +| .--------. .--------. +'->| dir A |->| dir B | + | pair 0 | | pair 0 | + | | | | + '--------' '--------' + +| update root directory to mark directory A as moving +v + + .----------. + |root dir |-. + | pair 0 | | +.-------| moving A!|-' +| '----------' +| .-' '-. +| v v +| .--------. .--------. +'->| dir A |->| dir B | + | pair 0 | | pair 0 | + | | | | + '--------' '--------' + +| update directory B to point to directory A +v + + .----------. + |root dir |-. + | pair 0 | | +.-------| moving A!|-' +| '----------' +| .-----' '-. +| | v +| | .--------. +| | .->| dir B | +| | | | pair 0 | +| | | | | +| | | '--------' +| | .-------' +| v v | +| .--------. | +'->| dir A |-' + | pair 0 | + | | + '--------' + +| update root to no longer contain directory A +v + .--------. + |root dir|-. + | pair 0 | | +.----| |-' +| '--------' +| | +| v +| .--------. +| .->| dir B | +| | | pair 0 | +| '--| |-. +| '--------' | +| | | +| v | +| .--------. | +'--->| dir A |-' + | pair 0 | + | | + '--------' +``` + +Now, if we run into a directory entry that has been marked as "moved", one +of two things is possible. Either the directory entry exists elsewhere in the +filesystem, or it doesn't. This is a O(n) operation, but only occurs in the +unlikely case we lost power during a move. + +And we can easily fix the "moved" directory entry. Since we're already scanning +the filesystem during the deorphan step, we can also check for moved entries. +If we find one, we either remove the "moved" marking or remove the whole entry +if it exists elsewhere in the filesystem. + +## Wear awareness + +So now that we have all of the pieces of a filesystem, we can look at a more +subtle attribute of embedded storage: The wear down of flash blocks. + +The first concern for the littlefs, is that perfectly valid blocks can suddenly +become unusable. As a nice side-effect of using a COW data-structure for files, +we can simply move on to a different block when a file write fails. All +modifications to files are performed in copies, so we will only replace the +old file when we are sure none of the new file has errors. Directories, on +the other hand, need a different strategy. + +The solution to directory corruption in the littlefs relies on the redundant +nature of the metadata pairs. If an error is detected during a write to one +of the metadata pairs, we seek out a new block to take its place. Once we find +a block without errors, we iterate through the directory tree, updating any +references to the corrupted metadata pair to point to the new metadata block. +Just like when we remove directories, we can lose power during this operation +and end up with a desynchronized metadata pair in our filesystem. And just like +when we remove directories, we leave the possibility of a desynchronized +metadata pair up to the deorphan step to clean up. + +Here's what encountering a directory error may look like with all of +the directories and directory pointers fully expanded: +``` + root dir + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 0 |--. + | | |-.| +.------| | |-|' +|.-----| | |-' +|| '---------'---------' +|| |||||'--------------------------------------------------. +|| ||||'-----------------------------------------. | +|| |||'-----------------------------. | | +|| ||'--------------------. | | | +|| |'-------. | | | | +|| v v v v v v +|| dir A dir B dir C +|| block 3 block 4 block 5 block 6 block 7 block 8 +|| .---------.---------. .---------.---------. .---------.---------. +|'->| rev: 1 | rev: 0 |->| rev: 1 | rev: 0 |->| rev: 1 | rev: 0 | +'-->| | |->| | |->| | | + | | | | | | | + | | | | | | | | | + '---------'---------' '---------'---------' '---------'---------' + +| update directory B +v + + root dir + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 0 |--. + | | |-.| +.------| | |-|' +|.-----| | |-' +|| '---------'---------' +|| |||||'--------------------------------------------------. +|| ||||'-----------------------------------------. | +|| |||'-----------------------------. | | +|| ||'--------------------. | | | +|| |'-------. | | | | +|| v v v v v v +|| dir A dir B dir C +|| block 3 block 4 block 5 block 6 block 7 block 8 +|| .---------.---------. .---------.---------. .---------.---------. +|'->| rev: 1 | rev: 0 |->| rev: 1 | rev: 2 |->| rev: 1 | rev: 0 | +'-->| | |->| | corrupt!|->| | | + | | | | | corrupt!| | | | + | | | | | corrupt!| | | | + '---------'---------' '---------'---------' '---------'---------' + +| oh no! corruption detected +v allocate a replacement block + + root dir + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 0 |--. + | | |-.| +.------| | |-|' +|.-----| | |-' +|| '---------'---------' +|| |||||'----------------------------------------------------. +|| ||||'-------------------------------------------. | +|| |||'-----------------------------. | | +|| ||'--------------------. | | | +|| |'-------. | | | | +|| v v v v v v +|| dir A dir B dir C +|| block 3 block 4 block 5 block 6 block 7 block 8 +|| .---------.---------. .---------.---------. .---------.---------. +|'->| rev: 1 | rev: 0 |->| rev: 1 | rev: 2 |--->| rev: 1 | rev: 0 | +'-->| | |->| | corrupt!|--->| | | + | | | | | corrupt!| .->| | | + | | | | | corrupt!| | | | | + '---------'---------' '---------'---------' | '---------'---------' + block 9 | + .---------. | + | rev: 2 |-' + | | + | | + | | + '---------' + +| update root directory to contain block 9 +v + + root dir + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 2 |--. + | | |-.| +.-----| | |-|' +|.----| | |-' +|| '---------'---------' +|| .--------'||||'----------------------------------------------. +|| | |||'-------------------------------------. | +|| | ||'-----------------------. | | +|| | |'------------. | | | +|| | | | | | | +|| v v v v v v +|| dir A dir B dir C +|| block 3 block 4 block 5 block 9 block 7 block 8 +|| .---------.---------. .---------. .---------. .---------.---------. +|'->| rev: 1 | rev: 0 |-->| rev: 1 |-| rev: 2 |--->| rev: 1 | rev: 0 | +'-->| | |-. | | | |--->| | | + | | | | | | | | .->| | | + | | | | | | | | | | | | + '---------'---------' | '---------' '---------' | '---------'---------' + | block 6 | + | .---------. | + '------------>| rev: 2 |-' + | corrupt!| + | corrupt!| + | corrupt!| + '---------' + +| remove corrupted block from linked-list +v + + root dir + block 1 block 2 + .---------.---------. + | rev: 1 | rev: 2 |--. + | | |-.| +.-----| | |-|' +|.----| | |-' +|| '---------'---------' +|| .--------'||||'-----------------------------------------. +|| | |||'--------------------------------. | +|| | ||'--------------------. | | +|| | |'-----------. | | | +|| | | | | | | +|| v v v v v v +|| dir A dir B dir C +|| block 3 block 4 block 5 block 9 block 7 block 8 +|| .---------.---------. .---------.---------. .---------.---------. +|'->| rev: 1 | rev: 2 |->| rev: 1 | rev: 2 |->| rev: 1 | rev: 0 | +'-->| | |->| | |->| | | + | | | | | | | | | + | | | | | | | | | + '---------'---------' '---------'---------' '---------'---------' +``` + +Also one question I've been getting is, what about the root directory? +It can't move so wouldn't the filesystem die as soon as the root blocks +develop errors? And you would be correct. So instead of storing the root +in the first few blocks of the storage, the root is actually pointed to +by the superblock. The superblock contains a few bits of static data, but +outside of when the filesystem is formatted, it is only updated when the root +develops errors and needs to be moved. + +## Wear leveling + +The second concern for the littlefs is that blocks in the filesystem may wear +unevenly. In this situation, a filesystem may meet an early demise where +there are no more non-corrupted blocks that aren't in use. It's common to +have files that were written once and left unmodified, wasting the potential +erase cycles of the blocks it sits on. + +Wear leveling is a term that describes distributing block writes evenly to +avoid the early termination of a flash part. There are typically two levels +of wear leveling: +1. Dynamic wear leveling - Wear is distributed evenly across all **dynamic** + blocks. Usually this is accomplished by simply choosing the unused block + with the lowest amount of wear. Note this does not solve the problem of + static data. +2. Static wear leveling - Wear is distributed evenly across all **dynamic** + and **static** blocks. Unmodified blocks may be evicted for new block + writes. This does handle the problem of static data but may lead to + wear amplification. + +In littlefs's case, it's possible to use the revision count on metadata pairs +to approximate the wear of a metadata block. And combined with the COW nature +of files, littlefs could provide your usual implementation of dynamic wear +leveling. + +However, the littlefs does not. This is for a few reasons. Most notably, even +if the littlefs did implement dynamic wear leveling, this would still not +handle the case of write-once files, and near the end of the lifetime of a +flash device, you would likely end up with uneven wear on the blocks anyways. + +As a flash device reaches the end of its life, the metadata blocks will +naturally be the first to go since they are updated most often. In this +situation, the littlefs is designed to simply move on to another set of +metadata blocks. This travelling means that at the end of a flash device's +life, the filesystem will have worn the device down nearly as evenly as the +usual dynamic wear leveling could. More aggressive wear leveling would come +with a code-size cost for marginal benefit. + + +One important takeaway to note, if your storage stack uses highly sensitive +storage such as NAND flash, static wear leveling is the only valid solution. +In most cases you are going to be better off using a full [flash translation layer (FTL)](https://en.wikipedia.org/wiki/Flash_translation_layer). +NAND flash already has many limitations that make it poorly suited for an +embedded system: low erase cycles, very large blocks, errors that can develop +even during reads, errors that can develop during writes of neighboring blocks. +Managing sensitive storage such as NAND flash is out of scope for the littlefs. +The littlefs does have some properties that may be beneficial on top of a FTL, +such as limiting the number of writes where possible, but if you have the +storage requirements that necessitate the need of NAND flash, you should have +the RAM to match and just use an FTL or flash filesystem. + +## Summary + +So, to summarize: + +1. The littlefs is composed of directory blocks +2. Each directory is a linked-list of metadata pairs +3. These metadata pairs can be updated atomically by alternating which + metadata block is active +4. Directory blocks contain either references to other directories or files +5. Files are represented by copy-on-write CTZ skip-lists which support O(1) + append and O(n log n) reading +6. Blocks are allocated by scanning the filesystem for used blocks in a + fixed-size lookahead region that is stored in a bit-vector +7. To facilitate scanning the filesystem, all directories are part of a + linked-list that is threaded through the entire filesystem +8. If a block develops an error, the littlefs allocates a new block, and + moves the data and references of the old block to the new. +9. Any case where an atomic operation is not possible, mistakes are resolved + by a deorphan step that occurs on the first allocation after boot + +That's the little filesystem. Thanks for reading! + diff --git a/MicroPython_BUILD/components/littlefs/LICENSE.md b/MicroPython_BUILD/components/littlefs/LICENSE.md new file mode 100644 index 00000000..59cd3f8a --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/LICENSE.md @@ -0,0 +1,165 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. diff --git a/MicroPython_BUILD/components/littlefs/README.md b/MicroPython_BUILD/components/littlefs/README.md new file mode 100644 index 00000000..e778a650 --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/README.md @@ -0,0 +1,164 @@ +## The little filesystem + +A little fail-safe filesystem designed for embedded systems. + +``` + | | | .---._____ + .-----. | | +--|o |---| littlefs | +--| |---| | + '-----' '----------' + | | | +``` + +**Bounded RAM/ROM** - The littlefs is designed to work with a limited amount +of memory. Recursion is avoided and dynamic memory is limited to configurable +buffers that can be provided statically. + +**Power-loss resilient** - The littlefs is designed for systems that may have +random power failures. The littlefs has strong copy-on-write guarantees and +storage on disk is always kept in a valid state. + +**Wear leveling** - Since the most common form of embedded storage is erodible +flash memories, littlefs provides a form of dynamic wear leveling for systems +that can not fit a full flash translation layer. + +## Example + +Here's a simple example that updates a file named `boot_count` every time +main runs. The program can be interrupted at any time without losing track +of how many times it has been booted and without corrupting the filesystem: + +``` c +#include "lfs.h" + +// variables used by the filesystem +lfs_t lfs; +lfs_file_t file; + +// configuration of the filesystem is provided by this struct +const struct lfs_config cfg = { + // block device operations + .read = user_provided_block_device_read, + .prog = user_provided_block_device_prog, + .erase = user_provided_block_device_erase, + .sync = user_provided_block_device_sync, + + // block device configuration + .read_size = 16, + .prog_size = 16, + .block_size = 4096, + .block_count = 128, + .lookahead = 128, +}; + +// entry point +int main(void) { + // mount the filesystem + int err = lfs_mount(&lfs, &cfg); + + // reformat if we can't mount the filesystem + // this should only happen on the first boot + if (err) { + lfs_format(&lfs, &cfg); + lfs_mount(&lfs, &cfg); + } + + // read current count + uint32_t boot_count = 0; + lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT); + lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count)); + + // update boot count + boot_count += 1; + lfs_file_rewind(&lfs, &file); + lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count)); + + // remember the storage is not updated until the file is closed successfully + lfs_file_close(&lfs, &file); + + // release any resources we were using + lfs_unmount(&lfs); + + // print the boot count + printf("boot_count: %d\n", boot_count); +} +``` + +## Usage + +Detailed documentation (or at least as much detail as is currently available) +can be found in the comments in [lfs.h](lfs.h). + +As you may have noticed, littlefs takes in a configuration structure that +defines how the filesystem operates. The configuration struct provides the +filesystem with the block device operations and dimensions, tweakable +parameters that tradeoff memory usage for performance, and optional +static buffers if the user wants to avoid dynamic memory. + +The state of the littlefs is stored in the `lfs_t` type which is left up +to the user to allocate, allowing multiple filesystems to be in use +simultaneously. With the `lfs_t` and configuration struct, a user can +format a block device or mount the filesystem. + +Once mounted, the littlefs provides a full set of POSIX-like file and +directory functions, with the deviation that the allocation of filesystem +structures must be provided by the user. + +All POSIX operations, such as remove and rename, are atomic, even in event +of power-loss. Additionally, no file updates are actually committed to the +filesystem until sync or close is called on the file. + +## Other notes + +All littlefs have the potential to return a negative error code. The errors +can be either one of those found in the `enum lfs_error` in [lfs.h](lfs.h), +or an error returned by the user's block device operations. + +In the configuration struct, the `prog` and `erase` function provided by the +user may return a `LFS_ERR_CORRUPT` error if the implementation already can +detect corrupt blocks. However, the wear leveling does not depend on the return +code of these functions, instead all data is read back and checked for +integrity. + +If your storage caches writes, make sure that the provided `sync` function +flushes all the data to memory and ensures that the next read fetches the data +from memory, otherwise data integrity can not be guaranteed. If the `write` +function does not perform caching, and therefore each `read` or `write` call +hits the memory, the `sync` function can simply return 0. + +## Reference material + +[DESIGN.md](DESIGN.md) - DESIGN.md contains a fully detailed dive into how +littlefs actually works. I would encourage you to read it since the +solutions and tradeoffs at work here are quite interesting. + +[SPEC.md](SPEC.md) - SPEC.md contains the on-disk specification of littlefs +with all the nitty-gritty details. Can be useful for developing tooling. + +## Testing + +The littlefs comes with a test suite designed to run on a PC using the +[emulated block device](emubd/lfs_emubd.h) found in the emubd directory. +The tests assume a Linux environment and can be started with make: + +``` bash +make test +``` + +## Related projects + +[Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) - +The easiest way to get started with littlefs is to jump into [Mbed](https://os.mbed.com/), +which already has block device drivers for most forms of embedded storage. The +littlefs is available in Mbed OS as the [LittleFileSystem](https://os.mbed.com/docs/latest/reference/littlefilesystem.html) +class. + +[littlefs-fuse](https://github.com/geky/littlefs-fuse) - A [FUSE](https://github.com/libfuse/libfuse) +wrapper for littlefs. The project allows you to mount littlefs directly on a +Linux machine. Can be useful for debugging littlefs if you have an SD card +handy. + +[littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for +littlefs. I'm not sure why you would want this, but it is handy for demos. +You can see it in action [here](http://littlefs.geky.net/demo.html). diff --git a/MicroPython_BUILD/components/littlefs/SPEC.md b/MicroPython_BUILD/components/littlefs/SPEC.md new file mode 100644 index 00000000..2a1f9eca --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/SPEC.md @@ -0,0 +1,370 @@ +## The little filesystem technical specification + +This is the technical specification of the little filesystem. This document +covers the technical details of how the littlefs is stored on disk for +introspection and tooling development. This document assumes you are +familiar with the design of the littlefs, for more info on how littlefs +works check out [DESIGN.md](DESIGN.md). + +``` + | | | .---._____ + .-----. | | +--|o |---| littlefs | +--| |---| | + '-----' '----------' + | | | +``` + +## Some important details + +- The littlefs is a block-based filesystem. This is, the disk is divided into + an array of evenly sized blocks that are used as the logical unit of storage + in littlefs. Block pointers are stored in 32 bits. + +- There is no explicit free-list stored on disk, the littlefs only knows what + is in use in the filesystem. + +- The littlefs uses the value of 0xffffffff to represent a null block-pointer. + +- All values in littlefs are stored in little-endian byte order. + +## Directories / Metadata pairs + +Metadata pairs form the backbone of the littlefs and provide a system for +atomic updates. Even the superblock is stored in a metadata pair. + +As their name suggests, a metadata pair is stored in two blocks, with one block +acting as a redundant backup in case the other is corrupted. These two blocks +could be anywhere in the disk and may not be next to each other, so any +pointers to directory pairs need to be stored as two block pointers. + +Here's the layout of metadata blocks on disk: + +| offset | size | description | +|--------|---------------|----------------| +| 0x00 | 32 bits | revision count | +| 0x04 | 32 bits | dir size | +| 0x08 | 64 bits | tail pointer | +| 0x10 | size-16 bytes | dir entries | +| 0x00+s | 32 bits | CRC | + +**Revision count** - Incremented every update, only the uncorrupted +metadata-block with the most recent revision count contains the valid metadata. +Comparison between revision counts must use sequence comparison since the +revision counts may overflow. + +**Dir size** - Size in bytes of the contents in the current metadata block, +including the metadata-pair metadata. Additionally, the highest bit of the +dir size may be set to indicate that the directory's contents continue on the +next metadata-pair pointed to by the tail pointer. + +**Tail pointer** - Pointer to the next metadata-pair in the filesystem. +A null pair-pointer (0xffffffff, 0xffffffff) indicates the end of the list. +If the highest bit in the dir size is set, this points to the next +metadata-pair in the current directory, otherwise it points to an arbitrary +metadata-pair. Starting with the superblock, the tail-pointers form a +linked-list containing all metadata-pairs in the filesystem. + +**CRC** - 32 bit CRC used to detect corruption from power-lost, from block +end-of-life, or just from noise on the storage bus. The CRC is appended to +the end of each metadata-block. The littlefs uses the standard CRC-32, which +uses a polynomial of 0x04c11db7, initialized with 0xffffffff. + +Here's an example of a simple directory stored on disk: +``` +(32 bits) revision count = 10 (0x0000000a) +(32 bits) dir size = 154 bytes, end of dir (0x0000009a) +(64 bits) tail pointer = 37, 36 (0x00000025, 0x00000024) +(32 bits) CRC = 0xc86e3106 + +00000000: 0a 00 00 00 9a 00 00 00 25 00 00 00 24 00 00 00 ........%...$... +00000010: 22 08 00 03 05 00 00 00 04 00 00 00 74 65 61 22 "...........tea" +00000020: 08 00 06 07 00 00 00 06 00 00 00 63 6f 66 66 65 ...........coffe +00000030: 65 22 08 00 04 09 00 00 00 08 00 00 00 73 6f 64 e"...........sod +00000040: 61 22 08 00 05 1d 00 00 00 1c 00 00 00 6d 69 6c a"...........mil +00000050: 6b 31 22 08 00 05 1f 00 00 00 1e 00 00 00 6d 69 k1"...........mi +00000060: 6c 6b 32 22 08 00 05 21 00 00 00 20 00 00 00 6d lk2"...!... ...m +00000070: 69 6c 6b 33 22 08 00 05 23 00 00 00 22 00 00 00 ilk3"...#..."... +00000080: 6d 69 6c 6b 34 22 08 00 05 25 00 00 00 24 00 00 milk4"...%...$.. +00000090: 00 6d 69 6c 6b 35 06 31 6e c8 .milk5.1n. +``` + +A note about the tail pointer linked-list: Normally, this linked-list is +threaded through the entire filesystem. However, after power-loss this +linked-list may become out of sync with the rest of the filesystem. +- The linked-list may contain a directory that has actually been removed +- The linked-list may contain a metadata pair that has not been updated after + a block in the pair has gone bad. + +The threaded linked-list must be checked for these errors before it can be +used reliably. Fortunately, the threaded linked-list can simply be ignored +if littlefs is mounted read-only. + +## Entries + +Each metadata block contains a series of entries that follow a standard +layout. An entry contains the type of the entry, along with a section for +entry-specific data, attributes, and a name. + +Here's the layout of entries on disk: + +| offset | size | description | +|---------|------------------------|----------------------------| +| 0x0 | 8 bits | entry type | +| 0x1 | 8 bits | entry length | +| 0x2 | 8 bits | attribute length | +| 0x3 | 8 bits | name length | +| 0x4 | entry length bytes | entry-specific data | +| 0x4+e | attribute length bytes | system-specific attributes | +| 0x4+e+a | name length bytes | entry name | + +**Entry type** - Type of the entry, currently this is limited to the following: +- 0x11 - file entry +- 0x22 - directory entry +- 0x2e - superblock entry + +Additionally, the type is broken into two 4 bit nibbles, with the upper nibble +specifying the type's data structure used when scanning the filesystem. The +lower nibble clarifies the type further when multiple entries share the same +data structure. + +The highest bit is reserved for marking the entry as "moved". If an entry +is marked as "moved", the entry may also exist somewhere else in the +filesystem. If the entry exists elsewhere, this entry must be treated as +though it does not exist. + +**Entry length** - Length in bytes of the entry-specific data. This does +not include the entry type size, attributes, or name. The full size in bytes +of the entry is 4 + entry length + attribute length + name length. + +**Attribute length** - Length of system-specific attributes in bytes. Since +attributes are system specific, there is not much guarantee on the values in +this section, and systems are expected to work even when it is empty. See the +[attributes](#entry-attributes) section for more details. + +**Name length** - Length of the entry name. Entry names are stored as UTF8, +although most systems will probably only support ASCII. Entry names can not +contain '/' and can not be '.' or '..' as these are a part of the syntax of +filesystem paths. + +Here's an example of a simple entry stored on disk: +``` +(8 bits) entry type = file (0x11) +(8 bits) entry length = 8 bytes (0x08) +(8 bits) attribute length = 0 bytes (0x00) +(8 bits) name length = 12 bytes (0x0c) +(8 bytes) entry data = 05 00 00 00 20 00 00 00 +(12 bytes) entry name = smallavacado + +00000000: 11 08 00 0c 05 00 00 00 20 00 00 00 73 6d 61 6c ........ ...smal +00000010: 6c 61 76 61 63 61 64 6f lavacado +``` + +## Superblock + +The superblock is the anchor for the littlefs. The superblock is stored as +a metadata pair containing a single superblock entry. It is through the +superblock that littlefs can access the rest of the filesystem. + +The superblock can always be found in blocks 0 and 1, however fetching the +superblock requires knowing the block size. The block size can be guessed by +searching the beginning of disk for the string "littlefs", although currently +the filesystems relies on the user providing the correct block size. + +The superblock is the most valuable block in the filesystem. It is updated +very rarely, only during format or when the root directory must be moved. It +is encouraged to always write out both superblock pairs even though it is not +required. + +Here's the layout of the superblock entry: + +| offset | size | description | +|--------|------------------------|----------------------------------------| +| 0x00 | 8 bits | entry type (0x2e for superblock entry) | +| 0x01 | 8 bits | entry length (20 bytes) | +| 0x02 | 8 bits | attribute length | +| 0x03 | 8 bits | name length (8 bytes) | +| 0x04 | 64 bits | root directory | +| 0x0c | 32 bits | block size | +| 0x10 | 32 bits | block count | +| 0x14 | 32 bits | version | +| 0x18 | attribute length bytes | system-specific attributes | +| 0x18+a | 8 bytes | magic string ("littlefs") | + +**Root directory** - Pointer to the root directory's metadata pair. + +**Block size** - Size of the logical block size used by the filesystem. + +**Block count** - Number of blocks in the filesystem. + +**Version** - The littlefs version encoded as a 32 bit value. The upper 16 bits +encodes the major version, which is incremented when a breaking-change is +introduced in the filesystem specification. The lower 16 bits encodes the +minor version, which is incremented when a backwards-compatible change is +introduced. Non-standard Attribute changes do not change the version. This +specification describes version 1.1 (0x00010001), which is the first version +of littlefs. + +**Magic string** - The magic string "littlefs" takes the place of an entry +name. + +Here's an example of a complete superblock: +``` +(32 bits) revision count = 3 (0x00000003) +(32 bits) dir size = 52 bytes, end of dir (0x00000034) +(64 bits) tail pointer = 3, 2 (0x00000003, 0x00000002) +(8 bits) entry type = superblock (0x2e) +(8 bits) entry length = 20 bytes (0x14) +(8 bits) attribute length = 0 bytes (0x00) +(8 bits) name length = 8 bytes (0x08) +(64 bits) root directory = 3, 2 (0x00000003, 0x00000002) +(32 bits) block size = 512 bytes (0x00000200) +(32 bits) block count = 1024 blocks (0x00000400) +(32 bits) version = 1.1 (0x00010001) +(8 bytes) magic string = littlefs +(32 bits) CRC = 0xc50b74fa + +00000000: 03 00 00 00 34 00 00 00 03 00 00 00 02 00 00 00 ....4........... +00000010: 2e 14 00 08 03 00 00 00 02 00 00 00 00 02 00 00 ................ +00000020: 00 04 00 00 01 00 01 00 6c 69 74 74 6c 65 66 73 ........littlefs +00000030: fa 74 0b c5 .t.. +``` + +## Directory entries + +Directories are stored in entries with a pointer to the first metadata pair +in the directory. Keep in mind that a directory may be composed of multiple +metadata pairs connected by the tail pointer when the highest bit in the dir +size is set. + +Here's the layout of a directory entry: + +| offset | size | description | +|--------|------------------------|-----------------------------------------| +| 0x0 | 8 bits | entry type (0x22 for directory entries) | +| 0x1 | 8 bits | entry length (8 bytes) | +| 0x2 | 8 bits | attribute length | +| 0x3 | 8 bits | name length | +| 0x4 | 64 bits | directory pointer | +| 0xc | attribute length bytes | system-specific attributes | +| 0xc+a | name length bytes | directory name | + +**Directory pointer** - Pointer to the first metadata pair in the directory. + +Here's an example of a directory entry: +``` +(8 bits) entry type = directory (0x22) +(8 bits) entry length = 8 bytes (0x08) +(8 bits) attribute length = 0 bytes (0x00) +(8 bits) name length = 3 bytes (0x03) +(64 bits) directory pointer = 5, 4 (0x00000005, 0x00000004) +(3 bytes) name = tea + +00000000: 22 08 00 03 05 00 00 00 04 00 00 00 74 65 61 "...........tea +``` + +## File entries + +Files are stored in entries with a pointer to the head of the file and the +size of the file. This is enough information to determine the state of the +CTZ skip-list that is being referenced. + +How files are actually stored on disk is a bit complicated. The full +explanation of CTZ skip-lists can be found in [DESIGN.md](DESIGN.md#ctz-skip-lists). + +A terribly quick summary: For every nth block where n is divisible by 2^x, +the block contains a pointer to block n-2^x. These pointers are stored in +increasing order of x in each block of the file preceding the data in the +block. + +The maximum number of pointers in a block is bounded by the maximum file size +divided by the block size. With 32 bits for file size, this results in a +minimum block size of 104 bytes. + +Here's the layout of a file entry: + +| offset | size | description | +|--------|------------------------|------------------------------------| +| 0x0 | 8 bits | entry type (0x11 for file entries) | +| 0x1 | 8 bits | entry length (8 bytes) | +| 0x2 | 8 bits | attribute length | +| 0x3 | 8 bits | name length | +| 0x4 | 32 bits | file head | +| 0x8 | 32 bits | file size | +| 0xc | attribute length bytes | system-specific attributes | +| 0xc+a | name length bytes | directory name | + +**File head** - Pointer to the block that is the head of the file's CTZ +skip-list. + +**File size** - Size of file in bytes. + +Here's an example of a file entry: +``` +(8 bits) entry type = file (0x11) +(8 bits) entry length = 8 bytes (0x08) +(8 bits) attribute length = 0 bytes (0x00) +(8 bits) name length = 12 bytes (0x03) +(32 bits) file head = 543 (0x0000021f) +(32 bits) file size = 256 KB (0x00040000) +(12 bytes) name = largeavacado + +00000000: 11 08 00 0c 1f 02 00 00 00 00 04 00 6c 61 72 67 ............larg +00000010: 65 61 76 61 63 61 64 6f eavacado +``` + +## Entry attributes + +Each dir entry can have up to 256 bytes of system-specific attributes. Since +these attributes are system-specific, they may not be portable between +different systems. For this reason, all attributes must be optional. A minimal +littlefs driver must be able to get away with supporting no attributes at all. + +For some level of portability, littlefs has a simple scheme for attributes. +Each attribute is prefixes with an 8-bit type that indicates what the attribute +is. The length of attributes may also be determined from this type. Attributes +in an entry should be sorted based on portability, since attribute parsing +will end when it hits the first attribute it does not understand. + +Each system should choose a 4-bit value to prefix all attribute types with to +avoid conflicts with other systems. Additionally, littlefs drivers that support +attributes should provide a "ignore attributes" flag to users in case attribute +conflicts do occur. + +Attribute types prefixes with 0x0 and 0xf are currently reserved for future +standard attributes. Standard attributes will be added to this document in +that case. + +Here's an example of non-standard time attribute: +``` +(8 bits) attribute type = time (0xc1) +(72 bits) time in seconds = 1506286115 (0x0059c81a23) + +00000000: c1 23 1a c8 59 00 .#..Y. +``` + +Here's an example of non-standard permissions attribute: +``` +(8 bits) attribute type = permissions (0xc2) +(16 bits) permission bits = rw-rw-r-- (0x01b4) + +00000000: c2 b4 01 ... +``` + +Here's what a dir entry may look like with these attributes: +``` +(8 bits) entry type = file (0x11) +(8 bits) entry length = 8 bytes (0x08) +(8 bits) attribute length = 9 bytes (0x09) +(8 bits) name length = 12 bytes (0x0c) +(8 bytes) entry data = 05 00 00 00 20 00 00 00 +(8 bits) attribute type = time (0xc1) +(72 bits) time in seconds = 1506286115 (0x0059c81a23) +(8 bits) attribute type = permissions (0xc2) +(16 bits) permission bits = rw-rw-r-- (0x01b4) +(12 bytes) entry name = smallavacado + +00000000: 11 08 09 0c 05 00 00 00 20 00 00 00 c1 23 1a c8 ........ ....#.. +00000010: 59 00 c2 b4 01 73 6d 61 6c 6c 61 76 61 63 61 64 Y....smallavacad +00000020: 6f o +``` diff --git a/MicroPython_BUILD/components/littlefs/component.mk b/MicroPython_BUILD/components/littlefs/component.mk new file mode 100644 index 00000000..c7090ca3 --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/component.mk @@ -0,0 +1,7 @@ +# +# Component Makefile +# + +COMPONENT_SRCDIRS := . +COMPONENT_ADD_INCLUDEDIRS := + diff --git a/MicroPython_BUILD/components/littlefs/lfs.c b/MicroPython_BUILD/components/littlefs/lfs.c new file mode 100644 index 00000000..1fff5f8f --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/lfs.c @@ -0,0 +1,2677 @@ +/* + * The little filesystem + * + * Copyright (c) 2017 ARM Limited + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "lfs.h" +#include "lfs_util.h" + +#define ATTRIBUTE_LEN 5 + +static uint8_t lfs_dir_compute_attribute(uint8_t *buf); +static int lfs_dir_extract_attribute(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, struct lfs_info *info); + +/// Caching block device operations /// +static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache, + const lfs_cache_t *pcache, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size) { + uint8_t *data = buffer; + LFS_ASSERT(block < lfs->cfg->block_count); + + while (size > 0) { + if (pcache && block == pcache->block && off >= pcache->off && + off < pcache->off + lfs->cfg->prog_size) { + // is already in pcache? + lfs_size_t diff = lfs_min(size, + lfs->cfg->prog_size - (off-pcache->off)); + memcpy(data, &pcache->buffer[off-pcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + if (block == rcache->block && off >= rcache->off && + off < rcache->off + lfs->cfg->read_size) { + // is already in rcache? + lfs_size_t diff = lfs_min(size, + lfs->cfg->read_size - (off-rcache->off)); + memcpy(data, &rcache->buffer[off-rcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + if (off % lfs->cfg->read_size == 0 && size >= lfs->cfg->read_size) { + // bypass cache? + lfs_size_t diff = size - (size % lfs->cfg->read_size); + int err = lfs->cfg->read(lfs->cfg, block, off, data, diff); + if (err) { + return err; + } + + data += diff; + off += diff; + size -= diff; + continue; + } + + // load to cache, first condition can no longer fail + rcache->block = block; + rcache->off = off - (off % lfs->cfg->read_size); + int err = lfs->cfg->read(lfs->cfg, rcache->block, + rcache->off, rcache->buffer, lfs->cfg->read_size); + if (err) { + return err; + } + } + + return 0; +} + +static int lfs_cache_cmp(lfs_t *lfs, lfs_cache_t *rcache, + const lfs_cache_t *pcache, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + const uint8_t *data = buffer; + + for (lfs_off_t i = 0; i < size; i++) { + uint8_t c; + int err = lfs_cache_read(lfs, rcache, pcache, + block, off+i, &c, 1); + if (err) { + return err; + } + + if (c != data[i]) { + return false; + } + } + + return true; +} + +static int lfs_cache_crc(lfs_t *lfs, lfs_cache_t *rcache, + const lfs_cache_t *pcache, lfs_block_t block, + lfs_off_t off, lfs_size_t size, uint32_t *crc) { + for (lfs_off_t i = 0; i < size; i++) { + uint8_t c; + int err = lfs_cache_read(lfs, rcache, pcache, + block, off+i, &c, 1); + if (err) { + return err; + } + + lfs_crc(crc, &c, 1); + } + + return 0; +} + +static int lfs_cache_flush(lfs_t *lfs, + lfs_cache_t *pcache, lfs_cache_t *rcache) { + if (pcache->block != 0xffffffff) { + int err = lfs->cfg->prog(lfs->cfg, pcache->block, + pcache->off, pcache->buffer, lfs->cfg->prog_size); + if (err) { + return err; + } + + if (rcache) { + int res = lfs_cache_cmp(lfs, rcache, NULL, pcache->block, + pcache->off, pcache->buffer, lfs->cfg->prog_size); + if (res < 0) { + return res; + } + + if (!res) { + return LFS_ERR_CORRUPT; + } + } + + pcache->block = 0xffffffff; + } + + return 0; +} + +static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache, + lfs_cache_t *rcache, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + const uint8_t *data = buffer; + LFS_ASSERT(block < lfs->cfg->block_count); + + while (size > 0) { + if (block == pcache->block && off >= pcache->off && + off < pcache->off + lfs->cfg->prog_size) { + // is already in pcache? + lfs_size_t diff = lfs_min(size, + lfs->cfg->prog_size - (off-pcache->off)); + memcpy(&pcache->buffer[off-pcache->off], data, diff); + + data += diff; + off += diff; + size -= diff; + + if (off % lfs->cfg->prog_size == 0) { + // eagerly flush out pcache if we fill up + int err = lfs_cache_flush(lfs, pcache, rcache); + if (err) { + return err; + } + } + + continue; + } + + // pcache must have been flushed, either by programming and + // entire block or manually flushing the pcache + LFS_ASSERT(pcache->block == 0xffffffff); + + if (off % lfs->cfg->prog_size == 0 && + size >= lfs->cfg->prog_size) { + // bypass pcache? + lfs_size_t diff = size - (size % lfs->cfg->prog_size); + int err = lfs->cfg->prog(lfs->cfg, block, off, data, diff); + if (err) { + return err; + } + + if (rcache) { + int res = lfs_cache_cmp(lfs, rcache, NULL, + block, off, data, diff); + if (res < 0) { + return res; + } + + if (!res) { + return LFS_ERR_CORRUPT; + } + } + + data += diff; + off += diff; + size -= diff; + continue; + } + + // prepare pcache, first condition can no longer fail + pcache->block = block; + pcache->off = off - (off % lfs->cfg->prog_size); + } + + return 0; +} + + +/// General lfs block device operations /// +static int lfs_bd_read(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size) { + // if we ever do more than writes to alternating pairs, + // this may need to consider pcache + return lfs_cache_read(lfs, &lfs->rcache, NULL, + block, off, buffer, size); +} + +static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + return lfs_cache_prog(lfs, &lfs->pcache, NULL, + block, off, buffer, size); +} + +static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + return lfs_cache_cmp(lfs, &lfs->rcache, NULL, block, off, buffer, size); +} + +static int lfs_bd_crc(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, lfs_size_t size, uint32_t *crc) { + return lfs_cache_crc(lfs, &lfs->rcache, NULL, block, off, size, crc); +} + +static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { + return lfs->cfg->erase(lfs->cfg, block); +} + +static int lfs_bd_sync(lfs_t *lfs) { + lfs->rcache.block = 0xffffffff; + + int err = lfs_cache_flush(lfs, &lfs->pcache, NULL); + if (err) { + return err; + } + + return lfs->cfg->sync(lfs->cfg); +} + + +/// Internal operations predeclared here /// +int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); +static int lfs_pred(lfs_t *lfs, const lfs_block_t dir[2], lfs_dir_t *pdir); +static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2], + lfs_dir_t *parent, lfs_entry_t *entry); +static int lfs_moved(lfs_t *lfs, const void *e); +static int lfs_relocate(lfs_t *lfs, + const lfs_block_t oldpair[2], const lfs_block_t newpair[2]); +int lfs_deorphan(lfs_t *lfs); + + +/// Block allocator /// +static int lfs_alloc_lookahead(void *p, lfs_block_t block) { + lfs_t *lfs = p; + + lfs_block_t off = (((lfs_soff_t)(block - lfs->free.begin) + % (lfs_soff_t)(lfs->cfg->block_count)) + + lfs->cfg->block_count) % lfs->cfg->block_count; + + if (off < lfs->free.size) { + lfs->free.buffer[off / 32] |= 1U << (off % 32); + } + + return 0; +} + +//--------------------------------------------- +int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { + while (true) { + while (lfs->free.off != lfs->free.size) { + lfs_block_t off = lfs->free.off; + lfs->free.off += 1; + + if (!(lfs->free.buffer[off / 32] & (1U << (off % 32)))) { + // found a free block + *block = (lfs->free.begin + off) % lfs->cfg->block_count; + return 0; + } + } + + // check if we have looked at all blocks since last ack + if (lfs->free.off == lfs->free.ack - lfs->free.begin) { + LFS_WARN("No more free space %d", lfs->free.off + lfs->free.begin); + return LFS_ERR_NOSPC; + } + + lfs->free.begin += lfs->free.size; + lfs->free.size = lfs_min(lfs->cfg->lookahead, + lfs->free.ack - lfs->free.begin); + lfs->free.off = 0; + + // find mask of free blocks from tree + memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); + int err = lfs_traverse(lfs, lfs_alloc_lookahead, lfs); + if (err) { + return err; + } + } +} + +static void lfs_alloc_ack(lfs_t *lfs) { + lfs->free.ack = lfs->free.off-1 + lfs->free.begin + lfs->cfg->block_count; +} + + +/// Endian swapping functions /// +static void lfs_dir_fromle32(struct lfs_disk_dir *d) { + d->rev = lfs_fromle32(d->rev); + d->size = lfs_fromle32(d->size); + d->tail[0] = lfs_fromle32(d->tail[0]); + d->tail[1] = lfs_fromle32(d->tail[1]); +} + +static void lfs_dir_tole32(struct lfs_disk_dir *d) { + d->rev = lfs_tole32(d->rev); + d->size = lfs_tole32(d->size); + d->tail[0] = lfs_tole32(d->tail[0]); + d->tail[1] = lfs_tole32(d->tail[1]); +} + +static void lfs_entry_fromle32(struct lfs_disk_entry *d) { + d->u.dir[0] = lfs_fromle32(d->u.dir[0]); + d->u.dir[1] = lfs_fromle32(d->u.dir[1]); +} + +static void lfs_entry_tole32(struct lfs_disk_entry *d) { + d->u.dir[0] = lfs_tole32(d->u.dir[0]); + d->u.dir[1] = lfs_tole32(d->u.dir[1]); +} + +static void lfs_superblock_fromle32(struct lfs_disk_superblock *d) { + d->root[0] = lfs_fromle32(d->root[0]); + d->root[1] = lfs_fromle32(d->root[1]); + d->block_size = lfs_fromle32(d->block_size); + d->block_count = lfs_fromle32(d->block_count); + d->version = lfs_fromle32(d->version); +} + +static void lfs_superblock_tole32(struct lfs_disk_superblock *d) { + d->root[0] = lfs_tole32(d->root[0]); + d->root[1] = lfs_tole32(d->root[1]); + d->block_size = lfs_tole32(d->block_size); + d->block_count = lfs_tole32(d->block_count); + d->version = lfs_tole32(d->version); +} + + +/// Metadata pair and directory operations /// +static inline void lfs_pairswap(lfs_block_t pair[2]) { + lfs_block_t t = pair[0]; + pair[0] = pair[1]; + pair[1] = t; +} + +static inline bool lfs_pairisnull(const lfs_block_t pair[2]) { + return pair[0] == 0xffffffff || pair[1] == 0xffffffff; +} + +static inline int lfs_paircmp( + const lfs_block_t paira[2], + const lfs_block_t pairb[2]) { + return !(paira[0] == pairb[0] || paira[1] == pairb[1] || + paira[0] == pairb[1] || paira[1] == pairb[0]); +} + +static inline bool lfs_pairsync( + const lfs_block_t paira[2], + const lfs_block_t pairb[2]) { + return (paira[0] == pairb[0] && paira[1] == pairb[1]) || + (paira[0] == pairb[1] && paira[1] == pairb[0]); +} + +static inline lfs_size_t lfs_entry_size(const lfs_entry_t *entry) { + return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; +} + +static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) { + // allocate pair of dir blocks + for (int i = 0; i < 2; i++) { + int err = lfs_alloc(lfs, &dir->pair[i]); + if (err) { + return err; + } + } + + // rather than clobbering one of the blocks we just pretend + // the revision may be valid + int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->d.rev, 4); + dir->d.rev = lfs_fromle32(dir->d.rev); + if (err) { + return err; + } + + // set defaults + dir->d.rev += 1; + dir->d.size = sizeof(dir->d)+4; + dir->d.tail[0] = 0xffffffff; + dir->d.tail[1] = 0xffffffff; + dir->off = sizeof(dir->d); + + // don't write out yet, let caller take care of that + return 0; +} + +static int lfs_dir_fetch(lfs_t *lfs, + lfs_dir_t *dir, const lfs_block_t pair[2]) { + // copy out pair, otherwise may be aliasing dir + const lfs_block_t tpair[2] = {pair[0], pair[1]}; + bool valid = false; + + // check both blocks for the most recent revision + for (int i = 0; i < 2; i++) { + struct lfs_disk_dir test; + int err = lfs_bd_read(lfs, tpair[i], 0, &test, sizeof(test)); + lfs_dir_fromle32(&test); + if (err) { + return err; + } + + if (valid && lfs_scmp(test.rev, dir->d.rev) < 0) { + continue; + } + + if ((0x7fffffff & test.size) < sizeof(test)+4 || + (0x7fffffff & test.size) > lfs->cfg->block_size) { + continue; + } + + uint32_t crc = 0xffffffff; + lfs_dir_tole32(&test); + lfs_crc(&crc, &test, sizeof(test)); + lfs_dir_fromle32(&test); + err = lfs_bd_crc(lfs, tpair[i], sizeof(test), + (0x7fffffff & test.size) - sizeof(test), &crc); + if (err) { + return err; + } + + if (crc != 0) { + continue; + } + + valid = true; + + // setup dir in case it's valid + dir->pair[0] = tpair[(i+0) % 2]; + dir->pair[1] = tpair[(i+1) % 2]; + dir->off = sizeof(dir->d); + dir->d = test; + } + + if (!valid) { + LFS_ERROR("Corrupted dir pair at %d %d", tpair[0], tpair[1]); + return LFS_ERR_CORRUPT; + } + + return 0; +} + +struct lfs_region { + lfs_off_t oldoff; + lfs_size_t oldlen; + const void *newdata; + lfs_size_t newlen; +}; + +static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, + const struct lfs_region *regions, int count) { + // increment revision count + dir->d.rev += 1; + + // keep pairs in order such that pair[0] is most recent + lfs_pairswap(dir->pair); + for (int i = 0; i < count; i++) { + dir->d.size += regions[i].newlen - regions[i].oldlen; + } + + const lfs_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; + bool relocated = false; + + while (true) { + if (true) { + int err = lfs_bd_erase(lfs, dir->pair[0]); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + uint32_t crc = 0xffffffff; + lfs_dir_tole32(&dir->d); + lfs_crc(&crc, &dir->d, sizeof(dir->d)); + err = lfs_bd_prog(lfs, dir->pair[0], 0, &dir->d, sizeof(dir->d)); + lfs_dir_fromle32(&dir->d); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + int i = 0; + lfs_off_t oldoff = sizeof(dir->d); + lfs_off_t newoff = sizeof(dir->d); + while (newoff < (0x7fffffff & dir->d.size)-4) { + if (i < count && regions[i].oldoff == oldoff) { + lfs_crc(&crc, regions[i].newdata, regions[i].newlen); + err = lfs_bd_prog(lfs, dir->pair[0], + newoff, regions[i].newdata, regions[i].newlen); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + oldoff += regions[i].oldlen; + newoff += regions[i].newlen; + i += 1; + } else { + uint8_t data; + err = lfs_bd_read(lfs, oldpair[1], oldoff, &data, 1); + if (err) { + return err; + } + + lfs_crc(&crc, &data, 1); + err = lfs_bd_prog(lfs, dir->pair[0], newoff, &data, 1); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + oldoff += 1; + newoff += 1; + } + } + + crc = lfs_tole32(crc); + err = lfs_bd_prog(lfs, dir->pair[0], newoff, &crc, 4); + crc = lfs_fromle32(crc); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + err = lfs_bd_sync(lfs); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // successful commit, check checksum to make sure + uint32_t ncrc = 0xffffffff; + err = lfs_bd_crc(lfs, dir->pair[0], 0, + (0x7fffffff & dir->d.size)-4, &ncrc); + if (err) { + return err; + } + + if (ncrc != crc) { + goto relocate; + } + } + + break; +relocate: + //commit was corrupted + LFS_DEBUG("Bad block at %d", dir->pair[0]); + + // drop caches and prepare to relocate block + relocated = true; + lfs->pcache.block = 0xffffffff; + + // can't relocate superblock, filesystem is now frozen + if (lfs_paircmp(oldpair, (const lfs_block_t[2]){0, 1}) == 0) { + LFS_WARN("Superblock %d has become unwritable", oldpair[0]); + return LFS_ERR_CORRUPT; + } + + // relocate half of pair + int err = lfs_alloc(lfs, &dir->pair[0]); + if (err) { + return err; + } + } + + if (relocated) { + // update references if we relocated + LFS_DEBUG("Relocating %d %d to %d %d", + oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); + int err = lfs_relocate(lfs, oldpair, dir->pair); + if (err) { + return err; + } + } + + // shift over any directories that are affected + for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { + if (lfs_paircmp(d->pair, dir->pair) == 0) { + d->pair[0] = dir->pair[0]; + d->pair[1] = dir->pair[1]; + } + } + + return 0; +} + +//--------------------------------------------------- +static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, + lfs_entry_t *entry, const void *data, const void *attribute) { + lfs_entry_tole32(&entry->d); + int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, + {entry->off+sizeof(entry->d), entry->d.alen, attribute, entry->d.alen}, + {entry->off+sizeof(entry->d)+entry->d.alen, entry->d.nlen, data, entry->d.nlen} + }, data ? 3 : attribute ? 2 : 1); + lfs_entry_fromle32(&entry->d); + return err; +} + +//------------------------------------------------------------------------------------------------------------------ +static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, const void *data, const void *attribute) { + // check if we fit, if top bit is set we do not and move on + while (true) { + if (dir->d.size + lfs_entry_size(entry) <= lfs->cfg->block_size) { + entry->off = dir->d.size - 4; + + lfs_entry_tole32(&entry->d); + int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, 0, &entry->d, sizeof(entry->d)}, + {entry->off, 0, attribute, entry->d.alen}, + {entry->off, 0, data, entry->d.nlen} + }, 3); + lfs_entry_fromle32(&entry->d); + return err; + } + + // we need to allocate a new dir block + if (!(0x80000000 & dir->d.size)) { + lfs_dir_t olddir = *dir; + int err = lfs_dir_alloc(lfs, dir); + if (err) { + return err; + } + + dir->d.tail[0] = olddir.d.tail[0]; + dir->d.tail[1] = olddir.d.tail[1]; + entry->off = dir->d.size - 4; + lfs_entry_tole32(&entry->d); + err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, 0, &entry->d, sizeof(entry->d)}, + {entry->off, 0, attribute, entry->d.alen}, + {entry->off, 0, data, entry->d.nlen} + }, 3); + lfs_entry_fromle32(&entry->d); + if (err) { + return err; + } + + olddir.d.size |= 0x80000000; + olddir.d.tail[0] = dir->pair[0]; + olddir.d.tail[1] = dir->pair[1]; + return lfs_dir_commit(lfs, &olddir, NULL, 0); + } + + int err = lfs_dir_fetch(lfs, dir, dir->d.tail); + if (err) { + return err; + } + } +} + +static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { + // check if we should just drop the directory block + if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + + lfs_entry_size(entry)) { + lfs_dir_t pdir; + int res = lfs_pred(lfs, dir->pair, &pdir); + if (res < 0) { + return res; + } + + if (pdir.d.size & 0x80000000) { + pdir.d.size &= dir->d.size | 0x7fffffff; + pdir.d.tail[0] = dir->d.tail[0]; + pdir.d.tail[1] = dir->d.tail[1]; + return lfs_dir_commit(lfs, &pdir, NULL, 0); + } + } + + // shift out the entry + int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, lfs_entry_size(entry), NULL, 0}, + }, 1); + if (err) { + return err; + } + + // shift over any files/directories that are affected + for (lfs_file_t *f = lfs->files; f; f = f->next) { + if (lfs_paircmp(f->pair, dir->pair) == 0) { + if (f->poff == entry->off) { + f->pair[0] = 0xffffffff; + f->pair[1] = 0xffffffff; + } else if (f->poff > entry->off) { + f->poff -= lfs_entry_size(entry); + } + } + } + + for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { + if (lfs_paircmp(d->pair, dir->pair) == 0) { + if (d->off > entry->off) { + d->off -= lfs_entry_size(entry); + d->pos -= lfs_entry_size(entry); + } + } + } + + return 0; +} + +static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { + while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) { + if (!(0x80000000 & dir->d.size)) { + entry->off = dir->off; + return LFS_ERR_NOENT; + } + + int err = lfs_dir_fetch(lfs, dir, dir->d.tail); + if (err) { + return err; + } + + dir->off = sizeof(dir->d); + dir->pos += sizeof(dir->d) + 4; + } + + int err = lfs_bd_read(lfs, dir->pair[0], dir->off, + &entry->d, sizeof(entry->d)); + lfs_entry_fromle32(&entry->d); + if (err) { + return err; + } + + entry->off = dir->off; + dir->off += lfs_entry_size(entry); + dir->pos += lfs_entry_size(entry); + return 0; +} + +static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, + lfs_entry_t *entry, const char **path) { + const char *pathname = *path; + size_t pathlen; + + while (true) { + nextname: + // skip slashes + pathname += strspn(pathname, "/"); + pathlen = strcspn(pathname, "/"); + + // special case for root dir + if (pathname[0] == '\0') { + *entry = (lfs_entry_t){ + .d.type = LFS_TYPE_DIR, + .d.elen = sizeof(entry->d) - 4, + .d.alen = 0, + .d.nlen = 0, + .d.u.dir[0] = lfs->root[0], + .d.u.dir[1] = lfs->root[1], + }; + return 0; + } + + // skip '.' and root '..' + if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || + (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { + pathname += pathlen; + goto nextname; + } + + // skip if matched by '..' in name + const char *suffix = pathname + pathlen; + size_t sufflen; + int depth = 1; + while (true) { + suffix += strspn(suffix, "/"); + sufflen = strcspn(suffix, "/"); + if (sufflen == 0) { + break; + } + + if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { + depth -= 1; + if (depth == 0) { + pathname = suffix + sufflen; + goto nextname; + } + } else { + depth += 1; + } + + suffix += sufflen; + } + + // update what we've found + *path = pathname; + + // find path + while (true) { + int err = lfs_dir_next(lfs, dir, entry); + if (err) { + return err; + } + + if (((0x7f & entry->d.type) != LFS_TYPE_REG && + (0x7f & entry->d.type) != LFS_TYPE_DIR) || + entry->d.nlen != pathlen) { + continue; + } + + int res = lfs_bd_cmp(lfs, dir->pair[0], + entry->off + 4+entry->d.elen+entry->d.alen, + pathname, pathlen); + if (res < 0) { + return res; + } + + // found match + if (res) { + break; + } + } + + // check that entry has not been moved + if (entry->d.type & 0x80) { + int moved = lfs_moved(lfs, &entry->d.u); + if (moved < 0 || moved) { + return (moved < 0) ? moved : LFS_ERR_NOENT; + } + + entry->d.type &= ~0x80; + } + + pathname += pathlen; + pathname += strspn(pathname, "/"); + if (pathname[0] == '\0') { + return 0; + } + + // continue on if we hit a directory + if (entry->d.type != LFS_TYPE_DIR) { + return LFS_ERR_NOTDIR; + } + + int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir); + if (err) { + return err; + } + } +} + + +/// Top level directory operations /// + +//------------------------------------------- +int lfs_mkdir(lfs_t *lfs, const char *path) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + // fetch parent directory + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) { + return err ? err : LFS_ERR_EXIST; + } + + // build up new directory + lfs_alloc_ack(lfs); + + lfs_dir_t dir; + err = lfs_dir_alloc(lfs, &dir); + if (err) { + return err; + } + dir.d.tail[0] = cwd.d.tail[0]; + dir.d.tail[1] = cwd.d.tail[1]; + + err = lfs_dir_commit(lfs, &dir, NULL, 0); + if (err) { + return err; + } + + uint8_t attribute[ATTRIBUTE_LEN]; + entry.d.type = LFS_TYPE_DIR; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = lfs_dir_compute_attribute(attribute); + entry.d.nlen = strlen(path); + entry.d.u.dir[0] = dir.pair[0]; + entry.d.u.dir[1] = dir.pair[1]; + + cwd.d.tail[0] = dir.pair[0]; + cwd.d.tail[1] = dir.pair[1]; + + err = lfs_dir_append(lfs, &cwd, &entry, path, attribute); + if (err) { + return err; + } + + lfs_alloc_ack(lfs); + return 0; +} + +int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { + dir->pair[0] = lfs->root[0]; + dir->pair[1] = lfs->root[1]; + + int err = lfs_dir_fetch(lfs, dir, dir->pair); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, dir, &entry, &path); + if (err) { + return err; + } else if (entry.d.type != LFS_TYPE_DIR) { + return LFS_ERR_NOTDIR; + } + + err = lfs_dir_fetch(lfs, dir, entry.d.u.dir); + if (err) { + return err; + } + + // setup head dir + // special offset for '.' and '..' + dir->head[0] = dir->pair[0]; + dir->head[1] = dir->pair[1]; + dir->pos = sizeof(dir->d) - 2; + dir->off = sizeof(dir->d); + + // add to list of directories + dir->next = lfs->dirs; + lfs->dirs = dir; + + return 0; +} + +int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) { + // remove from list of directories + for (lfs_dir_t **p = &lfs->dirs; *p; p = &(*p)->next) { + if (*p == dir) { + *p = dir->next; + break; + } + } + + return 0; +} + +//------------------------------------------------------------------- +int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { + memset(info, 0, sizeof(*info)); + + // special offset for '.' and '..' + if (dir->pos == sizeof(dir->d) - 2) { + info->type = LFS_TYPE_DIR; + strcpy(info->name, "."); + dir->pos += 1; + return 1; + } else if (dir->pos == sizeof(dir->d) - 1) { + info->type = LFS_TYPE_DIR; + strcpy(info->name, ".."); + dir->pos += 1; + return 1; + } + + lfs_entry_t entry; + while (true) { + int err = lfs_dir_next(lfs, dir, &entry); + if (err) { + return (err == LFS_ERR_NOENT) ? 0 : err; + } + + if ((0x7f & entry.d.type) != LFS_TYPE_REG && + (0x7f & entry.d.type) != LFS_TYPE_DIR) { + continue; + } + + // check that entry has not been moved + if (entry.d.type & 0x80) { + int moved = lfs_moved(lfs, &entry.d.u); + if (moved < 0) { + return moved; + } + + if (moved) { + continue; + } + + entry.d.type &= ~0x80; + } + + break; + } + + info->type = entry.d.type; + if (info->type == LFS_TYPE_REG) { + info->size = entry.d.u.file.size; + } + + int err = 0; + if (entry.d.alen > 0) { + err = lfs_dir_extract_attribute(lfs, dir, &entry, info); + } + + err = lfs_bd_read(lfs, dir->pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); + if (err) { + return err; + } + + return 1; +} + +int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) { + // simply walk from head dir + int err = lfs_dir_rewind(lfs, dir); + if (err) { + return err; + } + dir->pos = off; + + while (off > (0x7fffffff & dir->d.size)) { + off -= 0x7fffffff & dir->d.size; + if (!(0x80000000 & dir->d.size)) { + return LFS_ERR_INVAL; + } + + err = lfs_dir_fetch(lfs, dir, dir->d.tail); + if (err) { + return err; + } + } + + dir->off = off; + return 0; +} + +lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) { + (void)lfs; + return dir->pos; +} + +int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) { + // reload the head dir + int err = lfs_dir_fetch(lfs, dir, dir->head); + if (err) { + return err; + } + + dir->pair[0] = dir->head[0]; + dir->pair[1] = dir->head[1]; + dir->pos = sizeof(dir->d) - 2; + dir->off = sizeof(dir->d); + return 0; +} + + +/// File index list operations /// +static int lfs_ctz_index(lfs_t *lfs, lfs_off_t *off) { + lfs_off_t size = *off; + lfs_off_t b = lfs->cfg->block_size - 2*4; + lfs_off_t i = size / b; + if (i == 0) { + return 0; + } + + i = (size - 4*(lfs_popc(i-1)+2)) / b; + *off = size - b*i - 4*lfs_popc(i); + return i; +} + +static int lfs_ctz_find(lfs_t *lfs, + lfs_cache_t *rcache, const lfs_cache_t *pcache, + lfs_block_t head, lfs_size_t size, + lfs_size_t pos, lfs_block_t *block, lfs_off_t *off) { + if (size == 0) { + *block = 0xffffffff; + *off = 0; + return 0; + } + + lfs_off_t current = lfs_ctz_index(lfs, &(lfs_off_t){size-1}); + lfs_off_t target = lfs_ctz_index(lfs, &pos); + + while (current > target) { + lfs_size_t skip = lfs_min( + lfs_npw2(current-target+1) - 1, + lfs_ctz(current)); + + int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4); + head = lfs_fromle32(head); + if (err) { + return err; + } + + LFS_ASSERT(head >= 2 && head <= lfs->cfg->block_count); + current -= 1 << skip; + } + + *block = head; + *off = pos; + return 0; +} + +//----------------------------------- +static int lfs_ctz_extend(lfs_t *lfs, + lfs_cache_t *rcache, lfs_cache_t *pcache, + lfs_block_t head, lfs_size_t size, + lfs_block_t *block, lfs_off_t *off) { + + memset(pcache->buffer, 0xFF, lfs->cfg->prog_size); + + while (true) { + // go ahead and grab a block + lfs_block_t nblock; + int err = lfs_alloc(lfs, &nblock); + if (err) { + return err; + } + LFS_ASSERT(nblock >= 2 && nblock <= lfs->cfg->block_count); + + if (true) { + err = lfs_bd_erase(lfs, nblock); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (size == 0) { + *block = nblock; + *off = 0; + return 0; + } + + size -= 1; + lfs_off_t index = lfs_ctz_index(lfs, &size); + size += 1; + + // just copy out the last block if it is incomplete + if (size != lfs->cfg->block_size) { + for (lfs_off_t i = 0; i < size; i++) { + uint8_t data; + err = lfs_cache_read(lfs, rcache, NULL, + head, i, &data, 1); + if (err) { + return err; + } + + err = lfs_cache_prog(lfs, pcache, rcache, + nblock, i, &data, 1); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + *block = nblock; + *off = size; + return 0; + } + + // append block + index += 1; + lfs_size_t skips = lfs_ctz(index) + 1; + + for (lfs_off_t i = 0; i < skips; i++) { + head = lfs_tole32(head); + err = lfs_cache_prog(lfs, pcache, rcache, + nblock, 4*i, &head, 4); + head = lfs_fromle32(head); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (i != skips-1) { + err = lfs_cache_read(lfs, rcache, NULL, + head, 4*i, &head, 4); + head = lfs_fromle32(head); + if (err) { + return err; + } + } + + LFS_ASSERT(head >= 2 && head <= lfs->cfg->block_count); + } + + *block = nblock; + *off = 4*skips; + return 0; + } + +relocate: + LFS_DEBUG("Bad block at %d", nblock); + + // just clear cache and try a new block + pcache->block = 0xffffffff; + } +} + +static int lfs_ctz_traverse(lfs_t *lfs, + lfs_cache_t *rcache, const lfs_cache_t *pcache, + lfs_block_t head, lfs_size_t size, + int (*cb)(void*, lfs_block_t), void *data) { + if (size == 0) { + return 0; + } + + lfs_off_t index = lfs_ctz_index(lfs, &(lfs_off_t){size-1}); + + while (true) { + int err = cb(data, head); + if (err) { + return err; + } + + if (index == 0) { + return 0; + } + + lfs_block_t heads[2]; + int count = 2 - (index & 1); + err = lfs_cache_read(lfs, rcache, pcache, head, 0, &heads, count*4); + heads[0] = lfs_fromle32(heads[0]); + heads[1] = lfs_fromle32(heads[1]); + if (err) { + return err; + } + + for (int i = 0; i < count-1; i++) { + err = cb(data, heads[i]); + if (err) { + return err; + } + } + + head = heads[count-1]; + index -= count; + } +} + + +/// Top level file operations /// + +//---------------------------------------------------------------------------- +int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) { + // deorphan if we haven't yet, needed at most once after poweron + if ((flags & 3) != LFS_O_RDONLY && !lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + // allocate entry for file if it doesn't exist + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) { + return err; + } + + if (err == LFS_ERR_NOENT) { + if (!(flags & LFS_O_CREAT)) { + return LFS_ERR_NOENT; + } + + uint8_t attribute[ATTRIBUTE_LEN]; + + // create entry to remember name + entry.d.type = LFS_TYPE_REG; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = lfs_dir_compute_attribute(attribute); + entry.d.nlen = strlen(path); + entry.d.u.file.head = 0xffffffff; + entry.d.u.file.size = 0; + err = lfs_dir_append(lfs, &cwd, &entry, path, attribute); + if (err) { + return err; + } + } + else if (entry.d.type == LFS_TYPE_DIR) { + return LFS_ERR_ISDIR; + } + else if (flags & LFS_O_EXCL) { + return LFS_ERR_EXIST; + } + + // setup file struct + file->pair[0] = cwd.pair[0]; + file->pair[1] = cwd.pair[1]; + file->poff = entry.off; + file->head = entry.d.u.file.head; + file->size = entry.d.u.file.size; + file->flags = flags; + file->pos = 0; + + if (flags & LFS_O_TRUNC) { + if (file->size != 0) { + file->flags |= LFS_F_DIRTY; + } + file->head = 0xffffffff; + file->size = 0; + } + + // allocate buffer if needed + file->cache.block = 0xffffffff; + if (lfs->cfg->file_buffer) { + file->cache.buffer = lfs->cfg->file_buffer; + } + else if ((file->flags & 3) == LFS_O_RDONLY) { + file->cache.buffer = lfs_malloc(lfs->cfg->read_size); + if (!file->cache.buffer) { + return LFS_ERR_NOMEM; + } + } + else { + file->cache.buffer = lfs_malloc(lfs->cfg->prog_size); + if (!file->cache.buffer) { + return LFS_ERR_NOMEM; + } + } + + // add to list of files + file->next = lfs->files; + lfs->files = file; + + return 0; +} + +int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { + int err = lfs_file_sync(lfs, file); + + // remove from list of files + for (lfs_file_t **p = &lfs->files; *p; p = &(*p)->next) { + if (*p == file) { + *p = file->next; + break; + } + } + + // clean up memory + if (!lfs->cfg->file_buffer) { + lfs_free(file->cache.buffer); + } + + return err; +} + +static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { +relocate: + LFS_DEBUG("Bad block at %d", file->block); + + // just relocate what exists into new block + lfs_block_t nblock; + int err = lfs_alloc(lfs, &nblock); + if (err) { + return err; + } + + err = lfs_bd_erase(lfs, nblock); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // either read from dirty cache or disk + for (lfs_off_t i = 0; i < file->off; i++) { + uint8_t data; + err = lfs_cache_read(lfs, &lfs->rcache, &file->cache, + file->block, i, &data, 1); + if (err) { + return err; + } + + err = lfs_cache_prog(lfs, &lfs->pcache, &lfs->rcache, + nblock, i, &data, 1); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + // copy over new state of file + memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->prog_size); + file->cache.block = lfs->pcache.block; + file->cache.off = lfs->pcache.off; + lfs->pcache.block = 0xffffffff; + + file->block = nblock; + return 0; +} + +static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { + if (file->flags & LFS_F_READING) { + // just drop read cache + file->cache.block = 0xffffffff; + file->flags &= ~LFS_F_READING; + } + + if (file->flags & LFS_F_WRITING) { + lfs_off_t pos = file->pos; + + // copy over anything after current branch + lfs_file_t orig = { + .head = file->head, + .size = file->size, + .flags = LFS_O_RDONLY, + .pos = file->pos, + .cache = lfs->rcache, + }; + lfs->rcache.block = 0xffffffff; + + while (file->pos < file->size) { + // copy over a byte at a time, leave it up to caching + // to make this efficient + uint8_t data; + lfs_ssize_t res = lfs_file_read(lfs, &orig, &data, 1); + if (res < 0) { + return res; + } + + res = lfs_file_write(lfs, file, &data, 1); + if (res < 0) { + return res; + } + + // keep our reference to the rcache in sync + if (lfs->rcache.block != 0xffffffff) { + orig.cache.block = 0xffffffff; + lfs->rcache.block = 0xffffffff; + } + } + + // write out what we have + while (true) { + int err = lfs_cache_flush(lfs, &file->cache, &lfs->rcache); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + break; +relocate: + err = lfs_file_relocate(lfs, file); + if (err) { + return err; + } + } + + // actual file updates + file->head = file->block; + file->size = file->pos; + file->flags &= ~LFS_F_WRITING; + file->flags |= LFS_F_DIRTY; + + file->pos = pos; + } + + return 0; +} + +//----------------------------------------------- +int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + + if ((file->flags & LFS_F_DIRTY) && + !(file->flags & LFS_F_ERRED) && + !lfs_pairisnull(file->pair)) { + // update dir entry + lfs_dir_t cwd; + err = lfs_dir_fetch(lfs, &cwd, file->pair); + if (err) { + return err; + } + + lfs_entry_t entry = {.off = file->poff}; + err = lfs_bd_read(lfs, cwd.pair[0], entry.off, + &entry.d, sizeof(entry.d)); + lfs_entry_fromle32(&entry.d); + if (err) { + return err; + } + + LFS_ASSERT(entry.d.type == LFS_TYPE_REG); + uint8_t attribute[ATTRIBUTE_LEN]; + entry.d.u.file.head = file->head; + entry.d.u.file.size = file->size; + entry.d.alen = lfs_dir_compute_attribute(attribute); + + err = lfs_dir_update(lfs, &cwd, &entry, NULL, attribute); + if (err) { + return err; + } + + file->flags &= ~LFS_F_DIRTY; + } + + return 0; +} + +lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, + void *buffer, lfs_size_t size) { + uint8_t *data = buffer; + lfs_size_t nsize = size; + + if ((file->flags & 3) == LFS_O_WRONLY) { + return LFS_ERR_BADF; + } + + if (file->flags & LFS_F_WRITING) { + // flush out any writes + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + } + + if (file->pos >= file->size) { + // eof if past end + return 0; + } + + size = lfs_min(size, file->size - file->pos); + nsize = size; + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS_F_READING) || + file->off == lfs->cfg->block_size) { + int err = lfs_ctz_find(lfs, &file->cache, NULL, + file->head, file->size, + file->pos, &file->block, &file->off); + if (err) { + return err; + } + + file->flags |= LFS_F_READING; + } + + // read as much as we can in current block + lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); + int err = lfs_cache_read(lfs, &file->cache, NULL, + file->block, file->off, data, diff); + if (err) { + return err; + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + } + + return size; +} + +lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, + const void *buffer, lfs_size_t size) { + const uint8_t *data = buffer; + lfs_size_t nsize = size; + + if ((file->flags & 3) == LFS_O_RDONLY) { + return LFS_ERR_BADF; + } + + if (file->flags & LFS_F_READING) { + // drop any reads + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + } + + if ((file->flags & LFS_O_APPEND) && file->pos < file->size) { + file->pos = file->size; + } + + if (!(file->flags & LFS_F_WRITING) && file->pos > file->size) { + // fill with zeros + lfs_off_t pos = file->pos; + file->pos = file->size; + + while (file->pos < pos) { + lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1); + if (res < 0) { + return res; + } + } + } + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS_F_WRITING) || + file->off == lfs->cfg->block_size) { + if (!(file->flags & LFS_F_WRITING) && file->pos > 0) { + // find out which block we're extending from + int err = lfs_ctz_find(lfs, &file->cache, NULL, + file->head, file->size, + file->pos-1, &file->block, &file->off); + if (err) { + file->flags |= LFS_F_ERRED; + return err; + } + + // mark cache as dirty since we may have read data into it + file->cache.block = 0xffffffff; + } + + // extend file with new blocks + lfs_alloc_ack(lfs); + int err = lfs_ctz_extend(lfs, &lfs->rcache, &file->cache, + file->block, file->pos, + &file->block, &file->off); + if (err) { + file->flags |= LFS_F_ERRED; + return err; + } + + file->flags |= LFS_F_WRITING; + } + + // program as much as we can in current block + lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); + while (true) { + int err = lfs_cache_prog(lfs, &file->cache, &lfs->rcache, + file->block, file->off, data, diff); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + file->flags |= LFS_F_ERRED; + return err; + } + + break; +relocate: + err = lfs_file_relocate(lfs, file); + if (err) { + file->flags |= LFS_F_ERRED; + return err; + } + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + + lfs_alloc_ack(lfs); + } + + file->flags &= ~LFS_F_ERRED; + return size; +} + +lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, + lfs_soff_t off, int whence) { + // write out everything beforehand, may be noop if rdonly + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + + // update pos + if (whence == LFS_SEEK_SET) { + file->pos = off; + } else if (whence == LFS_SEEK_CUR) { + if (off < 0 && (lfs_off_t)-off > file->pos) { + return LFS_ERR_INVAL; + } + + file->pos = file->pos + off; + } else if (whence == LFS_SEEK_END) { + if (off < 0 && (lfs_off_t)-off > file->size) { + return LFS_ERR_INVAL; + } + + file->pos = file->size + off; + } + + return file->pos; +} + +int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) { + if ((file->flags & 3) == LFS_O_RDONLY) { + return LFS_ERR_BADF; + } + + lfs_off_t oldsize = lfs_file_size(lfs, file); + if (size < oldsize) { + // need to flush since directly changing metadata + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + + // lookup new head in ctz skip list + err = lfs_ctz_find(lfs, &file->cache, NULL, + file->head, file->size, + size, &file->head, &(lfs_off_t){0}); + if (err) { + return err; + } + + file->size = size; + file->flags |= LFS_F_DIRTY; + } else if (size > oldsize) { + lfs_off_t pos = file->pos; + + // flush+seek if not already at end + if (file->pos != oldsize) { + int err = lfs_file_seek(lfs, file, 0, LFS_SEEK_END); + if (err < 0) { + return err; + } + } + + // fill with zeros + while (file->pos < size) { + lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1); + if (res < 0) { + return res; + } + } + + // restore pos + int err = lfs_file_seek(lfs, file, pos, LFS_SEEK_SET); + if (err < 0) { + return err; + } + } + + return 0; +} + +lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) { + (void)lfs; + return file->pos; +} + +int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) { + lfs_soff_t res = lfs_file_seek(lfs, file, 0, LFS_SEEK_SET); + if (res < 0) { + return res; + } + + return 0; +} + +lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) { + (void)lfs; + if (file->flags & LFS_F_WRITING) { + return lfs_max(file->pos, file->size); + } else { + return file->size; + } +} + + +/// General fs operations /// + +//----------------------------------------------------------------- +int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err) { + return err; + } + + memset(info, 0, sizeof(*info)); + info->type = entry.d.type; + if (info->type == LFS_TYPE_REG) { + info->size = entry.d.u.file.size; + } + + if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { + strcpy(info->name, "/"); + } else { + err = lfs_bd_read(lfs, cwd.pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); + if (err) { + return err; + } + } + if (entry.d.alen > 0){ + err = lfs_dir_extract_attribute(lfs, &cwd, &entry, info); + } + return 0; +} + +int lfs_remove(lfs_t *lfs, const char *path) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err) { + return err; + } + + lfs_dir_t dir; + if (entry.d.type == LFS_TYPE_DIR) { + // must be empty before removal, checking size + // without masking top bit checks for any case where + // dir is not empty + err = lfs_dir_fetch(lfs, &dir, entry.d.u.dir); + if (err) { + return err; + } else if (dir.d.size != sizeof(dir.d)+4) { + return LFS_ERR_NOTEMPTY; + } + } + + // remove the entry + err = lfs_dir_remove(lfs, &cwd, &entry); + if (err) { + return err; + } + + // if we were a directory, find pred, replace tail + if (entry.d.type == LFS_TYPE_DIR) { + int res = lfs_pred(lfs, dir.pair, &cwd); + if (res < 0) { + return res; + } + + LFS_ASSERT(res); // must have pred + cwd.d.tail[0] = dir.d.tail[0]; + cwd.d.tail[1] = dir.d.tail[1]; + + err = lfs_dir_commit(lfs, &cwd, NULL, 0); + if (err) { + return err; + } + } + + return 0; +} + +//-------------------------------------------------------------------- +int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + // find old entry + lfs_dir_t oldcwd; + int err = lfs_dir_fetch(lfs, &oldcwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t oldentry; + err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath); + if (err) { + return err; + } + + // allocate new entry + lfs_dir_t newcwd; + err = lfs_dir_fetch(lfs, &newcwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t preventry; + err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath); + if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) { + return err; + } + + bool prevexists = (err != LFS_ERR_NOENT); + bool samepair = (lfs_paircmp(oldcwd.pair, newcwd.pair) == 0); + + // must have same type + if (prevexists && preventry.d.type != oldentry.d.type) { + return LFS_ERR_ISDIR; + } + + lfs_dir_t dir; + if (prevexists && preventry.d.type == LFS_TYPE_DIR) { + // must be empty before removal, checking size + // without masking top bit checks for any case where + // dir is not empty + err = lfs_dir_fetch(lfs, &dir, preventry.d.u.dir); + if (err) { + return err; + } else if (dir.d.size != sizeof(dir.d)+4) { + return LFS_ERR_NOTEMPTY; + } + } + + // mark as moving + oldentry.d.type |= 0x80; + err = lfs_dir_update(lfs, &oldcwd, &oldentry, NULL, NULL); + if (err) { + return err; + } + + // update pair if newcwd == oldcwd + if (samepair) { + newcwd = oldcwd; + } + + // move to new location + uint8_t attribute[ATTRIBUTE_LEN]; + lfs_entry_t newentry = preventry; + newentry.d = oldentry.d; + newentry.d.type &= ~0x80; + newentry.d.nlen = strlen(newpath); + newentry.d.alen = lfs_dir_compute_attribute(attribute); + + if (prevexists) { + err = lfs_dir_update(lfs, &newcwd, &newentry, newpath, attribute); + if (err) { + return err; + } + } else { + err = lfs_dir_append(lfs, &newcwd, &newentry, newpath, attribute); + if (err) { + return err; + } + } + + // update pair if newcwd == oldcwd + if (samepair) { + oldcwd = newcwd; + } + + // remove old entry + err = lfs_dir_remove(lfs, &oldcwd, &oldentry); + if (err) { + return err; + } + + // if we were a directory, find pred, replace tail + if (prevexists && preventry.d.type == LFS_TYPE_DIR) { + int res = lfs_pred(lfs, dir.pair, &newcwd); + if (res < 0) { + return res; + } + + LFS_ASSERT(res); // must have pred + newcwd.d.tail[0] = dir.d.tail[0]; + newcwd.d.tail[1] = dir.d.tail[1]; + + err = lfs_dir_commit(lfs, &newcwd, NULL, 0); + if (err) { + return err; + } + } + + return 0; +} + + +/// Filesystem operations /// +static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { + lfs->cfg = cfg; + + // setup read cache + lfs->rcache.block = 0xffffffff; + if (lfs->cfg->read_buffer) { + lfs->rcache.buffer = lfs->cfg->read_buffer; + } else { + lfs->rcache.buffer = lfs_malloc(lfs->cfg->read_size); + if (!lfs->rcache.buffer) { + return LFS_ERR_NOMEM; + } + } + + // setup program cache + lfs->pcache.block = 0xffffffff; + if (lfs->cfg->prog_buffer) { + lfs->pcache.buffer = lfs->cfg->prog_buffer; + } else { + lfs->pcache.buffer = lfs_malloc(lfs->cfg->prog_size); + if (!lfs->pcache.buffer) { + return LFS_ERR_NOMEM; + } + } + + // setup lookahead, round down to nearest 32-bits + LFS_ASSERT(lfs->cfg->lookahead % 32 == 0); + LFS_ASSERT(lfs->cfg->lookahead > 0); + if (lfs->cfg->lookahead_buffer) { + lfs->free.buffer = lfs->cfg->lookahead_buffer; + } else { + lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8); + if (!lfs->free.buffer) { + return LFS_ERR_NOMEM; + } + } + + // check that program and read sizes are multiples of the block size + LFS_ASSERT(lfs->cfg->prog_size % lfs->cfg->read_size == 0); + LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->prog_size == 0); + + // check that the block size is large enough to fit ctz pointers + LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) + <= lfs->cfg->block_size); + + // setup default state + lfs->root[0] = 0xffffffff; + lfs->root[1] = 0xffffffff; + lfs->files = NULL; + lfs->dirs = NULL; + lfs->deorphaned = false; + + return 0; +} + +static int lfs_deinit(lfs_t *lfs) { + // free allocated memory + if (!lfs->cfg->read_buffer) { + lfs_free(lfs->rcache.buffer); + } + + if (!lfs->cfg->prog_buffer) { + lfs_free(lfs->pcache.buffer); + } + + if (!lfs->cfg->lookahead_buffer) { + lfs_free(lfs->free.buffer); + } + + return 0; +} + +//----------------------------- +void lfs_setup_free(lfs_t *lfs) +{ + // setup free lookahead + memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); + lfs->free.begin = 0; + lfs->free.size = 0; + lfs->free.off = 0; + lfs_alloc_ack(lfs); +} + +//-------------------------------------------------------- +int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { + int err = lfs_init(lfs, cfg); + if (err) { + return err; + } + + // create free lookahead + memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); + lfs->free.begin = 0; + lfs->free.size = lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count); + lfs->free.off = 0; + lfs_alloc_ack(lfs); + + // create superblock dir + lfs_dir_t superdir; + err = lfs_dir_alloc(lfs, &superdir); + if (err) { + return err; + } + + // write root directory + lfs_dir_t root; + err = lfs_dir_alloc(lfs, &root); + if (err) { + return err; + } + + err = lfs_dir_commit(lfs, &root, NULL, 0); + if (err) { + return err; + } + + lfs->root[0] = root.pair[0]; + lfs->root[1] = root.pair[1]; + + // write superblocks + lfs_superblock_t superblock = { + .off = sizeof(superdir.d), + .d.type = LFS_TYPE_SUPERBLOCK, + .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, + .d.nlen = sizeof(superblock.d.magic), + .d.version = LFS_DISK_VERSION, + .d.magic = {"littlefs"}, + .d.block_size = lfs->cfg->block_size, + .d.block_count = lfs->cfg->block_count, + .d.root = {lfs->root[0], lfs->root[1]}, + }; + superdir.d.tail[0] = root.pair[0]; + superdir.d.tail[1] = root.pair[1]; + superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4; + + // write both pairs to be safe + lfs_superblock_tole32(&superblock.d); + bool valid = false; + for (int i = 0; i < 2; i++) { + err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){ + {sizeof(superdir.d), sizeof(superblock.d), + &superblock.d, sizeof(superblock.d)} + }, 1); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + + valid = valid || !err; + } + + if (!valid) { + return LFS_ERR_CORRUPT; + } + + // sanity check that fetch works + err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1}); + if (err) { + return err; + } + + lfs_alloc_ack(lfs); + return lfs_deinit(lfs); +} + +//------------------------------------------------------- +int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { + int err = lfs_init(lfs, cfg); + if (err) { + return err; + } + + lfs_setup_free(lfs); + + // load superblock + lfs_dir_t dir; + lfs_superblock_t superblock; + err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); + if (err && err != LFS_ERR_CORRUPT) { + LFS_ERROR("Error fetching superblock at %d %d", 0, 1); + return err; + } + + if (!err) { + err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d), + &superblock.d, sizeof(superblock.d)); + lfs_superblock_fromle32(&superblock.d); + if (err) { + LFS_ERROR("Error reading superblock at %d %d", 0, 1); + return err; + } + + lfs->root[0] = superblock.d.root[0]; + lfs->root[1] = superblock.d.root[1]; + } + + if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) { + LFS_ERROR("Invalid superblock magic at %d %d", 0, 1); + return LFS_ERR_CORRUPT; + } + + uint16_t major_version = (0xffff & (superblock.d.version >> 16)); + uint16_t minor_version = (0xffff & (superblock.d.version >> 0)); + if ((major_version != LFS_DISK_VERSION_MAJOR || + minor_version != LFS_DISK_VERSION_MINOR)) { + LFS_ERROR("Invalid disk version %d.%d, expected %d.%d", major_version, minor_version, LFS_DISK_VERSION_MAJOR, LFS_DISK_VERSION_MINOR); + return LFS_ERR_INVAL; + } + + if (superblock.d.block_size != cfg->block_size) { + LFS_ERROR("Block size not matched [%u <> %u]", cfg->block_size, superblock.d.block_size); + return LFS_ERR_INVAL; + } + if (superblock.d.block_count != cfg->block_count) { + if (superblock.d.block_count < cfg->block_count) { + LFS_ERROR("Block count not matched [%u (configured) > %u (on disk)]", cfg->block_count, superblock.d.block_count); + return LFS_ERR_INVAL; + } + LFS_WARN("Block count not matched [%u (configured) <> %u (on disk)]", cfg->block_count, superblock.d.block_count); + // Adjust superblock block count + superblock.d.block_count = cfg->block_count; + // write both pairs to be safe + lfs_superblock_tole32(&superblock.d); + bool valid = false; + for (int i = 0; i < 2; i++) { + err = lfs_dir_commit(lfs, &dir, (struct lfs_region[]){ + {sizeof(dir.d), sizeof(superblock.d), + &superblock.d, sizeof(superblock.d)} + }, 1); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + + valid = valid || !err; + } + + if (!valid) { + return LFS_ERR_CORRUPT; + } + LFS_WARN("Block count adjusted to %u", cfg->block_count); + } + + return 0; +} + +int lfs_unmount(lfs_t *lfs) { + return lfs_deinit(lfs); +} + + +/// Littlefs specific operations /// +int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + // iterate over metadata pairs + lfs_dir_t dir; + lfs_entry_t entry; + lfs_block_t cwd[2] = {0, 1}; + + while (true) { + for (int i = 0; i < 2; i++) { + int err = cb(data, cwd[i]); + if (err) { + return err; + } + } + + int err = lfs_dir_fetch(lfs, &dir, cwd); + if (err) { + return err; + } + + // iterate over contents + while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { + err = lfs_bd_read(lfs, dir.pair[0], dir.off, + &entry.d, sizeof(entry.d)); + lfs_entry_fromle32(&entry.d); + if (err) { + return err; + } + + dir.off += lfs_entry_size(&entry); + if ((0x70 & entry.d.type) == (0x70 & LFS_TYPE_REG)) { + err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL, + entry.d.u.file.head, entry.d.u.file.size, cb, data); + if (err) { + return err; + } + } + } + + cwd[0] = dir.d.tail[0]; + cwd[1] = dir.d.tail[1]; + + if (lfs_pairisnull(cwd)) { + break; + } + } + + // iterate over any open files + for (lfs_file_t *f = lfs->files; f; f = f->next) { + if (f->flags & LFS_F_DIRTY) { + int err = lfs_ctz_traverse(lfs, &lfs->rcache, &f->cache, + f->head, f->size, cb, data); + if (err) { + return err; + } + } + + if (f->flags & LFS_F_WRITING) { + int err = lfs_ctz_traverse(lfs, &lfs->rcache, &f->cache, + f->block, f->pos, cb, data); + if (err) { + return err; + } + } + } + + return 0; +} + +static int lfs_pred(lfs_t *lfs, const lfs_block_t dir[2], lfs_dir_t *pdir) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + // iterate over all directory directory entries + int err = lfs_dir_fetch(lfs, pdir, (const lfs_block_t[2]){0, 1}); + if (err) { + return err; + } + + while (!lfs_pairisnull(pdir->d.tail)) { + if (lfs_paircmp(pdir->d.tail, dir) == 0) { + return true; + } + + err = lfs_dir_fetch(lfs, pdir, pdir->d.tail); + if (err) { + return err; + } + } + + return false; +} + +static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2], + lfs_dir_t *parent, lfs_entry_t *entry) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + parent->d.tail[0] = 0; + parent->d.tail[1] = 1; + + // iterate over all directory directory entries + while (!lfs_pairisnull(parent->d.tail)) { + int err = lfs_dir_fetch(lfs, parent, parent->d.tail); + if (err) { + return err; + } + + while (true) { + err = lfs_dir_next(lfs, parent, entry); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + if (err == LFS_ERR_NOENT) { + break; + } + + if (((0x70 & entry->d.type) == (0x70 & LFS_TYPE_DIR)) && + lfs_paircmp(entry->d.u.dir, dir) == 0) { + return true; + } + } + } + + return false; +} + +static int lfs_moved(lfs_t *lfs, const void *e) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + // skip superblock + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, (const lfs_block_t[2]){0, 1}); + if (err) { + return err; + } + + // iterate over all directory directory entries + lfs_entry_t entry; + while (!lfs_pairisnull(cwd.d.tail)) { + err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail); + if (err) { + return err; + } + + while (true) { + err = lfs_dir_next(lfs, &cwd, &entry); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + if (err == LFS_ERR_NOENT) { + break; + } + + if (!(0x80 & entry.d.type) && + memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) { + return true; + } + } + } + + return false; +} + +//----------------------------------------------------------------------------------------------- +static int lfs_relocate(lfs_t *lfs, const lfs_block_t oldpair[2], const lfs_block_t newpair[2]) { + // find parent + lfs_dir_t parent; + lfs_entry_t entry; + int res = lfs_parent(lfs, oldpair, &parent, &entry); + if (res < 0) { + return res; + } + + if (res) { + // update disk, this creates a desync + entry.d.u.dir[0] = newpair[0]; + entry.d.u.dir[1] = newpair[1]; + + int err = lfs_dir_update(lfs, &parent, &entry, NULL, NULL); + if (err) { + return err; + } + + // update internal root + if (lfs_paircmp(oldpair, lfs->root) == 0) { + LFS_DEBUG("Relocating root %d %d", newpair[0], newpair[1]); + lfs->root[0] = newpair[0]; + lfs->root[1] = newpair[1]; + } + + // clean up bad block, which should now be a desync + return lfs_deorphan(lfs); + } + + // find pred + res = lfs_pred(lfs, oldpair, &parent); + if (res < 0) { + return res; + } + + if (res) { + // just replace bad pair, no desync can occur + parent.d.tail[0] = newpair[0]; + parent.d.tail[1] = newpair[1]; + + return lfs_dir_commit(lfs, &parent, NULL, 0); + } + + // couldn't find dir, must be new + return 0; +} + +int lfs_deorphan(lfs_t *lfs) { + lfs->deorphaned = true; + + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + lfs_dir_t pdir = {.d.size = 0x80000000}; + lfs_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1}; + + // iterate over all directory directory entries + while (!lfs_pairisnull(cwd.d.tail)) { + int err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail); + if (err) { + return err; + } + + // check head blocks for orphans + if (!(0x80000000 & pdir.d.size)) { + // check if we have a parent + lfs_dir_t parent; + lfs_entry_t entry; + int res = lfs_parent(lfs, pdir.d.tail, &parent, &entry); + if (res < 0) { + return res; + } + + if (!res) { + // we are an orphan + LFS_DEBUG("Found orphan %d %d", + pdir.d.tail[0], pdir.d.tail[1]); + + pdir.d.tail[0] = cwd.d.tail[0]; + pdir.d.tail[1] = cwd.d.tail[1]; + + err = lfs_dir_commit(lfs, &pdir, NULL, 0); + if (err) { + return err; + } + + break; + } + + if (!lfs_pairsync(entry.d.u.dir, pdir.d.tail)) { + // we have desynced + LFS_DEBUG("Found desync %d %d", + entry.d.u.dir[0], entry.d.u.dir[1]); + + pdir.d.tail[0] = entry.d.u.dir[0]; + pdir.d.tail[1] = entry.d.u.dir[1]; + + err = lfs_dir_commit(lfs, &pdir, NULL, 0); + if (err) { + return err; + } + + break; + } + } + + // check entries for moves + lfs_entry_t entry; + while (true) { + err = lfs_dir_next(lfs, &cwd, &entry); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + if (err == LFS_ERR_NOENT) { + break; + } + + // found moved entry + if (entry.d.type & 0x80) { + int moved = lfs_moved(lfs, &entry.d.u); + if (moved < 0) { + return moved; + } + + if (moved) { + LFS_DEBUG("Found move %d %d", + entry.d.u.dir[0], entry.d.u.dir[1]); + err = lfs_dir_remove(lfs, &cwd, &entry); + if (err) { + return err; + } + } else { + LFS_DEBUG("Found partial move %d %d", + entry.d.u.dir[0], entry.d.u.dir[1]); + entry.d.type &= ~0x80; + err = lfs_dir_update(lfs, &cwd, &entry, NULL, NULL); + if (err) { + return err; + } + } + } + } + + memcpy(&pdir, &cwd, sizeof(pdir)); + } + + return 0; +} + +// ==== Attributes support ============================== + +//------------------------------------------------------ +static uint8_t lfs_dir_compute_attribute(uint8_t *buf) { + time_t now = time(NULL); + buf[0] = LFS_ATTRIBUTE_TIME; + buf[1] = now & 0xFF; + buf[2] = (now >> 8) & 0xFF; + buf[3] = (now >> 16) & 0xFF; + buf[4] = (now >> 24) & 0xFF; + + //LFS_DEBUG("compute attribute: time = %ld", now); + return ATTRIBUTE_LEN; +} + +//----------------------------------------------------------------------------------------------------------- +static int lfs_dir_extract_attribute(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, struct lfs_info *info) { + + uint8_t *attribute = lfs_malloc(entry->d.alen); + LFS_ASSERT(attribute); + if (attribute) { + int err = lfs_bd_read(lfs, dir->pair[0], + entry->off + 4 + entry->d.elen, + attribute, entry->d.alen); + if (err) { + lfs_free(attribute); + return err; + } + + // TODO search inside the attributes + if (entry->d.alen >= ATTRIBUTE_LEN) { + if (attribute[0] == LFS_ATTRIBUTE_TIME) { + info->time = + attribute[1] + attribute[2] * 256 + attribute[3] * 256 * 256 + attribute[4] * 256 * 256 * 256; + } + } + //LFS_DEBUG("extract attribute: alen = %u, time = %d", entry->d.alen, info->time); + lfs_free(attribute); + } + + return 0; +} + + diff --git a/MicroPython_BUILD/components/littlefs/lfs.h b/MicroPython_BUILD/components/littlefs/lfs.h new file mode 100644 index 00000000..5380cbd4 --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/lfs.h @@ -0,0 +1,495 @@ +/* + * The little filesystem + * + * Copyright (c) 2017 ARM Limited + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LFS_H +#define LFS_H + +#include +#include + + +/// Version info /// + +// Software library version +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS_VERSION 0x00010004 +#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16)) +#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0)) + +// Version of On-disk data structures +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS_DISK_VERSION 0x00010002 +#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16)) +#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0)) + + +/// Definitions /// + +// Type definitions +typedef uint32_t lfs_size_t; +typedef uint32_t lfs_off_t; + +typedef int32_t lfs_ssize_t; +typedef int32_t lfs_soff_t; + +typedef uint32_t lfs_block_t; + +typedef uint32_t lfs_time_t; + +// Max name size in bytes +#ifndef LFS_NAME_MAX +#define LFS_NAME_MAX 255 +#endif + +// Possible error codes, these are negative to allow +// valid positive return values +enum lfs_error { + LFS_ERR_OK = 0, // No error + LFS_ERR_IO = -5, // Error during device operation + LFS_ERR_CORRUPT = -52, // Corrupted + LFS_ERR_NOENT = -2, // No directory entry + LFS_ERR_EXIST = -17, // Entry already exists + LFS_ERR_NOTDIR = -20, // Entry is not a dir + LFS_ERR_ISDIR = -21, // Entry is a dir + LFS_ERR_NOTEMPTY = -39, // Dir is not empty + LFS_ERR_BADF = -9, // Bad file number + LFS_ERR_INVAL = -22, // Invalid parameter + LFS_ERR_NOSPC = -28, // No space left on device + LFS_ERR_NOMEM = -12, // No more memory available +}; + +// File types +enum lfs_type { + LFS_TYPE_REG = 0x11, + LFS_TYPE_DIR = 0x22, + LFS_TYPE_SUPERBLOCK = 0x2e, +}; + +// Attribute types +enum lfs_attribute { + LFS_ATTRIBUTE_TIME = 0xC1, +}; + +// File open flags +enum lfs_open_flags { + // open flags + LFS_O_RDONLY = 1, // Open a file as read only + LFS_O_WRONLY = 2, // Open a file as write only + LFS_O_RDWR = 3, // Open a file as read and write + LFS_O_CREAT = 0x0100, // Create a file if it does not exist + LFS_O_EXCL = 0x0200, // Fail if a file already exists + LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size + LFS_O_APPEND = 0x0800, // Move to end of file on every write + + // internally used flags + LFS_F_DIRTY = 0x10000, // File does not match storage + LFS_F_WRITING = 0x20000, // File has been written since last flush + LFS_F_READING = 0x40000, // File has been read since last flush + LFS_F_ERRED = 0x80000, // An error occured during write +}; + +// File seek flags +enum lfs_whence_flags { + LFS_SEEK_SET = 0, // Seek relative to an absolute position + LFS_SEEK_CUR = 1, // Seek relative to the current file position + LFS_SEEK_END = 2, // Seek relative to the end of the file +}; + + +// Configuration provided during initialization of the littlefs +struct lfs_config { + // Opaque user provided context that can be used to pass + // information to the block device operations + void *context; + + // Read a region in a block. Negative error codes are propogated + // to the user. + int (*read)(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size); + + // Program a region in a block. The block must have previously + // been erased. Negative error codes are propogated to the user. + // May return LFS_ERR_CORRUPT if the block should be considered bad. + int (*prog)(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size); + + // Erase a block. A block must be erased before being programmed. + // The state of an erased block is undefined. Negative error codes + // are propogated to the user. + // May return LFS_ERR_CORRUPT if the block should be considered bad. + int (*erase)(const struct lfs_config *c, lfs_block_t block); + + // Sync the state of the underlying block device. Negative error codes + // are propogated to the user. + int (*sync)(const struct lfs_config *c); + + // Minimum size of a block read. This determines the size of read buffers. + // This may be larger than the physical read size to improve performance + // by caching more of the block device. + lfs_size_t read_size; + + // Minimum size of a block program. This determines the size of program + // buffers. This may be larger than the physical program size to improve + // performance by caching more of the block device. + // Must be a multiple of the read size. + lfs_size_t prog_size; + + // Size of an erasable block. This does not impact ram consumption and + // may be larger than the physical erase size. However, this should be + // kept small as each file currently takes up an entire block. + // Must be a multiple of the program size. + lfs_size_t block_size; + + // Number of erasable blocks on the device. + lfs_size_t block_count; + + // Number of blocks to lookahead during block allocation. A larger + // lookahead reduces the number of passes required to allocate a block. + // The lookahead buffer requires only 1 bit per block so it can be quite + // large with little ram impact. Should be a multiple of 32. + lfs_size_t lookahead; + + // Optional, statically allocated read buffer. Must be read sized. + void *read_buffer; + + // Optional, statically allocated program buffer. Must be program sized. + void *prog_buffer; + + // Optional, statically allocated lookahead buffer. Must be 1 bit per + // lookahead block. + void *lookahead_buffer; + + // Optional, statically allocated buffer for files. Must be program sized. + // If enabled, only one file may be opened at a time. + void *file_buffer; +}; + + +// File info structure +struct lfs_info { + // Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR + uint8_t type; + + // Size of the file, only valid for REG files + lfs_size_t size; + + // Name of the file stored as a null-terminated string + char name[LFS_NAME_MAX+1]; + + lfs_time_t time; +}; + + +/// littlefs data structures /// +typedef struct lfs_entry { + lfs_off_t off; + + struct lfs_disk_entry { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + union { + struct { + lfs_block_t head; + lfs_size_t size; + } file; + lfs_block_t dir[2]; + } u; + } d; +} lfs_entry_t; + +typedef struct lfs_cache { + lfs_block_t block; + lfs_off_t off; + uint8_t *buffer; +} lfs_cache_t; + +typedef struct lfs_file { + struct lfs_file *next; + lfs_block_t pair[2]; + lfs_off_t poff; + + lfs_block_t head; + lfs_size_t size; + + uint32_t flags; + lfs_off_t pos; + lfs_block_t block; + lfs_off_t off; + lfs_cache_t cache; +} lfs_file_t; + +typedef struct lfs_dir { + struct lfs_dir *next; + lfs_block_t pair[2]; + lfs_off_t off; + + lfs_block_t head[2]; + lfs_off_t pos; + + struct lfs_disk_dir { + uint32_t rev; + lfs_size_t size; + lfs_block_t tail[2]; + } d; +} lfs_dir_t; + +typedef struct lfs_superblock { + lfs_off_t off; + + struct lfs_disk_superblock { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + lfs_block_t root[2]; + uint32_t block_size; + uint32_t block_count; + uint32_t version; + char magic[8]; + } d; +} lfs_superblock_t; + +typedef struct lfs_free { + lfs_block_t begin; + lfs_block_t size; + lfs_block_t off; + lfs_block_t ack; + uint32_t *buffer; +} lfs_free_t; + +// The littlefs type +typedef struct lfs { + const struct lfs_config *cfg; + + lfs_block_t root[2]; + lfs_file_t *files; + lfs_dir_t *dirs; + + lfs_cache_t rcache; + lfs_cache_t pcache; + + lfs_free_t free; + bool deorphaned; +} lfs_t; + + +/// Filesystem functions /// + +// Format a block device with the littlefs +// +// Requires a littlefs object and config struct. This clobbers the littlefs +// object, and does not leave the filesystem mounted. +// +// Returns a negative error code on failure. +int lfs_format(lfs_t *lfs, const struct lfs_config *config); + +// Mounts a littlefs +// +// Requires a littlefs object and config struct. Multiple filesystems +// may be mounted simultaneously with multiple littlefs objects. Both +// lfs and config must be allocated while mounted. +// +// Returns a negative error code on failure. +int lfs_mount(lfs_t *lfs, const struct lfs_config *config); + +// Unmounts a littlefs +// +// Does nothing besides releasing any allocated resources. +// Returns a negative error code on failure. +int lfs_unmount(lfs_t *lfs); + +/// General operations /// + +// Removes a file or directory +// +// If removing a directory, the directory must be empty. +// Returns a negative error code on failure. +int lfs_remove(lfs_t *lfs, const char *path); + +// Rename or move a file or directory +// +// If the destination exists, it must match the source in type. +// If the destination is a directory, the directory must be empty. +// +// Note: If power loss occurs, it is possible that the file or directory +// will exist in both the oldpath and newpath simultaneously after the +// next mount. +// +// Returns a negative error code on failure. +int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath); + +// Find info about a file or directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a negative error code on failure. +int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info); + + +/// File operations /// + +// Open a file +// +// The mode that the file is opened in is determined +// by the flags, which are values from the enum lfs_open_flags +// that are bitwise-ored together. +// +// Returns a negative error code on failure. +int lfs_file_open(lfs_t *lfs, lfs_file_t *file, + const char *path, int flags); + +// Close a file +// +// Any pending writes are written out to storage as though +// sync had been called and releases any allocated resources. +// +// Returns a negative error code on failure. +int lfs_file_close(lfs_t *lfs, lfs_file_t *file); + +// Synchronize a file on storage +// +// Any pending writes are written out to storage. +// Returns a negative error code on failure. +int lfs_file_sync(lfs_t *lfs, lfs_file_t *file); + +// Read data from file +// +// Takes a buffer and size indicating where to store the read data. +// Returns the number of bytes read, or a negative error code on failure. +lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, + void *buffer, lfs_size_t size); + +// Write data to file +// +// Takes a buffer and size indicating the data to write. The file will not +// actually be updated on the storage until either sync or close is called. +// +// Returns the number of bytes written, or a negative error code on failure. +lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, + const void *buffer, lfs_size_t size); + +// Change the position of the file +// +// The change in position is determined by the offset and whence flag. +// Returns the old position of the file, or a negative error code on failure. +lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, + lfs_soff_t off, int whence); + +// Truncates the size of the file to the specified size +// +// Returns a negative error code on failure. +int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size); + +// Return the position of the file +// +// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR) +// Returns the position of the file, or a negative error code on failure. +lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file); + +// Change the position of the file to the beginning of the file +// +// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR) +// Returns a negative error code on failure. +int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file); + +// Return the size of the file +// +// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END) +// Returns the size of the file, or a negative error code on failure. +lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file); + + +/// Directory operations /// + +// Create a directory +// +// Returns a negative error code on failure. +int lfs_mkdir(lfs_t *lfs, const char *path); + +// Open a directory +// +// Once open a directory can be used with read to iterate over files. +// Returns a negative error code on failure. +int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path); + +// Close a directory +// +// Releases any allocated resources. +// Returns a negative error code on failure. +int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir); + +// Read an entry in the directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a negative error code on failure. +int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info); + +// Change the position of the directory +// +// The new off must be a value previous returned from tell and specifies +// an absolute offset in the directory seek. +// +// Returns a negative error code on failure. +int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off); + +// Return the position of the directory +// +// The returned offset is only meant to be consumed by seek and may not make +// sense, but does indicate the current position in the directory iteration. +// +// Returns the position of the directory, or a negative error code on failure. +lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir); + +// Change the position of the directory to the beginning of the directory +// +// Returns a negative error code on failure. +int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir); + + +/// Miscellaneous littlefs specific operations /// + +// Traverse through all blocks in use by the filesystem +// +// The provided callback will be called with each block address that is +// currently in use by the filesystem. This can be used to determine which +// blocks are in use or how much of the storage is available. +// +// Returns a negative error code on failure. +int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); + +// Prunes any recoverable errors that may have occured in the filesystem +// +// Not needed to be called by user unless an operation is interrupted +// but the filesystem is still mounted. This is already called on first +// allocation. +// +// Returns a negative error code on failure. +int lfs_deorphan(lfs_t *lfs); + + +// setup free lookahead +void lfs_setup_free(lfs_t *lfs); + +// Find the first free (unused) block +// return its number in *block +int lfs_alloc(lfs_t *lfs, lfs_block_t *block); + +#endif diff --git a/MicroPython_BUILD/components/littlefs/lfs_util.c b/MicroPython_BUILD/components/littlefs/lfs_util.c new file mode 100644 index 00000000..3a2a351b --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/lfs_util.c @@ -0,0 +1,42 @@ +/* + * lfs util functions + * + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "lfs_util.h" + +// Only compile if user does not provide custom config +#ifndef LFS_CONFIG + + +// Software CRC implementation with small lookup table +void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { + static const uint32_t rtable[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c, + }; + + const uint8_t *data = buffer; + + for (size_t i = 0; i < size; i++) { + *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf]; + *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf]; + } +} + + +#endif diff --git a/MicroPython_BUILD/components/littlefs/lfs_util.h b/MicroPython_BUILD/components/littlefs/lfs_util.h new file mode 100644 index 00000000..d28cad68 --- /dev/null +++ b/MicroPython_BUILD/components/littlefs/lfs_util.h @@ -0,0 +1,187 @@ +/* + * lfs utility functions + * + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LFS_UTIL_H +#define LFS_UTIL_H + +// Users can override lfs_util.h with their own configuration by defining +// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h). +// +// If LFS_CONFIG is used, none of the default utils will be emitted and must be +// provided by the config file. To start I would suggest copying lfs_util.h and +// modifying as needed. +#ifdef LFS_CONFIG +#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) +#define LFS_STRINGIZE2(x) #x +#include LFS_STRINGIZE(LFS_CONFIG) +#else + +// System includes +#include +#include +#include +#include "esp_log.h" + +#ifndef LFS_NO_MALLOC +#include +#endif +#ifndef LFS_NO_ASSERT +#include +#endif +#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR) +#include +#endif + +#define LFS_TAG "lfs.c" + +// Macros, may be replaced by system specific wrappers. Arguments to these +// macros must not have side-effects as the macros can be removed for a smaller +// code footprint + +// Logging functions +#ifndef LFS_NO_DEBUG +#define LFS_DEBUG(fmt, ...) \ + ESP_LOGD(LFS_TAG, "%d: " fmt, __LINE__, __VA_ARGS__) +#else +#define LFS_DEBUG(fmt, ...) +#endif + +#ifndef LFS_NO_WARN +#define LFS_WARN(fmt, ...) \ + ESP_LOGW(LFS_TAG, "%d: " fmt, __LINE__, __VA_ARGS__) +#else +#define LFS_WARN(fmt, ...) +#endif + +#ifndef LFS_NO_ERROR +#define LFS_ERROR(fmt, ...) \ + ESP_LOGE(LFS_TAG, "%d: " fmt, __LINE__, __VA_ARGS__) +#else +#define LFS_ERROR(fmt, ...) +#endif + +// Runtime assertions +#ifndef LFS_NO_ASSERT +#define LFS_ASSERT(test) assert(test) +#else +#define LFS_ASSERT(test) +#endif + + +// Builtin functions, these may be replaced by more efficient +// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more +// expensive basic C implementation for debugging purposes + +// Min/max functions for unsigned 32-bit numbers +static inline uint32_t lfs_max(uint32_t a, uint32_t b) { + return (a > b) ? a : b; +} + +static inline uint32_t lfs_min(uint32_t a, uint32_t b) { + return (a < b) ? a : b; +} + +// Find the next smallest power of 2 less than or equal to a +static inline uint32_t lfs_npw2(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return 32 - __builtin_clz(a-1); +#else + uint32_t r = 0; + uint32_t s; + a -= 1; + s = (a > 0xffff) << 4; a >>= s; r |= s; + s = (a > 0xff ) << 3; a >>= s; r |= s; + s = (a > 0xf ) << 2; a >>= s; r |= s; + s = (a > 0x3 ) << 1; a >>= s; r |= s; + return (r | (a >> 1)) + 1; +#endif +} + +// Count the number of trailing binary zeros in a +// lfs_ctz(0) may be undefined +static inline uint32_t lfs_ctz(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__) + return __builtin_ctz(a); +#else + return lfs_npw2((a & -a) + 1) - 1; +#endif +} + +// Count the number of binary ones in a +static inline uint32_t lfs_popc(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return __builtin_popcount(a); +#else + a = a - ((a >> 1) & 0x55555555); + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); + return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; +#endif +} + +// Find the sequence comparison of a and b, this is the distance +// between a and b ignoring overflow +static inline int lfs_scmp(uint32_t a, uint32_t b) { + return (int)(unsigned)(a - b); +} + +// Convert from 32-bit little-endian to native order +static inline uint32_t lfs_fromle32(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + return a; +#elif !defined(LFS_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + return __builtin_bswap32(a); +#else + return (((uint8_t*)&a)[0] << 0) | + (((uint8_t*)&a)[1] << 8) | + (((uint8_t*)&a)[2] << 16) | + (((uint8_t*)&a)[3] << 24); +#endif +} + +// Convert to 32-bit little-endian from native order +static inline uint32_t lfs_tole32(uint32_t a) { + return lfs_fromle32(a); +} + +// Calculate CRC-32 with polynomial = 0x04c11db7 +void lfs_crc(uint32_t *crc, const void *buffer, size_t size); + +// Allocate memory, only used if buffers are not provided to littlefs +static inline void *lfs_malloc(size_t size) { +#ifndef LFS_NO_MALLOC + return malloc(size); +#else + return NULL; +#endif +} + +// Deallocate memory, only used if buffers are not provided to littlefs +static inline void lfs_free(void *p) { +#ifndef LFS_NO_MALLOC + free(p); +#endif +} + + +#endif +#endif diff --git a/MicroPython_BUILD/components/micropython/Kconfig.projbuild b/MicroPython_BUILD/components/micropython/Kconfig.projbuild index bad49539..67194556 100644 --- a/MicroPython_BUILD/components/micropython/Kconfig.projbuild +++ b/MicroPython_BUILD/components/micropython/Kconfig.projbuild @@ -3,412 +3,696 @@ menu "MicroPython" string "Board name" default "ESP32 board" help - Hardware board mame + Hardware board mame config MICROPY_HW_MCU_NAME string "MCU name" default "ESP32" help - Hardware MCU mame + Hardware MCU mame config MICROPY_TIMEZONE string "Time zone" default "GMT0BST" help - Set the default time zone string used when updating the time from NTP server - You can use 'components/micropython/docs/zones.csv' - file to find the time zone string. - Use the second entry for your Region/city as the value set here. Example: - For Zagreb, the zones.csv file contains :"Europe/Zagreb","CET-1CEST,M3.5.0,M10.5.0/3". - You should put "CET-1CEST,M3.5.0,M10.5.0/3" or "CET-1CEST" as Time zone. + Set the default time zone string used when updating the time from NTP server + You can use 'components/micropython/docs/zones.csv' + file to find the time zone string. + Use the second entry for your Region/city as the value set here. Example: + For Zagreb, the zones.csv file contains :"Europe/Zagreb","CET-1CEST,M3.5.0,M10.5.0/3". + You should put "CET-1CEST,M3.5.0,M10.5.0/3" or "CET-1CEST" as Time zone. config MICROPY_USE_OTA bool "Use OTA partition layout" default n help - Use OTA partition layout and include OTA module into build + Use OTA partition layout and include OTA module into build config GPIO_INPUT_FORCE_FACTORY - bool "Use GPIO2 to force boot from Factory partition" - depends on MICROPY_USE_OTA + bool "Use GPIO pin to force boot from Factory partition" + depends on MICROPY_USE_OTA default no help - If OTA layout is enabled and OTA update has been executed - the system will boot from one of the OTA partition - To force boot from Factory partition GPIO2 must be high for 3 seconds during boot + If OTA layout is enabled and OTA update has been executed + the system will boot from one of the OTA partition + To force boot from Factory partition defined GPIO + must be on specified level for 3 seconds during boot + + config GPIO_PIN_FORCE_FACTORY + int "GPIO to force boot from Factory partition" + depends on GPIO_INPUT_FORCE_FACTORY + range 0 39 + default 0 + help + Set GPIO pin to be used to force boot from Factory partition + + config GPIO_LEVEL_FORCE_FACTORY + depends on GPIO_INPUT_FORCE_FACTORY + int "GPIO level to force boot from Factory partition" + range 0 1 + default 0 + help + Set GPIO pin level to force boot from Factory partition + + config BOOT_SET_LED + int "Activate LED (GPIO) on boot" + range -1 33 + default -1 + help + Set the GPIO pin to use as LED indication, switching on some device or any other purpose during boot + not used if set to -1 + + config BOOT_LED_ON + depends on BOOT_SET_LED >= 0 + int "Set boot LED On level" + range 0 1 + default 0 + help + Set to GPIO pin level for boot LED On state + + config BOOT_RESET_LED + depends on BOOT_SET_LED >= 0 + bool "Deactivate LED (GPIO) on MicroPython start" + default n + help + Deactivate the GPIO pin used for LED indication, switching on some device or any other purpose + after MicroPython starts menu "System settings" - config MICRO_PY_LOG_LEVEL - int - default 0 if MICRO_PY_LOG_LEVEL0 - default 1 if MICRO_PY_LOG_LEVEL1 - default 2 if MICRO_PY_LOG_LEVEL2 - default 3 if MICRO_PY_LOG_LEVEL3 - default 4 if MICRO_PY_LOG_LEVEL4 - default 5 if MICRO_PY_LOG_LEVEL5 - - choice - prompt "Set ESP32 log level" - default MICRO_PY_LOG_LEVEL2 - help - Select Log (debug) level - - config MICRO_PY_LOG_LEVEL0 - bool "None" - config MICRO_PY_LOG_LEVEL1 - bool "Error" - config MICRO_PY_LOG_LEVEL2 - bool "Warning" - config MICRO_PY_LOG_LEVEL3 - bool "Info" - config MICRO_PY_LOG_LEVEL4 - bool "Debug" - config MICRO_PY_LOG_LEVEL5 - bool "Verbose" - endchoice - - config MICROPY_RX_BUFFER_SIZE - int "RX buffer size" - range 256 4096 - default 1080 - help - Set the size of the stdin RX buffer in bytes - Minimum of 1080 bytes must be set if you want to use YModem module - - config MICROPY_USE_TASK_WDT - bool "Enable WatchDog for MicroPython task" - default y - help - Enable system WatchDog to monitor MicroPython task - - config MICROPY_USE_BOTH_CORES - bool "Use both cores for MicroPython tasks" - depends on !FREERTOS_UNICORE - default n - help - Run MicroPython tasks on both cores, if not selected MicroPython tasks are created pinned to one core - - config MICROPY_TASK_PRIORITY - int "Main task priority" - range 1 20 - default 5 - help - Set the priority of the main MicroPython task - - config MICROPY_STACK_SIZE - int "MicroPython stack size (KB)" - range 8 32 if !SPIRAM_SUPPORT - range 8 64 if SPIRAM_SUPPORT - default 20 - help - Set the size of the MicroPython stack in Kbytes. - - config MICROPY_HEAP_SIZE - int "MicroPython heap size (KB)" - range 48 96 if !SPIRAM_SUPPORT - range 48 74 if !SPIRAM_SUPPORT && MICROPY_USE_CURL && MICROPY_USE_CURL_TLS - range 512 3584 if SPIRAM_SUPPORT - default 80 if !SPIRAM_SUPPORT - default 72 if !SPIRAM_SUPPORT && MICROPY_USE_CURL && MICROPY_USE_CURL_TLS - default 2048 if SPIRAM_SUPPORT - help - Set the size of the MicroPython heap in Kbytes - If SPIRAM is not used, heap is allocated from DRAM and setting the heap size too large - may result in insuficient heap for C services like mqtt, gsm, curl... - - config MICROPY_THREAD_MAX_THREADS - int "Maximum number of threads" - range 1 16 - default 4 - help - Set the maximum number of threads that can run simultaneosly - - config MICROPY_THREAD_STACK_SIZE - int "Threads default stack size (KB)" - range 2 32 - default 4 - help - Set the default thread stack size. - Different stack size can be set when starting the thread - - config MICROPY_USE_TELNET - bool "Enable Telnet server" - default y - help - Enable Telnet server and REPL over telnet - - config MICROPY_USE_WEBSERVER - bool "Enable Web server (experimental)" - default n - help - Enable Web server (experimental) - - config MICROPY_USE_FTPSERVER - bool "Enable Ftp server" - default y - help - Enable Ftp server - - menu "FTP Server Configuration" - depends on MICROPY_USE_FTPSERVER - - config FTPSERVER_LOG_LEVEL - int - default 0 if FTPSERVER_LOG_LEVEL0 - default 1 if FTPSERVER_LOG_LEVEL1 - default 2 if FTPSERVER_LOG_LEVEL2 - default 3 if FTPSERVER_LOG_LEVEL3 - default 4 if FTPSERVER_LOG_LEVEL4 - - choice - prompt "Set FTP Server log level" - default FTPSERVER_LOG_LEVEL1 - help - Select Log (debug) level - - config FTPSERVER_LOG_LEVEL0 - bool "None" - config FTPSERVER_LOG_LEVEL1 - bool "Error" - config FTPSERVER_LOG_LEVEL2 - bool "Warning" - config FTPSERVER_LOG_LEVEL3 - bool "Info" - config FTPSERVER_LOG_LEVEL4 - bool "Debug" - endchoice - - config MICROPY_FTPSERVER_TIMEOUT - int "Ftp server connection timeout (seconds)" - range 60 3600 - default 300 - help - Disconnect ftp client if no activity for more than this timeout value - - config MICROPY_FTPSERVER_BUFFER_SIZE - int "Transfer buffer size (bytes)" - range 512 10240 - default 1024 - help - Transfer buffer size - Larger buffer enables faster transfer - endmenu + config MICRO_PY_LOG_LEVEL + int + default 0 if MICRO_PY_LOG_LEVEL0 + default 1 if MICRO_PY_LOG_LEVEL1 + default 2 if MICRO_PY_LOG_LEVEL2 + default 3 if MICRO_PY_LOG_LEVEL3 + default 4 if MICRO_PY_LOG_LEVEL4 + default 5 if MICRO_PY_LOG_LEVEL5 + + choice + prompt "Set ESP32 log level" + default MICRO_PY_LOG_LEVEL2 + help + Select Log (debug) level + + config MICRO_PY_LOG_LEVEL0 + bool "None" + config MICRO_PY_LOG_LEVEL1 + bool "Error" + config MICRO_PY_LOG_LEVEL2 + bool "Warning" + config MICRO_PY_LOG_LEVEL3 + bool "Info" + config MICRO_PY_LOG_LEVEL4 + bool "Debug" + config MICRO_PY_LOG_LEVEL5 + bool "Verbose" + endchoice + + config MICROPY_USE_TASK_WDT + bool "Enable WatchDog for MicroPython task" + default y + help + Enable system WatchDog to monitor MicroPython task + + config MICROPY_TASK_WDT_PANIC + bool "Invoke panic handler on MicroPython task Watchdog timeout" + depends on MICROPY_USE_TASK_WDT + default n + help + If this option is enabled, the Task Watchdog Timer will be configured to + trigger the panic handler when the MicroPython task times out. + + config MICROPY_USE_UNICODE + bool "Enable UNICODE support in MicroPython" + default y + help + Enable UNICODE support in MicroPython + Running without UNICODE support may solve some issues, + also the string operations may be faster + + config MICROPY_ENABLE_FINALISER + bool "Enable finalizer" + default y + help + Whether to enable finalisers in the garbage collector + If enabled, the __del__ methods of the objects will be called during garbage collect + + config MICROPY_GC_COLLECT_RETVAL + bool "gc.collect returns value" + default n + help + Whether to return number of collected objects from gc.collect() + If enabled, gc.collect will return the tuple of marked (used) and collected heap blocks + + config MICROPY_GC_SET_THRESHOLD + bool "Set GC threshold on boot" + default y + help + Set the automatic garbage collector threshold on boot + + config MICROPY_GC_THRESHOLD_VALUE + int "GC threshold percentage" + range 50 95 + default 90 + help + Default automatic garbage collector threshold value as percentage of the available heap + Threshold value can be changed at runtime using gc.threshold() function + + config MICROPY_SCHEDULER_DEPTH + int "Scheduler depth" + range 6 32 + default 8 + help + Maximum number of entries in the scheduler + + config MICROPY_PY_THREAD_GIL_VM_DIVISOR + int "Thread GIL VM divisor" + range 0 64 + default 32 + help + Number of VM jump-loops to do before releasing the GIL. + This affects the thread switching frequency. + If set to 0, disables the divisor. + + config MICROPY_RX_BUFFER_SIZE + int "RX buffer size" + range 256 4096 + default 1080 + help + Set the size of the stdin RX buffer in bytes + Minimum of 1080 bytes must be set if you want to use YModem module + + config MICROPY_USE_BOTH_CORES + bool "Use both cores for MicroPython tasks (experimental)" + depends on !FREERTOS_UNICORE + default n + help + Run MicroPython tasks on both cores, if not selected MicroPython tasks are created pinned to one core + WARNING: When enabled, it may introduce some issues with uasyncio and threads + There is no benefits from using it at the moment, so it is not recommended for now! + + config MICROPY_TASK_PRIORITY + int "Main task priority" + range 1 15 + default 5 + help + Set the priority of the main MicroPython task + + config MICROPY_STACK_SIZE + int "MicroPython stack size (KB)" + range 6 32 if !SPIRAM_SUPPORT + range 6 64 if SPIRAM_SUPPORT + default 16 + help + Set the default size of the MicroPython stack in Kbytes. + + config MICROPY_HEAP_SIZE + int "MicroPython heap size (KB)" + range 48 96 if !SPIRAM_SUPPORT + range 48 74 if !SPIRAM_SUPPORT && MICROPY_USE_CURL && MICROPY_USE_CURL_TLS + range 512 3840 if SPIRAM_SUPPORT + default 80 if !SPIRAM_SUPPORT + default 72 if !SPIRAM_SUPPORT && MICROPY_USE_CURL && MICROPY_USE_CURL_TLS + default 3072 if SPIRAM_SUPPORT + help + Set the default size of the MicroPython heap in Kbytes + If SPIRAM is not used, heap is allocated from DRAM and setting the heap size too large + may result in insuficient heap for C services like mqtt, gsm, curl... + + config MICROPY_THREAD_MAX_THREADS + int "Maximum number of threads" + range 1 16 + default 4 + help + Set the maximum number of threads that can run simultaneosly + + config MICROPY_THREAD_STACK_SIZE + int "Threads default stack size (KB)" + range 2 32 + default 4 + help + Set the default thread stack size. + Different stack size can be set when starting the thread + + config MICROPY_USE_TELNET + bool "Enable Telnet server" + default y + help + Enable Telnet server and REPL over telnet + + config MICROPY_USE_WEBSERVER + bool "Enable Web server (experimental)" + default n + help + Enable Web server (experimental) + + config MICROPY_USE_FTPSERVER + bool "Enable Ftp server" + default y + help + Enable Ftp server + + menu "FTP Server Configuration" + depends on MICROPY_USE_FTPSERVER + + config FTPSERVER_LOG_LEVEL + int + default 0 if FTPSERVER_LOG_LEVEL0 + default 1 if FTPSERVER_LOG_LEVEL1 + default 2 if FTPSERVER_LOG_LEVEL2 + default 3 if FTPSERVER_LOG_LEVEL3 + default 4 if FTPSERVER_LOG_LEVEL4 + + choice + prompt "Set FTP Server log level" + default FTPSERVER_LOG_LEVEL1 + help + Select Log (debug) level + + config FTPSERVER_LOG_LEVEL0 + bool "None" + config FTPSERVER_LOG_LEVEL1 + bool "Error" + config FTPSERVER_LOG_LEVEL2 + bool "Warning" + config FTPSERVER_LOG_LEVEL3 + bool "Info" + config FTPSERVER_LOG_LEVEL4 + bool "Debug" + endchoice + + config MICROPY_FTPSERVER_TIMEOUT + int "Ftp server connection timeout (seconds)" + range 60 3600 + default 300 + help + Disconnect ftp client if no activity for more than this timeout value + + config MICROPY_FTPSERVER_BUFFER_SIZE + int "Transfer buffer size (bytes)" + range 512 10240 + default 1024 + help + Transfer buffer size + Larger buffer enables faster transfer + endmenu endmenu menu "Modules" - config MICROPY_PY_FRAMEBUF - bool "Enable framebuffer" - default n - help - Include framebuffer module into build - - config MICROPY_PY_USE_BTREE - bool "Include Btree" - default n - help - Include Btree module into build - - config MICROPY_USE_WEBSOCKETS - bool "Use Websockets" - default n - help - Include websockets module into build - - config MICROPY_USE_DISPLAY - bool "Use Display module" - default n - help - Include Display module into build - Display module includes support for various SPI TFT displays - - config MICROPY_USE_EVE - bool "Use EVE display module (experimental, do not enable)" - default n - help - Include EVE display module into build - Display module includes support for EVE displays (FT80x, FT81x) - - config MICROPY_USE_GSM - bool "Use GSM module" - depends on PPP_SUPPORT - default n - help - Include GSM module and PPPoS support into build - - config MICROPY_USE_ETHERNET - bool "Use Ethernet module" - default n - help - Include Ethernet (network.LAN) module into build - - config MICROPY_USE_BLUETOOTH - bool "Use Bluetooth module (experimental, do not enable)" - depends on BT_ENABLED - default n - help - Include Bluetooth module into build - When using Bluetooth ~72 KB more RAM will be used, - it is not recommended to use it on boards without psRAM! - - config MICROPY_USE_MDNS - bool "Use mDNS module" - default y - help - Include mDNS module into build - - config MICROPY_USE_CURL - bool "Use Curl module" - default n - help - Include CURL module into build - Using CURLmodule will add ~230 KB to your flash code size - - config MICROPY_USE_CURL_TLS - bool "Enable TLS in Curl module" - depends on MICROPY_USE_CURL - default y if SPIRAM_SUPPORT - default n if !SPIRAM_SUPPORT - help - Enable SSL/TLS in CURL module - TLS support requires large amount RAM ! - If SPIRAM is not used, MicroPython heap size should not be set larger than 72KB ! - - config MICROPY_USE_CURLFTP - bool "FTP support in Curl module" - depends on MICROPY_USE_CURL - default n - help - Include Ftp support in Curl module - Not including it may save ~24 KB of flash code space - - config MICROPY_USE_MAIL - bool "MAIL support in Curl module" - depends on MICROPY_USE_CURL - default y - help - Include Mail support in Curl module - Mail support is based on 'quickmail' library which is licensed under GPL, - so you may want to exclude it from the build - - config MICROPY_USE_SSH - bool "Use SSH module" - default n - help - Include SSH module into build - Using SSH module will add ~86 KB to your flash code size - - config MICROPY_USE_MQTT - bool "Use Mqtt module" - default n - help - Include Mqtt module into build - - menu "MQTT Configuration" - depends on MICROPY_USE_MQTT - config MQTT_PROTOCOL_311 - bool "Use protocol version 3.1.1" - default y - help - Use protocol version 3.1.1 - If not set, protocol version 3.1.0 is used - - config MQTT_PRIORITY - int "MQTT task priority" - default MICROPY_TASK_PRIORITY - range 1 20 - help - FreeRTOS task priority of the Mqtt task - Default is MicroPython task priority - - config MQTT_BUFFER_SIZE_BYTE - int "MQTT send/receive buffer size" - default 256 - range 256 2048 - help - Send/Receive buffer size in bytes - More than buffer size bytes can be received... - Publish payload size is limited to this size. - Keep in mind that 4*CONFIG_MQTT_BUFFER_SIZE_BYTE queue buffer will also be created. - - config MQTT_MAX_PAYLOAD_SIZE - int "MQTT max payload size" - default 2048 - range MQTT_BUFFER_SIZE_BYTE 16384 - help - Maximum payload size which can be received - If the payload size is larger, it will be truncated - - config MQTT_LOG_LEVEL - int - default 0 if MQTT_LOG_LEVEL0 - default 1 if MQTT_LOG_LEVEL1 - default 2 if MQTT_LOG_LEVEL2 - default 3 if MQTT_LOG_LEVEL3 - default 4 if MQTT_LOG_LEVEL4 - - choice - prompt "Set Mqtt log level" - default MQTT_LOG_LEVEL1 - help - Select Log (debug) level - - config MQTT_LOG_LEVEL0 - bool "None" - config MQTT_LOG_LEVEL1 - bool "Error" - config MQTT_LOG_LEVEL2 - bool "Warning" - config MQTT_LOG_LEVEL3 - bool "Info" - config MQTT_LOG_LEVEL4 - bool "Debug" - endchoice - - endmenu - endmenu + config MICROPY_PY_FRAMEBUF + bool "Enable framebuffer" + default n + help + Include framebuffer module into build + + config MICROPY_PY_USE_BTREE + bool "Include Btree" + default n + help + Include Btree module into build + + config MICROPY_USE_WEBSOCKETS + bool "Use Websockets" + default n + help + Include websockets module into build + + config MICROPY_USE_DISPLAY + bool "Use Display module" + default n + help + Include Display module into build + + config MICROPY_USE_TFT + depends on MICROPY_USE_DISPLAY + bool "Enable support for SPI TFT displays" + default y + help + Include support for various SPI TFT displays + + config MICROPY_USE_EPD + depends on MICROPY_USE_DISPLAY + bool "Enable support for ePaper displays (NOT COMPLETE, DO NOT ENABLE)" + default n + help + Include support for ePaper displays into build + + config MICROPY_USE_EVE + depends on MICROPY_USE_DISPLAY + bool "Enable support for EVE (FT8xx) displays" + default n + help + Include support for EVE displays (FT80x, FT81x) + + config MICROPY_EVE_IC_TYPE + int + depends on MICROPY_USE_EVE + default 0 if EVE_CHIP_TYPE0 + default 1 if EVE_CHIP_TYPE1 + + choice + prompt "Select EVE IC type" + depends on MICROPY_USE_EVE + default EVE_CHIP_TYPE1 + help + Select the EVE IC type, FT80x or FT81x + + config EVE_CHIP_TYPE0 + bool "FT80x" + config EVE_CHIP_TYPE1 + bool "FT81x" + endchoice + + config EVE_MODE_TYPE + int + depends on MICROPY_USE_EVE + default 0 if FT8_USER_TYPE + default 1 if FT8_FT810CB_HY50HD + default 2 if FT8_FT811CB_HY50HD + default 3 if FT8_VM800B35A + default 4 if FT8_VM800B43A + default 5 if FT8_VM800B50A + default 6 if FT8_EVE2_50G + default 6 if FT8_EVE2_TEST + + choice + prompt "Select EVE display type" + depends on MICROPY_USE_EVE + default EVE_MODE_TYPE1 + help + Select predefined EVE display type or user type + If user type is selected, display configuration must be set using 'config' method + + config FT8_USER_TYPE + bool "User defined" + config FT8_FT810CB_HY50HD + bool "FT810CB-HY50HD: FT810 800x480 5\", HAOYU" + config FT8_FT811CB_HY50HD + bool "FT811CB-HY50HD: FT810 800x480 5\", HAOYU" + config FT8_VM800B35A + bool "VM800B35A: FT800 320x240 3.5\", FTDI" + config FT8_VM800B43A + bool "VM800B43A: FT800 480x272 4.4\", FTDI/BRT" + config FT8_VM800B50A + bool "VM800B50A: FT800 480x272 5\", FTDI/BRT" + config FT8_EVE2_50G + bool "800x480 5.0\" capacitive touch, FT813" + config FT8_EVE2_TEST + bool "TEST display" + endchoice + + config MICROPY_USE_GSM + bool "Use GSM module" + depends on PPP_SUPPORT + default n + help + Include GSM module and PPPoS support into build + + config MICROPY_USE_GPS + bool "Use GPS module" + default y + help + Include GPS module into build + + config MICROPY_GPS_SERVICE_STACK + int "GPS service stack size" + depends on MICROPY_USE_GPS + default 3072 + range 3072 6144 + help + Set the stack size of GPS service task + + config MICROPY_USE_ETHERNET + bool "Use Ethernet module" + default n + help + Include Ethernet (network.LAN) module into build + + config MICROPY_USE_BLUETOOTH + bool "Use BLE module (experimental, do not enable)" + depends on SPIRAM_SUPPORT && BT_ENABLED && BLUEDROID_ENABLED && GATTS_ENABLE && GATTC_ENABLE + default n + help + Include Bluetooth module into build + When using Bluetooth ~72 KB more RAM will be used + It can only be used on boards with psRAM + The used Flash size will increase by more than 500 KB if used + + config MICROPY_USE_RFCOMM + bool "Use RFCOMM module" + depends on SPIRAM_SUPPORT && BT_ENABLED && BLUEDROID_ENABLED && CLASSIC_BT_ENABLED && BT_SPP_ENABLED + default n + help + Include Bluetooth RFCOMM module into build + When using Bluetooth ~72 KB more RAM will be used + It can only be used on boards with psRAM + The used Flash size will increase by more than 500 KB if used + + config MICROPY_USE_MDNS + bool "Use mDNS module" + default y + help + Include mDNS module into build + + config MICROPY_USE_REQUESTS + bool "Use requests module" + default y + help + Include requests module into build + The module ofers less features than curl, but uses far les resources + + config MICROPY_USE_CURL + bool "Use Curl module" + default n + help + Include CURL module into build + Using CURL module will add ~230 KB to your flash code size + + config MICROPY_CURL_MAX_WRITE_SIZE + int "Curl max write buffer size" + depends on MICROPY_USE_CURL + range 1024 16384 + default 8192 + help + Curl buffer size used in many Curl functions + If not using SPIRAM, it may be necessary to set the size to the lower value + + config MICROPY_USE_CURL_TLS + bool "Enable TLS in Curl module" + depends on MICROPY_USE_CURL + default y if SPIRAM_SUPPORT + default n if !SPIRAM_SUPPORT + help + Enable SSL/TLS in CURL module + TLS support requires large amount RAM ! + If SPIRAM is not used, MicroPython heap size should not be set larger than 72KB ! + + config MICROPY_USE_CURLFTP + bool "FTP support in Curl module" + depends on MICROPY_USE_CURL + default n + help + Include Ftp support in Curl module + Not including it may save ~24 KB of flash code space + + config MICROPY_USE_SSH + bool "Use SSH module" + default n + help + Include SSH module into build + Using SSH module will add ~86 KB to your flash code size + + config MICROPY_USE_MQTT + bool "Use Mqtt module" + default n + help + Include Mqtt module into build + + menu "MQTT Configuration" + depends on MICROPY_USE_MQTT + config MQTT_PROTOCOL_311 + bool "Enable MQTT protocol 3.1.1" + default y + help + If not, this library will use MQTT protocol 3.1 + + config MQTT_TRANSPORT_SSL + bool "Enable MQTT over SSL" + default y + help + Enable MQTT transport over SSL with mbedtls + + config MQTT_TRANSPORT_WEBSOCKET + bool "Enable MQTT over Websocket" + default y + help + Enable MQTT transport over Websocket. + + config MQTT_TRANSPORT_WEBSOCKET_SECURE + bool "Enable MQTT over Websocket Secure" + default y + depends on MQTT_TRANSPORT_WEBSOCKET + depends on MQTT_TRANSPORT_SSL + help + Enable MQTT transport over Websocket Secure. + + config MQTT_USE_CUSTOM_CONFIG + bool "MQTT Using custom configurations" + default n + help + Custom MQTT configurations. + + config MQTT_TCP_DEFAULT_PORT + int "Default MQTT over TCP port" + default 1883 + depends on MQTT_USE_CUSTOM_CONFIG + help + Default MQTT over TCP port + + config MQTT_SSL_DEFAULT_PORT + int "Default MQTT over SSL port" + default 8883 + depends on MQTT_USE_CUSTOM_CONFIG + depends on MQTT_TRANSPORT_SSL + help + Default MQTT over SSL port + + config MQTT_WS_DEFAULT_PORT + int "Default MQTT over Websocket port" + default 80 + depends on MQTT_USE_CUSTOM_CONFIG + depends on MQTT_TRANSPORT_WEBSOCKET + help + Default MQTT over Websocket port + + config MQTT_WSS_DEFAULT_PORT + int "Default MQTT over Websocket Secure port" + default 443 + depends on MQTT_USE_CUSTOM_CONFIG + depends on MQTT_TRANSPORT_WEBSOCKET + depends on MQTT_TRANSPORT_WEBSOCKET_SECURE + help + Default MQTT over Websocket Secure port + + config MQTT_BUFFER_SIZE + int "Default MQTT Buffer Size" + default 1024 + depends on MQTT_USE_CUSTOM_CONFIG + help + This buffer size using for both transmit and receive + + config MQTT_TASK_STACK_SIZE + int "MQTT task stack size" + default 6144 + depends on MQTT_USE_CUSTOM_CONFIG + help + MQTT task stack size + + config MQTT_LOG_LEVEL + int + default 0 if MQTT_LOG_LEVEL0 + default 1 if MQTT_LOG_LEVEL1 + default 2 if MQTT_LOG_LEVEL2 + default 3 if MQTT_LOG_LEVEL3 + default 4 if MQTT_LOG_LEVEL4 + + choice + prompt "Set Mqtt log level" + default MQTT_LOG_LEVEL1 + help + Select Log (debug) level + + config MQTT_LOG_LEVEL0 + bool "None" + config MQTT_LOG_LEVEL1 + bool "Error" + config MQTT_LOG_LEVEL2 + bool "Warning" + config MQTT_LOG_LEVEL3 + bool "Info" + config MQTT_LOG_LEVEL4 + bool "Debug" + endchoice + + endmenu + endmenu menu "File systems" + config MICROPY_FILESYSTEM_TYPE + int + default 0 if MICROPY_FS_TYPE0 + default 1 if MICROPY_FS_TYPE1 + default 2 if MICROPY_FS_TYPE2 + + choice + prompt "Set internal filesystem type" + default MICROPY_FS_TYPE0 + help + Select internal file system type + + config MICROPY_FS_TYPE0 + bool "SPIFFS" + config MICROPY_FS_TYPE1 + bool "FatFS" + config MICROPY_FS_TYPE2 + bool "LittleFS" + endchoice + + config LITTLEFLASH_USE_WEAR_LEVELING + bool "Use LittleFS on top of ESP32 wear leveling" + depends on MICROPY_FILESYSTEM_TYPE = 2 + default y + help + LittleFS will be used on top of wear leveling system. + This options distributes wearing of the Flash sectors evenly over the whole file system partition. + It is RECOMMENDED to use this option. + Note: LittleFS block size will be the one selected for wear leveling + → Component config → Wear Levelling → Wear Levelling library sector size + With block size of 4096 bytes the operations will be faster, + but if lot of small files are used, more of the file system space will be wasted. + Block size of 512 bytes is more suited if small files are used, + but the file system operations will be slower. + config MICROPY_FATFS_MAX_OPEN_FILES int "Maximum number of opened files" range 4 24 default 6 help - Maximum number of opened files - - config MICROPY_USE_SPIFFS - bool "Use SPIFFS" - default y - help - Use spiffs on spi Flash instead of FatFS + Maximum number of opened files config MICROPY_SDMMC_SHOW_INFO bool "Show SDCard/InternalFS info" default y help - Show info after initializing SD card or internal FS - + Show info after initializing SD card or internal FS endmenu menu "SD Card configuration" - config SDCARD_MODE - int - default 1 if SDCARD_MODE1 - default 2 if SDCARD_MODE2 - default 3 if SDCARD_MODE3 - - choice - prompt "SD Card mode" - default SDCARD_MODE3 - help - Select SD Card operating mode - - config SDCARD_MODE1 - bool "SPI Mode" - depends on !MEMMAP_SPIRAM_ENABLE - config SDCARD_MODE2 - bool "1-line SD Mode" - config SDCARD_MODE3 - bool "4-line SD Mode" - endchoice + config SDCARD_MODE + int + default 1 if SDCARD_MODE1 + default 2 if SDCARD_MODE2 + default 3 if SDCARD_MODE3 + + choice + prompt "SD Card mode" + default SDCARD_MODE3 + help + Select SD Card operating mode + + config SDCARD_MODE1 + bool "SPI Mode" + depends on !MEMMAP_SPIRAM_ENABLE + config SDCARD_MODE2 + bool "1-line SD Mode" + config SDCARD_MODE3 + bool "4-line SD Mode" + endchoice + + config SDMMC_ALLOW_SPI_HIGHSPEED + bool "Allow hispeed in SPI mode" + default n + help + Allow using high speed mode when SD Card is configured in SPI mode config SDCARD_CLK int "CLK pin" @@ -416,7 +700,7 @@ menu "MicroPython" range 1 32 default 14 help - Pin used as SPI CLK + Pin used as SPI CLK config SDCARD_MOSI int "MOSI pin" @@ -424,7 +708,7 @@ menu "MicroPython" range 1 32 default 15 help - Pin used as SPI MOSI + Pin used as SPI MOSI config SDCARD_MISO int "MISO pin" @@ -432,7 +716,7 @@ menu "MicroPython" range 1 32 default 2 help - Pin used as SPI MISO + Pin used as SPI MISO config SDCARD_CS int "CS pin" @@ -440,6 +724,6 @@ menu "MicroPython" range 1 32 default 13 help - Pin used as SPI CS + Pin used as SPI CS endmenu endmenu diff --git a/MicroPython_BUILD/components/micropython/LICENSE b/MicroPython_BUILD/components/micropython/LICENSE index e3474e33..07c7dbe5 100644 --- a/MicroPython_BUILD/components/micropython/LICENSE +++ b/MicroPython_BUILD/components/micropython/LICENSE @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) 2013, 2014 Damien P. George +Copyright (c) 2018, LoBo (https://github.com/loboris) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/README.md b/MicroPython_BUILD/components/micropython/README.md new file mode 100644 index 00000000..9bfde4d6 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/README.md @@ -0,0 +1,58 @@ +# MicroPython for ESP32 + +# with support for 4MB of psRAM + + +**MicroPython core** is synchronized with [main MicroPython repository](https://github.com/micropython/micropython) + +**Commit:** bcfff4fc98a73c5ad9b7d3e338649955e861ada4 + +
+ +Some source files are changed to be compatible with this port.
+All modified files has the copyright notice:
+_Copyright (c) 2018 LoBo (https://github.com/loboris)_
+ +## List of the modified files: + +### **py** directory + +builtinhelp.c
+modmath.c
+modmicropython.c
+modsys.c
+modthread.c
+mpconfig.h
+mphal.h
+mpstate.h
+mpthread.h
+mpz.c
+mpz.h
+obj.c
+obj.h
+objint_mpz.c
+ringbuf.h
+runtime.h
+scheduler.c
+vm.c
+ +### **extmod** directory + +machine_pulse.c
+modbtree.c
+modframebuf.c
+modlwip.c
+moduhashlib.c
+moduselect.c
+modussl_mbedtls.c
+modutimeq.c
+utime_mphal.c
+utime_mphal.h
+vfs.c
+ +### **lib** directory + +utils/pyexec.c
+utils/sys_stdio_mphal.c
+mp-readline/readline.c
+ diff --git a/MicroPython_BUILD/components/micropython/component.mk b/MicroPython_BUILD/components/micropython/component.mk index 9881fbba..9bed5efe 100644 --- a/MicroPython_BUILD/components/micropython/component.mk +++ b/MicroPython_BUILD/components/micropython/component.mk @@ -7,10 +7,7 @@ COMPONENT_ADD_INCLUDEDIRS := . genhdr py esp32 lib lib/utils lib/mp-readline extmod extmod/crypto-algorithms lib/netutils drivers/dht \ lib/timeutils lib/berkeley-db-1.xx/include lib/berkeley-db-1.xx/btree \ lib/berkeley-db-1.xx/db lib/berkeley-db-1.xx/hash lib/berkeley-db-1.xx/man lib/berkeley-db-1.xx/mpool lib/berkeley-db-1.xx/recno \ - ../curl/include ../curl/lib ../zlib ../libssh2/include ../espmqtt/include -ifdef CONFIG_MICROPY_USE_MAIL -COMPONENT_ADD_INCLUDEDIRS += ../quickmail -endif + ../curl/include ../curl/lib ../zlib ../libssh2/include ../espmqtt/include ../espmqtt/lib/include ../littlefs COMPONENT_PRIV_INCLUDEDIRS := . genhdr py esp32 lib @@ -52,6 +49,8 @@ MP_EXTRA_INC += -I$(PROJECT_PATH)/components/curl/include MP_EXTRA_INC += -I$(PROJECT_PATH)/components/libssh2/include MP_EXTRA_INC += -I$(PROJECT_PATH)/components/zlib MP_EXTRA_INC += -I$(PROJECT_PATH)/components/espmqtt/include +MP_EXTRA_INC += -I$(PROJECT_PATH)/components/espmqtt/lib/include +MP_EXTRA_INC += -I$(PROJECT_PATH)/components/littlefs MP_EXTRA_INC += -I$(COMPONENT_PATH)/py MP_EXTRA_INC += -I$(COMPONENT_PATH)/lib/mp-readline MP_EXTRA_INC += -I$(COMPONENT_PATH)/lib/netutils @@ -84,7 +83,7 @@ MP_EXTRA_INC += -I$(ESPCOMP)/tcpip_adapter/include MP_EXTRA_INC += -I$(ESPCOMP)/lwip/include/lwip MP_EXTRA_INC += -I$(ESPCOMP)/lwip/include/lwip/port MP_EXTRA_INC += -I$(ESPCOMP)/lwip/include/lwip/posix -MP_EXTRA_INC += -I$(ESPCOMP)/mbedtls/include +MP_EXTRA_INC += -I$(ESPCOMP)/mbedtls/mbedtls/include MP_EXTRA_INC += -I$(ESPCOMP)/mbedtls/port/include MP_EXTRA_INC += -I$(ESPCOMP)/spi_flash/include MP_EXTRA_INC += -I$(ESPCOMP)/wear_levelling/include @@ -102,14 +101,25 @@ MP_EXTRA_INC += -I$(ESPCOMP)/heap/include MP_EXTRA_INC += -I$(ESPCOMP)/openssl/include MP_EXTRA_INC += -I$(ESPCOMP)/app_update/include MP_EXTRA_INC += -I$(ESPCOMP)/mdns/include - -ifdef CONFIG_MICROPY_USE_MAIL -MP_EXTRA_INC += -I$(PROJECT_PATH)/components/quickmail -endif +MP_EXTRA_INC += -I$(ESPCOMP)/esp_https_ota/include ifdef CONFIG_MICROPY_USE_BLUETOOTH MP_EXTRA_INC += -I$(ESPCOMP)/bt/include MP_EXTRA_INC += -I$(ESPCOMP)/bt/bluedroid/api/include +else +ifdef CONFIG_MICROPY_USE_RFCOMM +MP_EXTRA_INC += -I$(ESPCOMP)/bt/include +MP_EXTRA_INC += -I$(ESPCOMP)/bt/bluedroid/api/include +endif +endif + +ifdef CONFIG_MICROPY_USE_GPS +MP_EXTRA_INC += -I$(PROJECT_PATH)/components/libnmea/src/nmea +MP_EXTRA_INC += -I$(PROJECT_PATH)/components/libnmea/src/parsers +endif + +ifdef CONFIG_MICROPY_USE_REQUESTS +MP_EXTRA_INC += -I$(ESPCOMP)/esp_http_client/include/ endif # CPP macro @@ -137,7 +147,7 @@ MP_CLEAN_EXTRA += $(COMPONENT_PATH)/genhdr/qstrdefs.generated.h # -------------------------------- include $(COMPONENT_PATH)/py/py.mk -#CFLAGS += -std=gnu99 +#CFLAGS += -DESP_PLATFORM CFLAGS += $(CFLAGS_MOD) @@ -173,16 +183,26 @@ SRC_C = $(addprefix esp32/,\ machine_neopixel.c \ machine_dht.c \ machine_ow.c \ + machine_i2s.c \ ) ifdef CONFIG_MICROPY_USE_DISPLAY SRC_C += esp32/moddisplay.c +SRC_C += esp32/m5ui.c endif ifdef CONFIG_MICROPY_USE_CURL SRC_C += esp32/modcurl.c endif +ifdef CONFIG_MICROPY_USE_REQUESTS +SRC_C += esp32/modrequests.c +endif + +ifdef CONFIG_MICROPY_USE_GPS +SRC_C += esp32/machine_gps.c +endif + ifdef CONFIG_MICROPY_USE_SSH SRC_C += esp32/modssh.c endif @@ -212,29 +232,15 @@ SRC_C += esp32/bluetooth_le.c SRC_C += esp32/modbluetooth.c endif +ifdef CONFIG_MICROPY_USE_RFCOMM +SRC_C += esp32/machine_rfcomm.c +endif + EXTMOD_SRC_C = $(addprefix extmod/,\ modbtree.c \ ) LIB_SRC_C = $(addprefix lib/,\ - libm/math.c \ - libm/fmodf.c \ - libm/roundf.c \ - libm/ef_sqrt.c \ - libm/kf_rem_pio2.c \ - libm/kf_sin.c \ - libm/kf_cos.c \ - libm/kf_tan.c \ - libm/ef_rem_pio2.c \ - libm/sf_sin.c \ - libm/sf_cos.c \ - libm/sf_tan.c \ - libm/sf_frexp.c \ - libm/sf_modf.c \ - libm/sf_ldexp.c \ - libm/asinfacosf.c \ - libm/atanf.c \ - libm/atan2f.c \ mp-readline/readline.c \ netutils/netutils.c \ timeutils/timeutils.c \ @@ -251,13 +257,17 @@ LIBS_SRC_C = $(addprefix esp32/libs/,\ ftp.c \ websrv.c \ libGSM.c \ + curl_mail.c \ ow/owb_rmt.c \ ow/owb.c \ ow/ds18b20.c \ + littleflash.c \ + qrcode.c \ ) -ifdef CONFIG_MICROPY_USE_DISPLAY +ifdef CONFIG_MICROPY_USE_TFT LIBS_SRC_C += \ + esp32/moddisplay_tft.c \ esp32/libs/tft/tftspi.c \ esp32/libs/tft/tft.c \ esp32/libs/tft/comic24.c \ @@ -268,12 +278,19 @@ LIBS_SRC_C += \ esp32/libs/tft/SmallFont.c \ esp32/libs/tft/tooney32.c \ esp32/libs/tft/Ubuntu16.c \ - esp32/libs/tft/def_small.c + esp32/libs/tft/def_small.c \ + esp32/libs/m5ui/m5ui_rect.c \ + esp32/libs/m5ui/m5ui_circle.c \ + esp32/libs/m5ui/m5ui_title.c \ + esp32/libs/m5ui/m5ui_textbox.c \ + esp32/libs/m5ui/m5ui_button.c \ + esp32/libs/m5ui/m5ui_img.c endif ifdef CONFIG_MICROPY_USE_EVE LIBS_SRC_C += \ - esp32/libs/eve/FT8_commands.c + esp32/libs/eve/FT8_commands.c \ + esp32/moddisplay_eve.c endif ifeq ($(MICROPY_PY_BTREE),1) diff --git a/MicroPython_BUILD/components/micropython/docs/library/array.rst b/MicroPython_BUILD/components/micropython/docs/library/array.rst new file mode 100644 index 00000000..f837b034 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/array.rst @@ -0,0 +1,29 @@ +:mod:`array` -- arrays of numeric data +====================================== + +.. module:: array + :synopsis: efficient arrays of numeric data + +|see_cpython_module| :mod:`python:array`. + +Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, +``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the +floating-point support). + +Classes +------- + +.. class:: array.array(typecode, [iterable]) + + Create array with elements of given type. Initial contents of the + array are given by *iterable*. If it is not provided, an empty + array is created. + + .. method:: append(val) + + Append new element *val* to the end of array, growing it. + + .. method:: extend(iterable) + + Append new elements as contained in *iterable* to the end of + array, growing it. diff --git a/MicroPython_BUILD/components/micropython/docs/library/btree.rst b/MicroPython_BUILD/components/micropython/docs/library/btree.rst new file mode 100644 index 00000000..3578acd8 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/btree.rst @@ -0,0 +1,159 @@ +:mod:`btree` -- simple BTree database +===================================== + +.. module:: btree + :synopsis: simple BTree database + +The ``btree`` module implements a simple key-value database using external +storage (disk files, or in general case, a random-access `stream`). Keys are +stored sorted in the database, and besides efficient retrieval by a key +value, a database also supports efficient ordered range scans (retrieval +of values with the keys in a given range). On the application interface +side, BTree database work as close a possible to a way standard `dict` +type works, one notable difference is that both keys and values must +be `bytes` objects (so, if you want to store objects of other types, you +need to serialize them to `bytes` first). + +The module is based on the well-known BerkelyDB library, version 1.xx. + +Example:: + + import btree + + # First, we need to open a stream which holds a database + # This is usually a file, but can be in-memory database + # using uio.BytesIO, a raw flash partition, etc. + # Oftentimes, you want to create a database file if it doesn't + # exist and open if it exists. Idiom below takes care of this. + # DO NOT open database with "a+b" access mode. + try: + f = open("mydb", "r+b") + except OSError: + f = open("mydb", "w+b") + + # Now open a database itself + db = btree.open(f) + + # The keys you add will be sorted internally in the database + db[b"3"] = b"three" + db[b"1"] = b"one" + db[b"2"] = b"two" + + # Assume that any changes are cached in memory unless + # explicitly flushed (or database closed). Flush database + # at the end of each "transaction". + db.flush() + + # Prints b'two' + print(db[b"2"]) + + # Iterate over sorted keys in the database, starting from b"2" + # until the end of the database, returning only values. + # Mind that arguments passed to values() method are *key* values. + # Prints: + # b'two' + # b'three' + for word in db.values(b"2"): + print(word) + + del db[b"2"] + + # No longer true, prints False + print(b"2" in db) + + # Prints: + # b"1" + # b"3" + for key in db: + print(key) + + db.close() + + # Don't forget to close the underlying stream! + f.close() + + +Functions +--------- + +.. function:: open(stream, \*, flags=0, pagesize=0, cachesize=0, minkeypage=0) + + Open a database from a random-access `stream` (like an open file). All + other parameters are optional and keyword-only, and allow to tweak advanced + parameters of the database operation (most users will not need them): + + * *flags* - Currently unused. + * *pagesize* - Page size used for the nodes in BTree. Acceptable range + is 512-65536. If 0, a port-specific default will be used, optimized for + port's memory usage and/or performance. + * *cachesize* - Suggested memory cache size in bytes. For a + board with enough memory using larger values may improve performance. + Cache policy is as follows: entire cache is not allocated at once; + instead, accessing a new page in database will allocate a memory buffer + for it, until value specified by *cachesize* is reached. Then, these + buffers will be managed using LRU (least recently used) policy. More + buffers may still be allocated if needed (e.g., if a database contains + big keys and/or values). Allocated cache buffers aren't reclaimed. + * *minkeypage* - Minimum number of keys to store per page. Default value + of 0 equivalent to 2. + + Returns a BTree object, which implements a dictionary protocol (set + of methods), and some additional methods described below. + +Methods +------- + +.. method:: btree.close() + + Close the database. It's mandatory to close the database at the end of + processing, as some unwritten data may be still in the cache. Note that + this does not close underlying stream with which the database was opened, + it should be closed separately (which is also mandatory to make sure that + data flushed from buffer to the underlying storage). + +.. method:: btree.flush() + + Flush any data in cache to the underlying stream. + +.. method:: btree.__getitem__(key) + btree.get(key, default=None) + btree.__setitem__(key, val) + btree.__detitem__(key) + btree.__contains__(key) + + Standard dictionary methods. + +.. method:: btree.__iter__() + + A BTree object can be iterated over directly (similar to a dictionary) + to get access to all keys in order. + +.. method:: btree.keys([start_key, [end_key, [flags]]]) + btree.values([start_key, [end_key, [flags]]]) + btree.items([start_key, [end_key, [flags]]]) + + These methods are similar to standard dictionary methods, but also can + take optional parameters to iterate over a key sub-range, instead of + the entire database. Note that for all 3 methods, *start_key* and + *end_key* arguments represent key values. For example, `values()` + method will iterate over values corresponding to they key range + given. None values for *start_key* means "from the first key", no + *end_key* or its value of None means "until the end of database". + By default, range is inclusive of *start_key* and exclusive of + *end_key*, you can include *end_key* in iteration by passing *flags* + of `btree.INCL`. You can iterate in descending key direction + by passing *flags* of `btree.DESC`. The flags values can be ORed + together. + +Constants +--------- + +.. data:: INCL + + A flag for `keys()`, `values()`, `items()` methods to specify that + scanning should be inclusive of the end key. + +.. data:: DESC + + A flag for `keys()`, `values()`, `items()` methods to specify that + scanning should be in descending direction of keys. diff --git a/MicroPython_BUILD/components/micropython/docs/library/builtins.rst b/MicroPython_BUILD/components/micropython/docs/library/builtins.rst new file mode 100644 index 00000000..365248dc --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/builtins.rst @@ -0,0 +1,199 @@ +Builtin functions and exceptions +================================ + +All builtin functions and exceptions are described here. They are also +available via ``builtins`` module. + +Functions and types +------------------- + +.. function:: abs() + +.. function:: all() + +.. function:: any() + +.. function:: bin() + +.. class:: bool() + +.. class:: bytearray() + +.. class:: bytes() + + |see_cpython| `python:bytes`. + +.. function:: callable() + +.. function:: chr() + +.. function:: classmethod() + +.. function:: compile() + +.. class:: complex() + +.. function:: delattr(obj, name) + + The argument *name* should be a string, and this function deletes the named + attribute from the object given by *obj*. + +.. class:: dict() + +.. function:: dir() + +.. function:: divmod() + +.. function:: enumerate() + +.. function:: eval() + +.. function:: exec() + +.. function:: filter() + +.. class:: float() + +.. class:: frozenset() + +.. function:: getattr() + +.. function:: globals() + +.. function:: hasattr() + +.. function:: hash() + +.. function:: hex() + +.. function:: id() + +.. function:: input() + +.. class:: int() + + .. classmethod:: from_bytes(bytes, byteorder) + + In MicroPython, `byteorder` parameter must be positional (this is + compatible with CPython). + + .. method:: to_bytes(size, byteorder) + + In MicroPython, `byteorder` parameter must be positional (this is + compatible with CPython). + +.. function:: isinstance() + +.. function:: issubclass() + +.. function:: iter() + +.. function:: len() + +.. class:: list() + +.. function:: locals() + +.. function:: map() + +.. function:: max() + +.. class:: memoryview() + +.. function:: min() + +.. function:: next() + +.. class:: object() + +.. function:: oct() + +.. function:: open() + +.. function:: ord() + +.. function:: pow() + +.. function:: print() + +.. function:: property() + +.. function:: range() + +.. function:: repr() + +.. function:: reversed() + +.. function:: round() + +.. class:: set() + +.. function:: setattr() + +.. class:: slice() + + The *slice* builtin is the type that slice objects have. + +.. function:: sorted() + +.. function:: staticmethod() + +.. class:: str() + +.. function:: sum() + +.. function:: super() + +.. class:: tuple() + +.. function:: type() + +.. function:: zip() + + +Exceptions +---------- + +.. exception:: AssertionError + +.. exception:: AttributeError + +.. exception:: Exception + +.. exception:: ImportError + +.. exception:: IndexError + +.. exception:: KeyboardInterrupt + +.. exception:: KeyError + +.. exception:: MemoryError + +.. exception:: NameError + +.. exception:: NotImplementedError + +.. exception:: OSError + + |see_cpython| `python:OSError`. MicroPython doesn't implement ``errno`` + attribute, instead use the standard way to access exception arguments: + ``exc.args[0]``. + +.. exception:: RuntimeError + +.. exception:: StopIteration + +.. exception:: SyntaxError + +.. exception:: SystemExit + + |see_cpython| `python:SystemExit`. + +.. exception:: TypeError + + |see_cpython| `python:TypeError`. + +.. exception:: ValueError + +.. exception:: ZeroDivisionError diff --git a/MicroPython_BUILD/components/micropython/docs/library/cmath.rst b/MicroPython_BUILD/components/micropython/docs/library/cmath.rst new file mode 100644 index 00000000..59e4ec17 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/cmath.rst @@ -0,0 +1,63 @@ +:mod:`cmath` -- mathematical functions for complex numbers +========================================================== + +.. module:: cmath + :synopsis: mathematical functions for complex numbers + +|see_cpython_module| :mod:`python:cmath`. + +The ``cmath`` module provides some basic mathematical functions for +working with complex numbers. + +Availability: not available on WiPy and ESP8266. Floating point support +required for this module. + +Functions +--------- + +.. function:: cos(z) + + Return the cosine of ``z``. + +.. function:: exp(z) + + Return the exponential of ``z``. + +.. function:: log(z) + + Return the natural logarithm of ``z``. The branch cut is along the negative real axis. + +.. function:: log10(z) + + Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis. + +.. function:: phase(z) + + Returns the phase of the number ``z``, in the range (-pi, +pi]. + +.. function:: polar(z) + + Returns, as a tuple, the polar form of ``z``. + +.. function:: rect(r, phi) + + Returns the complex number with modulus ``r`` and phase ``phi``. + +.. function:: sin(z) + + Return the sine of ``z``. + +.. function:: sqrt(z) + + Return the square-root of ``z``. + +Constants +--------- + +.. data:: e + + base of the natural logarithm + +.. data:: pi + + the ratio of a circle's circumference to its diameter diff --git a/MicroPython_BUILD/components/micropython/docs/library/framebuf.rst b/MicroPython_BUILD/components/micropython/docs/library/framebuf.rst new file mode 100644 index 00000000..ed4b78ab --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/framebuf.rst @@ -0,0 +1,161 @@ +:mod:`framebuf` --- Frame buffer manipulation +============================================= + +.. module:: framebuf + :synopsis: Frame buffer manipulation + +This module provides a general frame buffer which can be used to create +bitmap images, which can then be sent to a display. + +class FrameBuffer +----------------- + +The FrameBuffer class provides a pixel buffer which can be drawn upon with +pixels, lines, rectangles, text and even other FrameBuffer's. It is useful +when generating output for displays. + +For example:: + + import framebuf + + # FrameBuffer needs 2 bytes for every RGB565 pixel + fbuf = FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565) + + fbuf.fill(0) + fbuf.text('MicroPython!', 0, 0, 0xffff) + fbuf.hline(0, 10, 96, 0xffff) + +Constructors +------------ + +.. class:: FrameBuffer(buffer, width, height, format, stride=width) + + Construct a FrameBuffer object. The parameters are: + + - *buffer* is an object with a buffer protocol which must be large + enough to contain every pixel defined by the width, height and + format of the FrameBuffer. + - *width* is the width of the FrameBuffer in pixels + - *height* is the height of the FrameBuffer in pixels + - *format* specifies the type of pixel used in the FrameBuffer; + permissible values are listed under Constants below. These set the + number of bits used to encode a color value and the layout of these + bits in *buffer*. + Where a color value c is passed to a method, c is a small integer + with an encoding that is dependent on the format of the FrameBuffer. + - *stride* is the number of pixels between each horizontal line + of pixels in the FrameBuffer. This defaults to *width* but may + need adjustments when implementing a FrameBuffer within another + larger FrameBuffer or screen. The *buffer* size must accommodate + an increased step size. + + One must specify valid *buffer*, *width*, *height*, *format* and + optionally *stride*. Invalid *buffer* size or dimensions may lead to + unexpected errors. + +Drawing primitive shapes +------------------------ + +The following methods draw shapes onto the FrameBuffer. + +.. method:: FrameBuffer.fill(c) + + Fill the entire FrameBuffer with the specified color. + +.. method:: FrameBuffer.pixel(x, y[, c]) + + If *c* is not given, get the color value of the specified pixel. + If *c* is given, set the specified pixel to the given color. + +.. method:: FrameBuffer.hline(x, y, w, c) +.. method:: FrameBuffer.vline(x, y, h, c) +.. method:: FrameBuffer.line(x1, y1, x2, y2, c) + + Draw a line from a set of coordinates using the given color and + a thickness of 1 pixel. The `line` method draws the line up to + a second set of coordinates whereas the `hline` and `vline` + methods draw horizontal and vertical lines respectively up to + a given length. + +.. method:: FrameBuffer.rect(x, y, w, h, c) +.. method:: FrameBuffer.fill_rect(x, y, w, h, c) + + Draw a rectangle at the given location, size and color. The `rect` + method draws only a 1 pixel outline whereas the `fill_rect` method + draws both the outline and interior. + +Drawing text +------------ + +.. method:: FrameBuffer.text(s, x, y[, c]) + + Write text to the FrameBuffer using the the coordinates as the upper-left + corner of the text. The color of the text can be defined by the optional + argument but is otherwise a default value of 1. All characters have + dimensions of 8x8 pixels and there is currently no way to change the font. + + +Other methods +------------- + +.. method:: FrameBuffer.scroll(xstep, ystep) + + Shift the contents of the FrameBuffer by the given vector. This may + leave a footprint of the previous colors in the FrameBuffer. + +.. method:: FrameBuffer.blit(fbuf, x, y[, key]) + + Draw another FrameBuffer on top of the current one at the given coordinates. + If *key* is specified then it should be a color integer and the + corresponding color will be considered transparent: all pixels with that + color value will not be drawn. + + This method works between FrameBuffer instances utilising different formats, + but the resulting colors may be unexpected due to the mismatch in color + formats. + +Constants +--------- + +.. data:: framebuf.MONO_VLSB + + Monochrome (1-bit) color format + This defines a mapping where the bits in a byte are vertically mapped with + bit 0 being nearest the top of the screen. Consequently each byte occupies + 8 vertical pixels. Subsequent bytes appear at successive horizontal + locations until the rightmost edge is reached. Further bytes are rendered + at locations starting at the leftmost edge, 8 pixels lower. + +.. data:: framebuf.MONO_HLSB + + Monochrome (1-bit) color format + This defines a mapping where the bits in a byte are horizontally mapped. + Each byte occupies 8 horizontal pixels with bit 0 being the leftmost. + Subsequent bytes appear at successive horizontal locations until the + rightmost edge is reached. Further bytes are rendered on the next row, one + pixel lower. + +.. data:: framebuf.MONO_HMSB + + Monochrome (1-bit) color format + This defines a mapping where the bits in a byte are horizontally mapped. + Each byte occupies 8 horizontal pixels with bit 7 being the leftmost. + Subsequent bytes appear at successive horizontal locations until the + rightmost edge is reached. Further bytes are rendered on the next row, one + pixel lower. + +.. data:: framebuf.RGB565 + + Red Green Blue (16-bit, 5+6+5) color format + +.. data:: framebuf.GS2_HMSB + + Grayscale (2-bit) color format + +.. data:: framebuf.GS4_HMSB + + Grayscale (4-bit) color format + +.. data:: framebuf.GS8 + + Grayscale (8-bit) color format diff --git a/MicroPython_BUILD/components/micropython/docs/library/gc.rst b/MicroPython_BUILD/components/micropython/docs/library/gc.rst new file mode 100644 index 00000000..c823aed3 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/gc.rst @@ -0,0 +1,66 @@ +:mod:`gc` -- control the garbage collector +========================================== + +.. module:: gc + :synopsis: control the garbage collector + +|see_cpython_module| :mod:`python:gc`. + +Functions +--------- + +.. function:: enable() + + Enable automatic garbage collection. + +.. function:: disable() + + Disable automatic garbage collection. Heap memory can still be allocated, + and garbage collection can still be initiated manually using :meth:`gc.collect`. + +.. function:: collect() + + Run a garbage collection. + +.. function:: mem_alloc() + + Return the number of bytes of heap RAM that are allocated. + + .. admonition:: Difference to CPython + :class: attention + + This function is MicroPython extension. + +.. function:: mem_free() + + Return the number of bytes of available heap RAM, or -1 if this amount + is not known. + + .. admonition:: Difference to CPython + :class: attention + + This function is MicroPython extension. + +.. function:: threshold([amount]) + + Set or query the additional GC allocation threshold. Normally, a collection + is triggered only when a new allocation cannot be satisfied, i.e. on an + out-of-memory (OOM) condition. If this function is called, in addition to + OOM, a collection will be triggered each time after *amount* bytes have been + allocated (in total, since the previous time such an amount of bytes + have been allocated). *amount* is usually specified as less than the + full heap size, with the intention to trigger a collection earlier than when the + heap becomes exhausted, and in the hope that an early collection will prevent + excessive memory fragmentation. This is a heuristic measure, the effect + of which will vary from application to application, as well as + the optimal value of the *amount* parameter. + + Calling the function without argument will return the current value of + the threshold. A value of -1 means a disabled allocation threshold. + + .. admonition:: Difference to CPython + :class: attention + + This function is a MicroPython extension. CPython has a similar + function - ``set_threshold()``, but due to different GC + implementations, its signature and semantics are different. diff --git a/MicroPython_BUILD/components/micropython/docs/library/math.rst b/MicroPython_BUILD/components/micropython/docs/library/math.rst new file mode 100644 index 00000000..a6f13d48 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/math.rst @@ -0,0 +1,185 @@ +:mod:`math` -- mathematical functions +===================================== + +.. module:: math + :synopsis: mathematical functions + +|see_cpython_module| :mod:`python:math`. + +The ``math`` module provides some basic mathematical functions for +working with floating-point numbers. + +*Note:* On the pyboard, floating-point numbers have 32-bit precision. + +Availability: not available on WiPy. Floating point support required +for this module. + +Functions +--------- + +.. function:: acos(x) + + Return the inverse cosine of ``x``. + +.. function:: acosh(x) + + Return the inverse hyperbolic cosine of ``x``. + +.. function:: asin(x) + + Return the inverse sine of ``x``. + +.. function:: asinh(x) + + Return the inverse hyperbolic sine of ``x``. + +.. function:: atan(x) + + Return the inverse tangent of ``x``. + +.. function:: atan2(y, x) + + Return the principal value of the inverse tangent of ``y/x``. + +.. function:: atanh(x) + + Return the inverse hyperbolic tangent of ``x``. + +.. function:: ceil(x) + + Return an integer, being ``x`` rounded towards positive infinity. + +.. function:: copysign(x, y) + + Return ``x`` with the sign of ``y``. + +.. function:: cos(x) + + Return the cosine of ``x``. + +.. function:: cosh(x) + + Return the hyperbolic cosine of ``x``. + +.. function:: degrees(x) + + Return radians ``x`` converted to degrees. + +.. function:: erf(x) + + Return the error function of ``x``. + +.. function:: erfc(x) + + Return the complementary error function of ``x``. + +.. function:: exp(x) + + Return the exponential of ``x``. + +.. function:: expm1(x) + + Return ``exp(x) - 1``. + +.. function:: fabs(x) + + Return the absolute value of ``x``. + +.. function:: floor(x) + + Return an integer, being ``x`` rounded towards negative infinity. + +.. function:: fmod(x, y) + + Return the remainder of ``x/y``. + +.. function:: frexp(x) + + Decomposes a floating-point number into its mantissa and exponent. + The returned value is the tuple ``(m, e)`` such that ``x == m * 2**e`` + exactly. If ``x == 0`` then the function returns ``(0.0, 0)``, otherwise + the relation ``0.5 <= abs(m) < 1`` holds. + +.. function:: gamma(x) + + Return the gamma function of ``x``. + +.. function:: isfinite(x) + + Return ``True`` if ``x`` is finite. + +.. function:: isinf(x) + + Return ``True`` if ``x`` is infinite. + +.. function:: isnan(x) + + Return ``True`` if ``x`` is not-a-number + +.. function:: ldexp(x, exp) + + Return ``x * (2**exp)``. + +.. function:: lgamma(x) + + Return the natural logarithm of the gamma function of ``x``. + +.. function:: log(x) + + Return the natural logarithm of ``x``. + +.. function:: log10(x) + + Return the base-10 logarithm of ``x``. + +.. function:: log2(x) + + Return the base-2 logarithm of ``x``. + +.. function:: modf(x) + + Return a tuple of two floats, being the fractional and integral parts of + ``x``. Both return values have the same sign as ``x``. + +.. function:: pow(x, y) + + Returns ``x`` to the power of ``y``. + +.. function:: radians(x) + + Return degrees ``x`` converted to radians. + +.. function:: sin(x) + + Return the sine of ``x``. + +.. function:: sinh(x) + + Return the hyperbolic sine of ``x``. + +.. function:: sqrt(x) + + Return the square root of ``x``. + +.. function:: tan(x) + + Return the tangent of ``x``. + +.. function:: tanh(x) + + Return the hyperbolic tangent of ``x``. + +.. function:: trunc(x) + + Return an integer, being ``x`` rounded towards 0. + +Constants +--------- + +.. data:: e + + base of the natural logarithm + +.. data:: pi + + the ratio of a circle's circumference to its diameter diff --git a/MicroPython_BUILD/components/micropython/docs/library/micropython.rst b/MicroPython_BUILD/components/micropython/docs/library/micropython.rst new file mode 100644 index 00000000..a6ea738e --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/micropython.rst @@ -0,0 +1,137 @@ +:mod:`micropython` -- access and control MicroPython internals +============================================================== + +.. module:: micropython + :synopsis: access and control MicroPython internals + +Functions +--------- + +.. function:: const(expr) + + Used to declare that the expression is a constant so that the compile can + optimise it. The use of this function should be as follows:: + + from micropython import const + + CONST_X = const(123) + CONST_Y = const(2 * CONST_X + 1) + + Constants declared this way are still accessible as global variables from + outside the module they are declared in. On the other hand, if a constant + begins with an underscore then it is hidden, it is not available as a global + variable, and does not take up any memory during execution. + + This `const` function is recognised directly by the MicroPython parser and is + provided as part of the :mod:`micropython` module mainly so that scripts can be + written which run under both CPython and MicroPython, by following the above + pattern. + +.. function:: opt_level([level]) + + If *level* is given then this function sets the optimisation level for subsequent + compilation of scripts, and returns ``None``. Otherwise it returns the current + optimisation level. + + The optimisation level controls the following compilation features: + + - Assertions: at level 0 assertion statements are enabled and compiled into the + bytecode; at levels 1 and higher assertions are not compiled. + - Built-in ``__debug__`` variable: at level 0 this variable expands to ``True``; + at levels 1 and higher it expands to ``False``. + - Source-code line numbers: at levels 0, 1 and 2 source-code line number are + stored along with the bytecode so that exceptions can report the line number + they occurred at; at levels 3 and higher line numbers are not stored. + + The default optimisation level is usually level 0. + +.. function:: alloc_emergency_exception_buf(size) + + Allocate *size* bytes of RAM for the emergency exception buffer (a good + size is around 100 bytes). The buffer is used to create exceptions in cases + when normal RAM allocation would fail (eg within an interrupt handler) and + therefore give useful traceback information in these situations. + + A good way to use this function is to put it at the start of your main script + (eg ``boot.py`` or ``main.py``) and then the emergency exception buffer will be active + for all the code following it. + +.. function:: mem_info([verbose]) + + Print information about currently used memory. If the *verbose* argument + is given then extra information is printed. + + The information that is printed is implementation dependent, but currently + includes the amount of stack and heap used. In verbose mode it prints out + the entire heap indicating which blocks are used and which are free. + +.. function:: qstr_info([verbose]) + + Print information about currently interned strings. If the *verbose* + argument is given then extra information is printed. + + The information that is printed is implementation dependent, but currently + includes the number of interned strings and the amount of RAM they use. In + verbose mode it prints out the names of all RAM-interned strings. + +.. function:: stack_use() + + Return an integer representing the current amount of stack that is being + used. The absolute value of this is not particularly useful, rather it + should be used to compute differences in stack usage at different points. + +.. function:: heap_lock() +.. function:: heap_unlock() + + Lock or unlock the heap. When locked no memory allocation can occur and a + `MemoryError` will be raised if any heap allocation is attempted. + + These functions can be nested, ie `heap_lock()` can be called multiple times + in a row and the lock-depth will increase, and then `heap_unlock()` must be + called the same number of times to make the heap available again. + +.. function:: kbd_intr(chr) + + Set the character that will raise a `KeyboardInterrupt` exception. By + default this is set to 3 during script execution, corresponding to Ctrl-C. + Passing -1 to this function will disable capture of Ctrl-C, and passing 3 + will restore it. + + This function can be used to prevent the capturing of Ctrl-C on the + incoming stream of characters that is usually used for the REPL, in case + that stream is used for other purposes. + +.. function:: schedule(func, arg) + + Schedule the function *func* to be executed "very soon". The function + is passed the value *arg* as its single argument. "Very soon" means that + the MicroPython runtime will do its best to execute the function at the + earliest possible time, given that it is also trying to be efficient, and + that the following conditions hold: + + - A scheduled function will never preempt another scheduled function. + - Scheduled functions are always executed "between opcodes" which means + that all fundamental Python operations (such as appending to a list) + are guaranteed to be atomic. + - A given port may define "critical regions" within which scheduled + functions will never be executed. Functions may be scheduled within + a critical region but they will not be executed until that region + is exited. An example of a critical region is a preempting interrupt + handler (an IRQ). + + A use for this function is to schedule a callback from a preempting IRQ. + Such an IRQ puts restrictions on the code that runs in the IRQ (for example + the heap may be locked) and scheduling a function to call later will lift + those restrictions. + + Note: If `schedule()` is called from a preempting IRQ, when memory + allocation is not allowed and the callback to be passed to `schedule()` is + a bound method, passing this directly will fail. This is because creating a + reference to a bound method causes memory allocation. A solution is to + create a reference to the method in the class constructor and to pass that + reference to `schedule()`. This is discussed in detail here + :ref:`reference documentation ` under "Creation of Python + objects". + + There is a finite stack to hold the scheduled functions and `schedule()` + will raise a `RuntimeError` if the stack is full. diff --git a/MicroPython_BUILD/components/micropython/docs/library/network.rst b/MicroPython_BUILD/components/micropython/docs/library/network.rst new file mode 100644 index 00000000..a113209e --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/network.rst @@ -0,0 +1,603 @@ +**************************************** +:mod:`network` --- network configuration +**************************************** + +.. module:: network + :synopsis: network configuration + +This module provides network drivers and routing configuration. To use this +module, a MicroPython variant/build with network capabilities must be installed. +Network drivers for specific hardware are available within this module and are +used to configure hardware network interface(s). Network services provided +by configured interfaces are then available for use via the :mod:`usocket` +module. + +For example:: + + # connect/ show IP config a specific network interface + # see below for examples of specific drivers + import network + import utime + nic = network.Driver(...) + if not nic.isconnected(): + nic.connect() + print("Waiting for connection...") + while not nic.isconnected(): + utime.sleep(1) + print(nic.ifconfig()) + + # now use usocket as usual + import usocket as socket + addr = socket.getaddrinfo('micropython.org', 80)[0][-1] + s = socket.socket() + s.connect(addr) + s.send(b'GET / HTTP/1.1\r\nHost: micropython.org\r\n\r\n') + data = s.recv(1000) + s.close() + +Common network adapter interface +================================ + +This section describes an (implied) abstract base class for all network +interface classes implemented by `MicroPython ports ` +for different hardware. This means that MicroPython does not actually +provide ``AbstractNIC`` class, but any actual NIC class, as described +in the following sections, implements methods as described here. + +.. class:: AbstractNIC(id=None, ...) + +Instantiate a network interface object. Parameters are network interface +dependent. If there are more than one interface of the same type, the first +parameter should be `id`. + + .. method:: active([is_active]) + + Activate ("up") or deactivate ("down") the network interface, if + a boolean argument is passed. Otherwise, query current state if + no argument is provided. Most other methods require an active + interface (behavior of calling them on inactive interface is + undefined). + + .. method:: connect([service_id, key=None, \*, ...]) + + Connect the interface to a network. This method is optional, and + available only for interfaces which are not "always connected". + If no parameters are given, connect to the default (or the only) + service. If a single parameter is given, it is the primary identifier + of a service to connect to. It may be accompanied by a key + (password) required to access said service. There can be further + arbitrary keyword-only parameters, depending on the networking medium + type and/or particular device. Parameters can be used to: a) + specify alternative service identifer types; b) provide additional + connection parameters. For various medium types, there are different + sets of predefined/recommended parameters, among them: + + * WiFi: *bssid* keyword to connect to a specific BSSID (MAC address) + + .. method:: disconnect() + + Disconnect from network. + + .. method:: isconnected() + + Returns ``True`` if connected to network, otherwise returns ``False``. + + .. method:: scan(\*, ...) + + Scan for the available network services/connections. Returns a + list of tuples with discovered service parameters. For various + network media, there are different variants of predefined/ + recommended tuple formats, among them: + + * WiFi: (ssid, bssid, channel, RSSI, authmode, hidden). There + may be further fields, specific to a particular device. + + The function may accept additional keyword arguments to filter scan + results (e.g. scan for a particular service, on a particular channel, + for services of a particular set, etc.), and to affect scan + duration and other parameters. Where possible, parameter names + should match those in connect(). + + .. method:: status([param]) + + Query dynamic status information of the interface. When called with no + argument the return value describes the network link status. Otherwise + *param* should be a string naming the particular status parameter to + retrieve. + + The return types and values are dependent on the network + medium/technology. Some of the parameters that may be supported are: + + * WiFi STA: use ``'rssi'`` to retrieve the RSSI of the AP signal + * WiFi AP: use ``'stations'`` to retrieve a list of all the STAs + connected to the AP. The list contains tuples of the form + (MAC, RSSI). + + .. method:: ifconfig([(ip, subnet, gateway, dns)]) + + Get/set IP-level network interface parameters: IP address, subnet mask, + gateway and DNS server. When called with no arguments, this method returns + a 4-tuple with the above information. To set the above values, pass a + 4-tuple with the required information. For example:: + + nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) + + .. method:: config('param') + config(param=value, ...) + + Get or set general network interface parameters. These methods allow to work + with additional parameters beyond standard IP configuration (as dealt with by + `ifconfig()`). These include network-specific and hardware-specific + parameters. For setting parameters, the keyword argument + syntax should be used, and multiple parameters can be set at once. For + querying, a parameter name should be quoted as a string, and only one + parameter can be queried at a time:: + + # Set WiFi access point name (formally known as ESSID) and WiFi channel + ap.config(essid='My AP', channel=11) + # Query params one by one + print(ap.config('essid')) + print(ap.config('channel')) + +.. only:: port_pyboard + + class CC3K + ========== + + This class provides a driver for CC3000 WiFi modules. Example usage:: + + import network + nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) + nic.connect('your-ssid', 'your-password') + while not nic.isconnected(): + pyb.delay(50) + print(nic.ifconfig()) + + # now use socket as usual + ... + + For this example to work the CC3000 module must have the following connections: + + - MOSI connected to Y8 + - MISO connected to Y7 + - CLK connected to Y6 + - CS connected to Y5 + - VBEN connected to Y4 + - IRQ connected to Y3 + + It is possible to use other SPI busses and other pins for CS, VBEN and IRQ. + + Constructors + ------------ + + .. class:: CC3K(spi, pin_cs, pin_en, pin_irq) + + Create a CC3K driver object, initialise the CC3000 module using the given SPI bus + and pins, and return the CC3K object. + + Arguments are: + + - *spi* is an :ref:`SPI object ` which is the SPI bus that the CC3000 is + connected to (the MOSI, MISO and CLK pins). + - *pin_cs* is a :ref:`Pin object ` which is connected to the CC3000 CS pin. + - *pin_en* is a :ref:`Pin object ` which is connected to the CC3000 VBEN pin. + - *pin_irq* is a :ref:`Pin object ` which is connected to the CC3000 IRQ pin. + + All of these objects will be initialised by the driver, so there is no need to + initialise them yourself. For example, you can use:: + + nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3) + + Methods + ------- + + .. method:: cc3k.connect(ssid, key=None, \*, security=WPA2, bssid=None) + + Connect to a WiFi access point using the given SSID, and other security + parameters. + + .. method:: cc3k.disconnect() + + Disconnect from the WiFi access point. + + .. method:: cc3k.isconnected() + + Returns True if connected to a WiFi access point and has a valid IP address, + False otherwise. + + .. method:: cc3k.ifconfig() + + Returns a 7-tuple with (ip, subnet mask, gateway, DNS server, DHCP server, + MAC address, SSID). + + .. method:: cc3k.patch_version() + + Return the version of the patch program (firmware) on the CC3000. + + .. method:: cc3k.patch_program('pgm') + + Upload the current firmware to the CC3000. You must pass 'pgm' as the first + argument in order for the upload to proceed. + + Constants + --------- + + .. data:: CC3K.WEP + .. data:: CC3K.WPA + .. data:: CC3K.WPA2 + + security type to use + + class WIZNET5K + ============== + + This class allows you to control WIZnet5x00 Ethernet adaptors based on + the W5200 and W5500 chipsets. The particular chipset that is supported + by the firmware is selected at compile-time via the MICROPY_PY_WIZNET5K + option. + + Example usage:: + + import network + nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) + print(nic.ifconfig()) + + # now use socket as usual + ... + + For this example to work the WIZnet5x00 module must have the following connections: + + - MOSI connected to X8 + - MISO connected to X7 + - SCLK connected to X6 + - nSS connected to X5 + - nRESET connected to X4 + + It is possible to use other SPI busses and other pins for nSS and nRESET. + + Constructors + ------------ + + .. class:: WIZNET5K(spi, pin_cs, pin_rst) + + Create a WIZNET5K driver object, initialise the WIZnet5x00 module using the given + SPI bus and pins, and return the WIZNET5K object. + + Arguments are: + + - *spi* is an :ref:`SPI object ` which is the SPI bus that the WIZnet5x00 is + connected to (the MOSI, MISO and SCLK pins). + - *pin_cs* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nSS pin. + - *pin_rst* is a :ref:`Pin object ` which is connected to the WIZnet5x00 nRESET pin. + + All of these objects will be initialised by the driver, so there is no need to + initialise them yourself. For example, you can use:: + + nic = network.WIZNET5K(pyb.SPI(1), pyb.Pin.board.X5, pyb.Pin.board.X4) + + Methods + ------- + + .. method:: wiznet5k.isconnected() + + Returns ``True`` if the physical Ethernet link is connected and up. + Returns ``False`` otherwise. + + .. method:: wiznet5k.ifconfig([(ip, subnet, gateway, dns)]) + + Get/set IP address, subnet mask, gateway and DNS. + + When called with no arguments, this method returns a 4-tuple with the above information. + + To set the above values, pass a 4-tuple with the required information. For example:: + + nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) + + .. method:: wiznet5k.regs() + + Dump the WIZnet5x00 registers. Useful for debugging. + +.. _network.WLAN: + +.. only:: port_esp8266 + + Functions + ========= + + .. function:: phy_mode([mode]) + + Get or set the PHY mode. + + If the *mode* parameter is provided, sets the mode to its value. If + the function is called without parameters, returns the current mode. + + The possible modes are defined as constants: + * ``MODE_11B`` -- IEEE 802.11b, + * ``MODE_11G`` -- IEEE 802.11g, + * ``MODE_11N`` -- IEEE 802.11n. + + class WLAN + ========== + + This class provides a driver for WiFi network processor in the ESP8266. Example usage:: + + import network + # enable station interface and connect to WiFi access point + nic = network.WLAN(network.STA_IF) + nic.active(True) + nic.connect('your-ssid', 'your-password') + # now use sockets as usual + + Constructors + ------------ + .. class:: WLAN(interface_id) + + Create a WLAN network interface object. Supported interfaces are + ``network.STA_IF`` (station aka client, connects to upstream WiFi access + points) and ``network.AP_IF`` (access point, allows other WiFi clients to + connect). Availability of the methods below depends on interface type. + For example, only STA interface may `connect()` to an access point. + + Methods + ------- + + .. method:: wlan.active([is_active]) + + Activate ("up") or deactivate ("down") network interface, if boolean + argument is passed. Otherwise, query current state if no argument is + provided. Most other methods require active interface. + + .. method:: wlan.connect(ssid=None, password=None, \*, bssid=None) + + Connect to the specified wireless network, using the specified password. + If *bssid* is given then the connection will be restricted to the + access-point with that MAC address (the *ssid* must also be specified + in this case). + + .. method:: wlan.disconnect() + + Disconnect from the currently connected wireless network. + + .. method:: wlan.scan() + + Scan for the available wireless networks. + + Scanning is only possible on STA interface. Returns list of tuples with + the information about WiFi access points: + + (ssid, bssid, channel, RSSI, authmode, hidden) + + *bssid* is hardware address of an access point, in binary form, returned as + bytes object. You can use `ubinascii.hexlify()` to convert it to ASCII form. + + There are five values for authmode: + + * 0 -- open + * 1 -- WEP + * 2 -- WPA-PSK + * 3 -- WPA2-PSK + * 4 -- WPA/WPA2-PSK + + and two for hidden: + + * 0 -- visible + * 1 -- hidden + + .. method:: wlan.status([param]) + + Return the current status of the wireless connection. + + When called with no argument the return value describes the network link status. + The possible statuses are defined as constants: + + * ``STAT_IDLE`` -- no connection and no activity, + * ``STAT_CONNECTING`` -- connecting in progress, + * ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password, + * ``STAT_NO_AP_FOUND`` -- failed because no access point replied, + * ``STAT_CONNECT_FAIL`` -- failed due to other problems, + * ``STAT_GOT_IP`` -- connection successful. + + When called with one argument *param* should be a string naming the status + parameter to retrieve. Supported parameters in WiFI STA mode are: ``'rssi'``. + + .. method:: wlan.isconnected() + + In case of STA mode, returns ``True`` if connected to a WiFi access + point and has a valid IP address. In AP mode returns ``True`` when a + station is connected. Returns ``False`` otherwise. + + .. method:: wlan.ifconfig([(ip, subnet, gateway, dns)]) + + Get/set IP-level network interface parameters: IP address, subnet mask, + gateway and DNS server. When called with no arguments, this method returns + a 4-tuple with the above information. To set the above values, pass a + 4-tuple with the required information. For example:: + + nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) + + .. method:: wlan.config('param') + .. method:: wlan.config(param=value, ...) + + Get or set general network interface parameters. These methods allow to work + with additional parameters beyond standard IP configuration (as dealt with by + `wlan.ifconfig()`). These include network-specific and hardware-specific + parameters. For setting parameters, keyword argument syntax should be used, + multiple parameters can be set at once. For querying, parameters name should + be quoted as a string, and only one parameter can be queries at time:: + + # Set WiFi access point name (formally known as ESSID) and WiFi channel + ap.config(essid='My AP', channel=11) + # Query params one by one + print(ap.config('essid')) + print(ap.config('channel')) + + Following are commonly supported parameters (availability of a specific parameter + depends on network technology type, driver, and `MicroPython port`). + + ============= =========== + Parameter Description + ============= =========== + mac MAC address (bytes) + essid WiFi access point name (string) + channel WiFi channel (integer) + hidden Whether ESSID is hidden (boolean) + authmode Authentication mode supported (enumeration, see module constants) + password Access password (string) + dhcp_hostname The DHCP hostname to use + ============= =========== + + + +.. only:: port_wipy + + class WLAN + ========== + + This class provides a driver for the WiFi network processor in the WiPy. Example usage:: + + import network + import time + # setup as a station + wlan = network.WLAN(mode=WLAN.STA) + wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key')) + while not wlan.isconnected(): + time.sleep_ms(50) + print(wlan.ifconfig()) + + # now use socket as usual + ... + + Constructors + ------------ + + .. class:: WLAN(id=0, ...) + + Create a WLAN object, and optionally configure it. See `init()` for params of configuration. + + .. note:: + + The ``WLAN`` constructor is special in the sense that if no arguments besides the id are given, + it will return the already existing ``WLAN`` instance without re-configuring it. This is + because ``WLAN`` is a system feature of the WiPy. If the already existing instance is not + initialized it will do the same as the other constructors an will initialize it with default + values. + + Methods + ------- + + .. method:: wlan.init(mode, \*, ssid, auth, channel, antenna) + + Set or get the WiFi network processor configuration. + + Arguments are: + + - *mode* can be either ``WLAN.STA`` or ``WLAN.AP``. + - *ssid* is a string with the ssid name. Only needed when mode is ``WLAN.AP``. + - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, + ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. + If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal + values (e.g. 'ABC1DE45BF'). Only needed when mode is ``WLAN.AP``. + - *channel* a number in the range 1-11. Only needed when mode is ``WLAN.AP``. + - *antenna* selects between the internal and the external antenna. Can be either + ``WLAN.INT_ANT`` or ``WLAN.EXT_ANT``. + + For example, you can do:: + + # create and configure as an access point + wlan.init(mode=WLAN.AP, ssid='wipy-wlan', auth=(WLAN.WPA2,'www.wipy.io'), channel=7, antenna=WLAN.INT_ANT) + + or:: + + # configure as an station + wlan.init(mode=WLAN.STA) + + .. method:: wlan.connect(ssid, \*, auth=None, bssid=None, timeout=None) + + Connect to a WiFi access point using the given SSID, and other security + parameters. + + - *auth* is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``, + ``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password. + If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal + values (e.g. 'ABC1DE45BF'). + - *bssid* is the MAC address of the AP to connect to. Useful when there are several + APs with the same ssid. + - *timeout* is the maximum time in milliseconds to wait for the connection to succeed. + + .. method:: wlan.scan() + + Performs a network scan and returns a list of named tuples with (ssid, bssid, sec, channel, rssi). + Note that channel is always ``None`` since this info is not provided by the WiPy. + + .. method:: wlan.disconnect() + + Disconnect from the WiFi access point. + + .. method:: wlan.isconnected() + + In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address. + In AP mode returns ``True`` when a station is connected, ``False`` otherwise. + + .. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple]) + + With no parameters given returns a 4-tuple of *(ip, subnet_mask, gateway, DNS_server)*. + + if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params + are negotiated with the AP. + + If the 4-tuple config is given then a static IP is configured. For instance:: + + wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8')) + + .. method:: wlan.mode([mode]) + + Get or set the WLAN mode. + + .. method:: wlan.ssid([ssid]) + + Get or set the SSID when in AP mode. + + .. method:: wlan.auth([auth]) + + Get or set the authentication type when in AP mode. + + .. method:: wlan.channel([channel]) + + Get or set the channel (only applicable in AP mode). + + .. method:: wlan.antenna([antenna]) + + Get or set the antenna type (external or internal). + + .. method:: wlan.mac([mac_addr]) + + Get or set a 6-byte long bytes object with the MAC address. + + .. method:: wlan.irq(\*, handler, wake) + + Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP`` + mode. Events are triggered by socket activity or by WLAN connection/disconnection. + + - *handler* is the function that gets called when the IRQ is triggered. + - *wake* must be ``machine.SLEEP``. + + Returns an IRQ object. + + Constants + --------- + + .. data:: WLAN.STA + .. data:: WLAN.AP + + selects the WLAN mode + + .. data:: WLAN.WEP + .. data:: WLAN.WPA + .. data:: WLAN.WPA2 + + selects the network security + + .. data:: WLAN.INT_ANT + .. data:: WLAN.EXT_ANT + + selects the antenna type diff --git a/MicroPython_BUILD/components/micropython/docs/library/ubinascii.rst b/MicroPython_BUILD/components/micropython/docs/library/ubinascii.rst new file mode 100644 index 00000000..192d3451 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/ubinascii.rst @@ -0,0 +1,40 @@ +:mod:`ubinascii` -- binary/ASCII conversions +============================================ + +.. module:: ubinascii + :synopsis: binary/ASCII conversions + +|see_cpython_module| :mod:`python:binascii`. + +This module implements conversions between binary data and various +encodings of it in ASCII form (in both directions). + +Functions +--------- + +.. function:: hexlify(data, [sep]) + + Convert binary data to hexadecimal representation. Returns bytes string. + + .. admonition:: Difference to CPython + :class: attention + + If additional argument, *sep* is supplied, it is used as a separator + between hexadecimal values. + +.. function:: unhexlify(data) + + Convert hexadecimal data to binary representation. Returns bytes string. + (i.e. inverse of hexlify) + +.. function:: a2b_base64(data) + + Decode base64-encoded data, ignoring invalid characters in the input. + Conforms to `RFC 2045 s.6.8 `_. + Returns a bytes object. + +.. function:: b2a_base64(data) + + Encode binary data in base64 format, as in `RFC 3548 + `_. Returns the encoded data + followed by a newline character, as a bytes object. diff --git a/MicroPython_BUILD/components/micropython/docs/library/ucollections.rst b/MicroPython_BUILD/components/micropython/docs/library/ucollections.rst new file mode 100644 index 00000000..96de67ac --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/ucollections.rst @@ -0,0 +1,55 @@ +:mod:`ucollections` -- collection and container types +===================================================== + +.. module:: ucollections + :synopsis: collection and container types + +|see_cpython_module| :mod:`python:collections`. + +This module implements advanced collection and container types to +hold/accumulate various objects. + +Classes +------- + +.. function:: namedtuple(name, fields) + + This is factory function to create a new namedtuple type with a specific + name and set of fields. A namedtuple is a subclass of tuple which allows + to access its fields not just by numeric index, but also with an attribute + access syntax using symbolic field names. Fields is a sequence of strings + specifying field names. For compatibility with CPython it can also be a + a string with space-separated field named (but this is less efficient). + Example of use:: + + from ucollections import namedtuple + + MyTuple = namedtuple("MyTuple", ("id", "name")) + t1 = MyTuple(1, "foo") + t2 = MyTuple(2, "bar") + print(t1.name) + assert t2.name == t2[1] + +.. function:: OrderedDict(...) + + ``dict`` type subclass which remembers and preserves the order of keys + added. When ordered dict is iterated over, keys/items are returned in + the order they were added:: + + from ucollections import OrderedDict + + # To make benefit of ordered keys, OrderedDict should be initialized + # from sequence of (key, value) pairs. + d = OrderedDict([("z", 1), ("a", 2)]) + # More items can be added as usual + d["w"] = 5 + d["b"] = 3 + for k, v in d.items(): + print(k, v) + + Output:: + + z 1 + a 2 + w 5 + b 3 diff --git a/MicroPython_BUILD/components/micropython/docs/library/uctypes.rst b/MicroPython_BUILD/components/micropython/docs/library/uctypes.rst new file mode 100644 index 00000000..c938d74a --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uctypes.rst @@ -0,0 +1,210 @@ +:mod:`uctypes` -- access binary data in a structured way +======================================================== + +.. module:: uctypes + :synopsis: access binary data in a structured way + +This module implements "foreign data interface" for MicroPython. The idea +behind it is similar to CPython's ``ctypes`` modules, but the actual API is +different, streamlined and optimized for small size. The basic idea of the +module is to define data structure layout with about the same power as the +C language allows, and then access it using familiar dot-syntax to reference +sub-fields. + +.. seealso:: + + Module :mod:`ustruct` + Standard Python way to access binary data structures (doesn't scale + well to large and complex structures). + +Defining structure layout +------------------------- + +Structure layout is defined by a "descriptor" - a Python dictionary which +encodes field names as keys and other properties required to access them as +associated values. Currently, uctypes requires explicit specification of +offsets for each field. Offset are given in bytes from a structure start. + +Following are encoding examples for various field types: + +* Scalar types:: + + "field_name": offset | uctypes.UINT32 + + in other words, value is scalar type identifier ORed with field offset + (in bytes) from the start of the structure. + +* Recursive structures:: + + "sub": (offset, { + "b0": 0 | uctypes.UINT8, + "b1": 1 | uctypes.UINT8, + }) + + i.e. value is a 2-tuple, first element of which is offset, and second is + a structure descriptor dictionary (note: offsets in recursive descriptors + are relative to the structure it defines). + +* Arrays of primitive types:: + + "arr": (offset | uctypes.ARRAY, size | uctypes.UINT8), + + i.e. value is a 2-tuple, first element of which is ARRAY flag ORed + with offset, and second is scalar element type ORed number of elements + in array. + +* Arrays of aggregate types:: + + "arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}), + + i.e. value is a 3-tuple, first element of which is ARRAY flag ORed + with offset, second is a number of elements in array, and third is + descriptor of element type. + +* Pointer to a primitive type:: + + "ptr": (offset | uctypes.PTR, uctypes.UINT8), + + i.e. value is a 2-tuple, first element of which is PTR flag ORed + with offset, and second is scalar element type. + +* Pointer to an aggregate type:: + + "ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}), + + i.e. value is a 2-tuple, first element of which is PTR flag ORed + with offset, second is descriptor of type pointed to. + +* Bitfields:: + + "bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN, + + i.e. value is type of scalar value containing given bitfield (typenames are + similar to scalar types, but prefixes with "BF"), ORed with offset for + scalar value containing the bitfield, and further ORed with values for + bit offset and bit length of the bitfield within scalar value, shifted by + BF_POS and BF_LEN positions, respectively. Bitfield position is counted + from the least significant bit, and is the number of right-most bit of a + field (in other words, it's a number of bits a scalar needs to be shifted + right to extract the bitfield). + + In the example above, first a UINT16 value will be extracted at offset 0 + (this detail may be important when accessing hardware registers, where + particular access size and alignment are required), and then bitfield + whose rightmost bit is *lsbit* bit of this UINT16, and length + is *bitsize* bits, will be extracted. For example, if *lsbit* is 0 and + *bitsize* is 8, then effectively it will access least-significant byte + of UINT16. + + Note that bitfield operations are independent of target byte endianness, + in particular, example above will access least-significant byte of UINT16 + in both little- and big-endian structures. But it depends on the least + significant bit being numbered 0. Some targets may use different + numbering in their native ABI, but ``uctypes`` always uses the normalized + numbering described above. + +Module contents +--------------- + +.. class:: struct(addr, descriptor, layout_type=NATIVE) + + Instantiate a "foreign data structure" object based on structure address in + memory, descriptor (encoded as a dictionary), and layout type (see below). + +.. data:: LITTLE_ENDIAN + + Layout type for a little-endian packed structure. (Packed means that every + field occupies exactly as many bytes as defined in the descriptor, i.e. + the alignment is 1). + +.. data:: BIG_ENDIAN + + Layout type for a big-endian packed structure. + +.. data:: NATIVE + + Layout type for a native structure - with data endianness and alignment + conforming to the ABI of the system on which MicroPython runs. + +.. function:: sizeof(struct) + + Return size of data structure in bytes. Argument can be either structure + class or specific instantiated structure object (or its aggregate field). + +.. function:: addressof(obj) + + Return address of an object. Argument should be bytes, bytearray or + other object supporting buffer protocol (and address of this buffer + is what actually returned). + +.. function:: bytes_at(addr, size) + + Capture memory at the given address and size as bytes object. As bytes + object is immutable, memory is actually duplicated and copied into + bytes object, so if memory contents change later, created object + retains original value. + +.. function:: bytearray_at(addr, size) + + Capture memory at the given address and size as bytearray object. + Unlike bytes_at() function above, memory is captured by reference, + so it can be both written too, and you will access current value + at the given memory address. + +Structure descriptors and instantiating structure objects +--------------------------------------------------------- + +Given a structure descriptor dictionary and its layout type, you can +instantiate a specific structure instance at a given memory address +using :class:`uctypes.struct()` constructor. Memory address usually comes from +following sources: + +* Predefined address, when accessing hardware registers on a baremetal + system. Lookup these addresses in datasheet for a particular MCU/SoC. +* As a return value from a call to some FFI (Foreign Function Interface) + function. +* From uctypes.addressof(), when you want to pass arguments to an FFI + function, or alternatively, to access some data for I/O (for example, + data read from a file or network socket). + +Structure objects +----------------- + +Structure objects allow accessing individual fields using standard dot +notation: ``my_struct.substruct1.field1``. If a field is of scalar type, +getting it will produce a primitive value (Python integer or float) +corresponding to the value contained in a field. A scalar field can also +be assigned to. + +If a field is an array, its individual elements can be accessed with +the standard subscript operator ``[]`` - both read and assigned to. + +If a field is a pointer, it can be dereferenced using ``[0]`` syntax +(corresponding to C ``*`` operator, though ``[0]`` works in C too). +Subscripting a pointer with other integer values but 0 are supported too, +with the same semantics as in C. + +Summing up, accessing structure fields generally follows C syntax, +except for pointer dereference, when you need to use ``[0]`` operator +instead of ``*``. + +Limitations +----------- + +Accessing non-scalar fields leads to allocation of intermediate objects +to represent them. This means that special care should be taken to +layout a structure which needs to be accessed when memory allocation +is disabled (e.g. from an interrupt). The recommendations are: + +* Avoid nested structures. For example, instead of + ``mcu_registers.peripheral_a.register1``, define separate layout + descriptors for each peripheral, to be accessed as + ``peripheral_a.register1``. +* Avoid other non-scalar data, like array. For example, instead of + ``peripheral_a.register[0]`` use ``peripheral_a.register0``. + +Note that these recommendations will lead to decreased readability +and conciseness of layouts, so they should be used only if the need +to access structure fields without allocation is anticipated (it's +even possible to define 2 parallel layouts - one for normal usage, +and a restricted one to use when memory allocation is prohibited). diff --git a/MicroPython_BUILD/components/micropython/docs/library/uerrno.rst b/MicroPython_BUILD/components/micropython/docs/library/uerrno.rst new file mode 100644 index 00000000..e336eb5c --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uerrno.rst @@ -0,0 +1,34 @@ +:mod:`uerrno` -- system error codes +=================================== + +.. module:: uerrno + :synopsis: system error codes + +|see_cpython_module| :mod:`python:errno`. + +This module provides access to symbolic error codes for `OSError` exception. +A particular inventory of codes depends on `MicroPython port`. + +Constants +--------- + +.. data:: EEXIST, EAGAIN, etc. + + Error codes, based on ANSI C/POSIX standard. All error codes start with + "E". As mentioned above, inventory of the codes depends on + `MicroPython port`. Errors are usually accessible as ``exc.args[0]`` + where ``exc`` is an instance of `OSError`. Usage example:: + + try: + uos.mkdir("my_dir") + except OSError as exc: + if exc.args[0] == uerrno.EEXIST: + print("Directory already exists") + +.. data:: errorcode + + Dictionary mapping numeric error codes to strings with symbolic error + code (see above):: + + >>> print(uerrno.errorcode[uerrno.EEXIST]) + EEXIST diff --git a/MicroPython_BUILD/components/micropython/docs/library/uhashlib.rst b/MicroPython_BUILD/components/micropython/docs/library/uhashlib.rst new file mode 100644 index 00000000..50ed658c --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uhashlib.rst @@ -0,0 +1,57 @@ +:mod:`uhashlib` -- hashing algorithms +===================================== + +.. module:: uhashlib + :synopsis: hashing algorithms + +|see_cpython_module| :mod:`python:hashlib`. + +This module implements binary data hashing algorithms. The exact inventory +of available algorithms depends on a board. Among the algorithms which may +be implemented: + +* SHA256 - The current generation, modern hashing algorithm (of SHA2 series). + It is suitable for cryptographically-secure purposes. Included in the + MicroPython core and any board is recommended to provide this, unless + it has particular code size constraints. + +* SHA1 - A previous generation algorithm. Not recommended for new usages, + but SHA1 is a part of number of Internet standards and existing + applications, so boards targeting network connectivity and + interoperatiability will try to provide this. + +* MD5 - A legacy algorithm, not considered cryptographically secure. Only + selected boards, targeting interoperatibility with legacy applications, + will offer this. + +Constructors +------------ + +.. class:: uhashlib.sha256([data]) + + Create an SHA256 hasher object and optionally feed ``data`` into it. + +.. class:: uhashlib.sha1([data]) + + Create an SHA1 hasher object and optionally feed ``data`` into it. + +.. class:: uhashlib.md5([data]) + + Create an MD5 hasher object and optionally feed ``data`` into it. + +Methods +------- + +.. method:: hash.update(data) + + Feed more binary data into hash. + +.. method:: hash.digest() + + Return hash for all data passed through hash, as a bytes object. After this + method is called, more data cannot be fed into the hash any longer. + +.. method:: hash.hexdigest() + + This method is NOT implemented. Use ``ubinascii.hexlify(hash.digest())`` + to achieve a similar effect. diff --git a/MicroPython_BUILD/components/micropython/docs/library/uheapq.rst b/MicroPython_BUILD/components/micropython/docs/library/uheapq.rst new file mode 100644 index 00000000..f822f1e7 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uheapq.rst @@ -0,0 +1,27 @@ +:mod:`uheapq` -- heap queue algorithm +===================================== + +.. module:: uheapq + :synopsis: heap queue algorithm + +|see_cpython_module| :mod:`python:heapq`. + +This module implements the heap queue algorithm. + +A heap queue is simply a list that has its elements stored in a certain way. + +Functions +--------- + +.. function:: heappush(heap, item) + + Push the ``item`` onto the ``heap``. + +.. function:: heappop(heap) + + Pop the first item from the ``heap``, and return it. Raises IndexError if + heap is empty. + +.. function:: heapify(x) + + Convert the list ``x`` into a heap. This is an in-place operation. diff --git a/MicroPython_BUILD/components/micropython/docs/library/uio.rst b/MicroPython_BUILD/components/micropython/docs/library/uio.rst new file mode 100644 index 00000000..81420702 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uio.rst @@ -0,0 +1,114 @@ +:mod:`uio` -- input/output streams +================================== + +.. module:: uio + :synopsis: input/output streams + +|see_cpython_module| :mod:`python:io`. + +This module contains additional types of `stream` (file-like) objects +and helper functions. + +Conceptual hierarchy +-------------------- + +.. admonition:: Difference to CPython + :class: attention + + Conceptual hierarchy of stream base classes is simplified in MicroPython, + as described in this section. + +(Abstract) base stream classes, which serve as a foundation for behavior +of all the concrete classes, adhere to few dichotomies (pair-wise +classifications) in CPython. In MicroPython, they are somewhat simplified +and made implicit to achieve higher efficiencies and save resources. + +An important dichotomy in CPython is unbuffered vs buffered streams. In +MicroPython, all streams are currently unbuffered. This is because all +modern OSes, and even many RTOSes and filesystem drivers already perform +buffering on their side. Adding another layer of buffering is counter- +productive (an issue known as "bufferbloat") and takes precious memory. +Note that there still cases where buffering may be useful, so we may +introduce optional buffering support at a later time. + +But in CPython, another important dichotomy is tied with "bufferedness" - +it's whether a stream may incur short read/writes or not. A short read +is when a user asks e.g. 10 bytes from a stream, but gets less, similarly +for writes. In CPython, unbuffered streams are automatically short +operation susceptible, while buffered are guarantee against them. The +no short read/writes is an important trait, as it allows to develop +more concise and efficient programs - something which is highly desirable +for MicroPython. So, while MicroPython doesn't support buffered streams, +it still provides for no-short-operations streams. Whether there will +be short operations or not depends on each particular class' needs, but +developers are strongly advised to favor no-short-operations behavior +for the reasons stated above. For example, MicroPython sockets are +guaranteed to avoid short read/writes. Actually, at this time, there is +no example of a short-operations stream class in the core, and one would +be a port-specific class, where such a need is governed by hardware +peculiarities. + +The no-short-operations behavior gets tricky in case of non-blocking +streams, blocking vs non-blocking behavior being another CPython dichotomy, +fully supported by MicroPython. Non-blocking streams never wait for +data either to arrive or be written - they read/write whatever possible, +or signal lack of data (or ability to write data). Clearly, this conflicts +with "no-short-operations" policy, and indeed, a case of non-blocking +buffered (and this no-short-ops) streams is convoluted in CPython - in +some places, such combination is prohibited, in some it's undefined or +just not documented, in some cases it raises verbose exceptions. The +matter is much simpler in MicroPython: non-blocking stream are important +for efficient asynchronous operations, so this property prevails on +the "no-short-ops" one. So, while blocking streams will avoid short +reads/writes whenever possible (the only case to get a short read is +if end of file is reached, or in case of error (but errors don't +return short data, but raise exceptions)), non-blocking streams may +produce short data to avoid blocking the operation. + +The final dichotomy is binary vs text streams. MicroPython of course +supports these, but while in CPython text streams are inherently +buffered, they aren't in MicroPython. (Indeed, that's one of the cases +for which we may introduce buffering support.) + +Note that for efficiency, MicroPython doesn't provide abstract base +classes corresponding to the hierarchy above, and it's not possible +to implement, or subclass, a stream class in pure Python. + +Functions +--------- + +.. function:: open(name, mode='r', **kwargs) + + Open a file. Builtin ``open()`` function is aliased to this function. + All ports (which provide access to file system) are required to support + *mode* parameter, but support for other arguments vary by port. + +Classes +------- + +.. class:: FileIO(...) + + This is type of a file open in binary mode, e.g. using ``open(name, "rb")``. + You should not instantiate this class directly. + +.. class:: TextIOWrapper(...) + + This is type of a file open in text mode, e.g. using ``open(name, "rt")``. + You should not instantiate this class directly. + +.. class:: StringIO([string]) +.. class:: BytesIO([string]) + + In-memory file-like objects for input/output. `StringIO` is used for + text-mode I/O (similar to a normal file opened with "t" modifier). + `BytesIO` is used for binary-mode I/O (similar to a normal file + opened with "b" modifier). Initial contents of file-like objects + can be specified with *string* parameter (should be normal string + for `StringIO` or bytes object for `BytesIO`). All the usual file + methods like ``read()``, ``write()``, ``seek()``, ``flush()``, + ``close()`` are available on these objects, and additionally, a + following method: + + .. method:: getvalue() + + Get the current contents of the underlying buffer which holds data. diff --git a/MicroPython_BUILD/components/micropython/docs/library/ujson.rst b/MicroPython_BUILD/components/micropython/docs/library/ujson.rst new file mode 100644 index 00000000..5668eb21 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/ujson.rst @@ -0,0 +1,35 @@ +:mod:`ujson` -- JSON encoding and decoding +========================================== + +.. module:: ujson + :synopsis: JSON encoding and decoding + +|see_cpython_module| :mod:`python:json`. + +This modules allows to convert between Python objects and the JSON +data format. + +Functions +--------- + +.. function:: dump(obj, stream) + + Serialise *obj* to a JSON string, writing it to the given *stream*. + +.. function:: dumps(obj) + + Return *obj* represented as a JSON string. + +.. function:: load(stream) + + Parse the given *stream*, interpreting it as a JSON string and + deserialising the data to a Python object. The resulting object is + returned. + + Parsing continues until end-of-file is encountered. + A :exc:`ValueError` is raised if the data in *stream* is not correctly formed. + +.. function:: loads(str) + + Parse the JSON *str* and return an object. Raises :exc:`ValueError` if the + string is not correctly formed. diff --git a/MicroPython_BUILD/components/micropython/docs/library/uos.rst b/MicroPython_BUILD/components/micropython/docs/library/uos.rst new file mode 100644 index 00000000..27f339bb --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uos.rst @@ -0,0 +1,249 @@ +:mod:`uos` -- basic "operating system" services +=============================================== + +.. module:: uos + :synopsis: basic "operating system" services + +|see_cpython_module| :mod:`python:os`. + +The ``uos`` module contains functions for filesystem access and mounting, +terminal redirection and duplication, and the ``uname`` and ``urandom`` +functions. + +General functions +----------------- + +.. function:: uname() + + Return a tuple (possibly a named tuple) containing information about the + underlying machine and/or its operating system. The tuple has five fields + in the following order, each of them being a string: + + * ``sysname`` -- the name of the underlying system + * ``nodename`` -- the network name (can be the same as ``sysname``) + * ``release`` -- the version of the underlying system + * ``version`` -- the MicroPython version and build date + * ``machine`` -- an identifier for the underlying hardware (eg board, CPU) + +.. function:: urandom(n) + + Return a bytes object with *n* random bytes. Whenever possible, it is + generated by the hardware random number generator. + +Filesystem access +----------------- + +.. function:: chdir(path) + + Change current directory. + +.. function:: getcwd() + + Get the current directory. + +.. function:: ilistdir([dir]) + + This function returns an iterator which then yields tuples corresponding to + the entries in the directory that it is listing. With no argument it lists the + current directory, otherwise it lists the directory given by *dir*. + + The tuples have the form *(name, type, inode[, size])*: + + - *name* is a string (or bytes if *dir* is a bytes object) and is the name of + the entry; + - *type* is an integer that specifies the type of the entry, with 0x4000 for + directories and 0x8000 for regular files; + - *inode* is an integer corresponding to the inode of the file, and may be 0 + for filesystems that don't have such a notion. + - Some platforms may return a 4-tuple that includes the entry's *size*. For + file entries, *size* is an integer representing the size of the file + or -1 if unknown. Its meaning is currently undefined for directory + entries. + +.. function:: listdir([dir]) + + With no argument, list the current directory. Otherwise list the given directory. + +.. function:: mkdir(path) + + Create a new directory. + +.. function:: remove(path) + + Remove a file. + +.. function:: rmdir(path) + + Remove a directory. + +.. function:: rename(old_path, new_path) + + Rename a file. + +.. function:: stat(path) + + Get the status of a file or directory. + +.. function:: statvfs(path) + + Get the status of a fileystem. + + Returns a tuple with the filesystem information in the following order: + + * ``f_bsize`` -- file system block size + * ``f_frsize`` -- fragment size + * ``f_blocks`` -- size of fs in f_frsize units + * ``f_bfree`` -- number of free blocks + * ``f_bavail`` -- number of free blocks for unpriviliged users + * ``f_files`` -- number of inodes + * ``f_ffree`` -- number of free inodes + * ``f_favail`` -- number of free inodes for unpriviliged users + * ``f_flag`` -- mount flags + * ``f_namemax`` -- maximum filename length + + Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail`` + and the ``f_flags`` parameter may return ``0`` as they can be unavailable + in a port-specific implementation. + +.. function:: sync() + + Sync all filesystems. + +Terminal redirection and duplication +------------------------------------ + +.. function:: dupterm(stream_object, index=0) + + Duplicate or switch the MicroPython terminal (the REPL) on the given `stream`-like + object. The *stream_object* argument must implement the ``readinto()`` and + ``write()`` methods. The stream should be in non-blocking mode and + ``readinto()`` should return ``None`` if there is no data available for reading. + + After calling this function all terminal output is repeated on this stream, + and any input that is available on the stream is passed on to the terminal input. + + The *index* parameter should be a non-negative integer and specifies which + duplication slot is set. A given port may implement more than one slot (slot 0 + will always be available) and in that case terminal input and output is + duplicated on all the slots that are set. + + If ``None`` is passed as the *stream_object* then duplication is cancelled on + the slot given by *index*. + + The function returns the previous stream-like object in the given slot. + +Filesystem mounting +------------------- + +Some ports provide a Virtual Filesystem (VFS) and the ability to mount multiple +"real" filesystems within this VFS. Filesystem objects can be mounted at either +the root of the VFS, or at a subdirectory that lives in the root. This allows +dynamic and flexible configuration of the filesystem that is seen by Python +programs. Ports that have this functionality provide the :func:`mount` and +:func:`umount` functions, and possibly various filesystem implementations +represented by VFS classes. + +.. function:: mount(fsobj, mount_point, \*, readonly) + + Mount the filesystem object *fsobj* at the location in the VFS given by the + *mount_point* string. *fsobj* can be a a VFS object that has a ``mount()`` + method, or a block device. If it's a block device then the filesystem type + is automatically detected (an exception is raised if no filesystem was + recognised). *mount_point* may be ``'/'`` to mount *fsobj* at the root, + or ``'/'`` to mount it at a subdirectory under the root. + + If *readonly* is ``True`` then the filesystem is mounted read-only. + + During the mount process the method ``mount()`` is called on the filesystem + object. + + Will raise ``OSError(EPERM)`` if *mount_point* is already mounted. + +.. function:: umount(mount_point) + + Unmount a filesystem. *mount_point* can be a string naming the mount location, + or a previously-mounted filesystem object. During the unmount process the + method ``umount()`` is called on the filesystem object. + + Will raise ``OSError(EINVAL)`` if *mount_point* is not found. + +.. class:: VfsFat(block_dev) + + Create a filesystem object that uses the FAT filesystem format. Storage of + the FAT filesystem is provided by *block_dev*. + Objects created by this constructor can be mounted using :func:`mount`. + + .. staticmethod:: mkfs(block_dev) + + Build a FAT filesystem on *block_dev*. + +Block devices +------------- + +A block device is an object which implements the block protocol, which is a set +of methods described below by the :class:`AbstractBlockDev` class. A concrete +implementation of this class will usually allow access to the memory-like +functionality a piece of hardware (like flash memory). A block device can be +used by a particular filesystem driver to store the data for its filesystem. + +.. class:: AbstractBlockDev(...) + + Construct a block device object. The parameters to the constructor are + dependent on the specific block device. + + .. method:: readblocks(block_num, buf) + + Starting at *block_num*, read blocks from the device into *buf* (an array + of bytes). The number of blocks to read is given by the length of *buf*, + which will be a multiple of the block size. + + .. method:: writeblocks(block_num, buf) + + Starting at *block_num*, write blocks from *buf* (an array of bytes) to + the device. The number of blocks to write is given by the length of *buf*, + which will be a multiple of the block size. + + .. method:: ioctl(op, arg) + + Control the block device and query its parameters. The operation to + perform is given by *op* which is one of the following integers: + + - 1 -- initialise the device (*arg* is unused) + - 2 -- shutdown the device (*arg* is unused) + - 3 -- sync the device (*arg* is unused) + - 4 -- get a count of the number of blocks, should return an integer + (*arg* is unused) + - 5 -- get the number of bytes in a block, should return an integer, + or ``None`` in which case the default value of 512 is used + (*arg* is unused) + +By way of example, the following class will implement a block device that stores +its data in RAM using a ``bytearray``:: + + class RAMBlockDev: + def __init__(self, block_size, num_blocks): + self.block_size = block_size + self.data = bytearray(block_size * num_blocks) + + def readblocks(self, block_num, buf): + for i in range(len(buf)): + buf[i] = self.data[block_num * self.block_size + i] + + def writeblocks(self, block_num, buf): + for i in range(len(buf)): + self.data[block_num * self.block_size + i] = buf[i] + + def ioctl(self, op, arg): + if op == 4: # get number of blocks + return len(self.data) // self.block_size + if op == 5: # get block size + return self.block_size + +It can be used as follows:: + + import uos + + bdev = RAMBlockDev(512, 50) + uos.VfsFat.mkfs(bdev) + vfs = uos.VfsFat(bdev) + uos.mount(vfs, '/ramdisk') diff --git a/MicroPython_BUILD/components/micropython/docs/library/ure.rst b/MicroPython_BUILD/components/micropython/docs/library/ure.rst new file mode 100644 index 00000000..f54614f0 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/ure.rst @@ -0,0 +1,102 @@ +:mod:`ure` -- simple regular expressions +======================================== + +.. module:: ure + :synopsis: regular expressions + +|see_cpython_module| :mod:`python:re`. + +This module implements regular expression operations. Regular expression +syntax supported is a subset of CPython ``re`` module (and actually is +a subset of POSIX extended regular expressions). + +Supported operators are: + +``'.'`` + Match any character. + +``'[...]'`` + Match set of characters. Individual characters and ranges are supported, + including negated sets (e.g. ``[^a-c]``). + +``'^'`` + +``'$'`` + +``'?'`` + +``'*'`` + +``'+'`` + +``'??'`` + +``'*?'`` + +``'+?'`` + +``'|'`` + +``'(...)'`` + Grouping. Each group is capturing (a substring it captures can be accessed + with `match.group()` method). + +**NOT SUPPORTED**: Counted repetitions (``{m,n}``), more advanced assertions +(``\b``, ``\B``), named groups (``(?P...)``), non-capturing groups +(``(?:...)``), etc. + + +Functions +--------- + +.. function:: compile(regex_str, [flags]) + + Compile regular expression, return `regex ` object. + +.. function:: match(regex_str, string) + + Compile *regex_str* and match against *string*. Match always happens + from starting position in a string. + +.. function:: search(regex_str, string) + + Compile *regex_str* and search it in a *string*. Unlike `match`, this will search + string for first position which matches regex (which still may be + 0 if regex is anchored). + +.. data:: DEBUG + + Flag value, display debug information about compiled expression. + (Availability depends on `MicroPython port`.) + + +.. _regex: + +Regex objects +------------- + +Compiled regular expression. Instances of this class are created using +`ure.compile()`. + +.. method:: regex.match(string) + regex.search(string) + + Similar to the module-level functions :meth:`match` and :meth:`search`. + Using methods is (much) more efficient if the same regex is applied to + multiple strings. + +.. method:: regex.split(string, max_split=-1) + + Split a *string* using regex. If *max_split* is given, it specifies + maximum number of splits to perform. Returns list of strings (there + may be up to *max_split+1* elements if it's specified). + +Match objects +------------- + +Match objects as returned by `match()` and `search()` methods. + +.. method:: match.group([index]) + + Return matching (sub)string. *index* is 0 for entire match, + 1 and above for each capturing group. Only numeric groups are supported. diff --git a/MicroPython_BUILD/components/micropython/docs/library/uselect.rst b/MicroPython_BUILD/components/micropython/docs/library/uselect.rst new file mode 100644 index 00000000..77d45847 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uselect.rst @@ -0,0 +1,94 @@ +:mod:`uselect` -- wait for events on a set of streams +======================================================================== + +.. module:: uselect + :synopsis: wait for events on a set of streams + +|see_cpython_module| :mod:`python:select`. + +This module provides functions to efficiently wait for events on multiple +`streams ` (select streams which are ready for operations). + +Functions +--------- + +.. function:: poll() + + Create an instance of the Poll class. + +.. function:: select(rlist, wlist, xlist[, timeout]) + + Wait for activity on a set of objects. + + This function is provided by some MicroPython ports for compatibility + and is not efficient. Usage of :class:`Poll` is recommended instead. + +.. _class: Poll + +class ``Poll`` +-------------- + +Methods +~~~~~~~ + +.. method:: poll.register(obj[, eventmask]) + + Register `stream` *obj* for polling. *eventmask* is logical OR of: + + * ``uselect.POLLIN`` - data available for reading + * ``uselect.POLLOUT`` - more data can be written + + Note that flags like ``uselect.POLLHUP`` and ``uselect.POLLERR`` are + *not* valid as input eventmask (these are unsolicited events which + will be returned from `poll()` regardless of whether they are asked + for). This semantics is per POSIX. + + *eventmask* defaults to ``uselect.POLLIN | uselect.POLLOUT``. + +.. method:: poll.unregister(obj) + + Unregister *obj* from polling. + +.. method:: poll.modify(obj, eventmask) + + Modify the *eventmask* for *obj*. + +.. method:: poll.poll(timeout=-1) + + Wait for at least one of the registered objects to become ready or have an + exceptional condition, with optional timeout in milliseconds (if *timeout* + arg is not specified or -1, there is no timeout). + + Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in + tuple, depending on a platform and version, so don't assume that its size is 2. + The ``event`` element specifies which events happened with a stream and + is a combination of ``uselect.POLL*`` constants described above. Note that + flags ``uselect.POLLHUP`` and ``uselect.POLLERR`` can be returned at any time + (even if were not asked for), and must be acted on accordingly (the + corresponding stream unregistered from poll and likely closed), because + otherwise all further invocations of `poll()` may return immediately with + these flags set for this stream again. + + In case of timeout, an empty list is returned. + + .. admonition:: Difference to CPython + :class: attention + + Tuples returned may contain more than 2 elements as described above. + +.. method:: poll.ipoll(timeout=-1, flags=0) + + Like :meth:`poll.poll`, but instead returns an iterator which yields a + `callee-owned tuple`. This function provides an efficient, allocation-free + way to poll on streams. + + If *flags* is 1, one-shot behavior for events is employed: streams for + which events happened will have their event masks automatically reset + (equivalent to ``poll.modify(obj, 0)``), so new events for such a stream + won't be processed until new mask is set with `poll.modify()`. This + behavior is useful for asynchronous I/O schedulers. + + .. admonition:: Difference to CPython + :class: attention + + This function is a MicroPython extension. diff --git a/MicroPython_BUILD/components/micropython/docs/library/usocket.rst b/MicroPython_BUILD/components/micropython/docs/library/usocket.rst new file mode 100644 index 00000000..3ae477a9 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/usocket.rst @@ -0,0 +1,339 @@ +******************************* +:mod:`usocket` -- socket module +******************************* + +.. module:: usocket + :synopsis: socket module + +|see_cpython_module| :mod:`python:socket`. + +This module provides access to the BSD socket interface. + +.. admonition:: Difference to CPython + :class: attention + + For efficiency and consistency, socket objects in MicroPython implement a `stream` + (file-like) interface directly. In CPython, you need to convert a socket to + a file-like object using `makefile()` method. This method is still supported + by MicroPython (but is a no-op), so where compatibility with CPython matters, + be sure to use it. + +Socket address format(s) +------------------------ + +The native socket address format of the ``usocket`` module is an opaque data type +returned by `getaddrinfo` function, which must be used to resolve textual address +(including numeric addresses):: + + sockaddr = usocket.getaddrinfo('www.micropython.org', 80)[0][-1] + # You must use getaddrinfo() even for numeric addresses + sockaddr = usocket.getaddrinfo('127.0.0.1', 80)[0][-1] + # Now you can use that address + sock.connect(addr) + +Using `getaddrinfo` is the most efficient (both in terms of memory and processing +power) and portable way to work with addresses. + +However, ``socket`` module (note the difference with native MicroPython +``usocket`` module described here) provides CPython-compatible way to specify +addresses using tuples, as described below. Note that depending on a +`MicroPython port`, ``socket`` module can be builtin or need to be +installed from `micropython-lib` (as in the case of `MicroPython Unix port`), +and some ports still accept only numeric addresses in the tuple format, +and require to use `getaddrinfo` function to resolve domain names. + +Summing up: + +* Always use `getaddrinfo` when writing portable applications. +* Tuple addresses described below can be used as a shortcut for + quick hacks and interactive use, if your port supports them. + +Tuple address format for ``socket`` module: + +* IPv4: *(ipv4_address, port)*, where *ipv4_address* is a string with + dot-notation numeric IPv4 address, e.g. ``"8.8.8.8"``, and *port* is and + integer port number in the range 1-65535. Note the domain names are not + accepted as *ipv4_address*, they should be resolved first using + `usocket.getaddrinfo()`. +* IPv6: *(ipv6_address, port, flowinfo, scopeid)*, where *ipv6_address* + is a string with colon-notation numeric IPv6 address, e.g. ``"2001:db8::1"``, + and *port* is an integer port number in the range 1-65535. *flowinfo* + must be 0. *scopeid* is the interface scope identifier for link-local + addresses. Note the domain names are not accepted as *ipv6_address*, + they should be resolved first using `usocket.getaddrinfo()`. Availability + of IPv6 support depends on a `MicroPython port`. + +Functions +--------- + +.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP) + + Create a new socket using the given address family, socket type and + protocol number. Note that specifying *proto* in most cases is not + required (and not recommended, as some MicroPython ports may omit + ``IPPROTO_*`` constants). Instead, *type* argument will select needed + protocol automatically:: + + # Create STREAM TCP socket + socket(AF_INET, SOCK_STREAM) + # Create DGRAM UDP socket + socket(AF_INET, SOCK_DGRAM) + +.. function:: getaddrinfo(host, port) + + Translate the host/port argument into a sequence of 5-tuples that contain all the + necessary arguments for creating a socket connected to that service. The list of + 5-tuples has following structure:: + + (family, type, proto, canonname, sockaddr) + + The following example shows how to connect to a given url:: + + s = usocket.socket() + s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1]) + + .. admonition:: Difference to CPython + :class: attention + + CPython raises a ``socket.gaierror`` exception (`OSError` subclass) in case + of error in this function. MicroPython doesn't have ``socket.gaierror`` + and raises OSError directly. Note that error numbers of `getaddrinfo()` + form a separate namespace and may not match error numbers from + the :mod:`uerrno` module. To distinguish `getaddrinfo()` errors, they are + represented by negative numbers, whereas standard system errors are + positive numbers (error numbers are accessible using ``e.args[0]`` property + from an exception object). The use of negative values is a provisional + detail which may change in the future. + +.. function:: inet_ntop(af, bin_addr) + + Convert a binary network address *bin_addr* of the given address family *af* + to a textual representation:: + + >>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1") + '127.0.0.1' + +.. function:: inet_pton(af, txt_addr) + + Convert a textual network address *txt_addr* of the given address family *af* + to a binary representation:: + + >>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4") + b'\x01\x02\x03\x04' + +Constants +--------- + +.. data:: AF_INET + AF_INET6 + + Address family types. Availability depends on a particular `MicroPython port`. + +.. data:: SOCK_STREAM + SOCK_DGRAM + + Socket types. + +.. data:: IPPROTO_UDP + IPPROTO_TCP + + IP protocol numbers. Availability depends on a particular `MicroPython port`. + Note that you don't need to specify these in a call to `usocket.socket()`, + because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and + `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants + is as an argument to `setsockopt()`. + +.. data:: usocket.SOL_* + + Socket option levels (an argument to `setsockopt()`). The exact + inventory depends on a `MicroPython port`. + +.. data:: usocket.SO_* + + Socket options (an argument to `setsockopt()`). The exact + inventory depends on a `MicroPython port`. + +Constants specific to WiPy: + +.. data:: IPPROTO_SEC + + Special protocol value to create SSL-compatible socket. + +class socket +============ + +Methods +------- + +.. method:: socket.close() + + Mark the socket closed and release all resources. Once that happens, all future operations + on the socket object will fail. The remote end will receive EOF indication if + supported by protocol. + + Sockets are automatically closed when they are garbage-collected, but it is recommended + to `close()` them explicitly as soon you finished working with them. + +.. method:: socket.bind(address) + + Bind the socket to *address*. The socket must not already be bound. + +.. method:: socket.listen([backlog]) + + Enable a server to accept connections. If *backlog* is specified, it must be at least 0 + (if it's lower, it will be set to 0); and specifies the number of unaccepted connections + that the system will allow before refusing new connections. If not specified, a default + reasonable value is chosen. + +.. method:: socket.accept() + + Accept a connection. The socket must be bound to an address and listening for connections. + The return value is a pair (conn, address) where conn is a new socket object usable to send + and receive data on the connection, and address is the address bound to the socket on the + other end of the connection. + +.. method:: socket.connect(address) + + Connect to a remote socket at *address*. + +.. method:: socket.send(bytes) + + Send data to the socket. The socket must be connected to a remote socket. + Returns number of bytes sent, which may be smaller than the length of data + ("short write"). + +.. method:: socket.sendall(bytes) + + Send all data to the socket. The socket must be connected to a remote socket. + Unlike `send()`, this method will try to send all of data, by sending data + chunk by chunk consecutively. + + The behavior of this method on non-blocking sockets is undefined. Due to this, + on MicroPython, it's recommended to use `write()` method instead, which + has the same "no short writes" policy for blocking sockets, and will return + number of bytes sent on non-blocking sockets. + +.. method:: socket.recv(bufsize) + + Receive data from the socket. The return value is a bytes object representing the data + received. The maximum amount of data to be received at once is specified by bufsize. + +.. method:: socket.sendto(bytes, address) + + Send data to the socket. The socket should not be connected to a remote socket, since the + destination socket is specified by *address*. + +.. method:: socket.recvfrom(bufsize) + + Receive data from the socket. The return value is a pair *(bytes, address)* where *bytes* is a + bytes object representing the data received and *address* is the address of the socket sending + the data. + +.. method:: socket.setsockopt(level, optname, value) + + Set the value of the given socket option. The needed symbolic constants are defined in the + socket module (SO_* etc.). The *value* can be an integer or a bytes-like object representing + a buffer. + +.. method:: socket.settimeout(value) + + **Note**: Not every port supports this method, see below. + + Set a timeout on blocking socket operations. The value argument can be a nonnegative floating + point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations + will raise an `OSError` exception if the timeout period value has elapsed before the operation has + completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket + is put in blocking mode. + + Not every `MicroPython port` supports this method. A more portable and + generic solution is to use `uselect.poll` object. This allows to wait on + multiple objects at the same time (and not just on sockets, but on generic + `stream` objects which support polling). Example:: + + # Instead of: + s.settimeout(1.0) # time in seconds + s.read(10) # may timeout + + # Use: + poller = uselect.poll() + poller.register(s, uselect.POLLIN) + res = poller.poll(1000) # time in milliseconds + if not res: + # s is still not ready for input, i.e. operation timed out + + .. admonition:: Difference to CPython + :class: attention + + CPython raises a ``socket.timeout`` exception in case of timeout, + which is an `OSError` subclass. MicroPython raises an OSError directly + instead. If you use ``except OSError:`` to catch the exception, + your code will work both in MicroPython and CPython. + +.. method:: socket.setblocking(flag) + + Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking, + else to blocking mode. + + This method is a shorthand for certain `settimeout()` calls: + + * ``sock.setblocking(True)`` is equivalent to ``sock.settimeout(None)`` + * ``sock.setblocking(False)`` is equivalent to ``sock.settimeout(0)`` + +.. method:: socket.makefile(mode='rb', buffering=0) + + Return a file object associated with the socket. The exact returned type depends on the arguments + given to makefile(). The support is limited to binary modes only ('rb', 'wb', and 'rwb'). + CPython's arguments: *encoding*, *errors* and *newline* are not supported. + + .. admonition:: Difference to CPython + :class: attention + + As MicroPython doesn't support buffered streams, values of *buffering* + parameter is ignored and treated as if it was 0 (unbuffered). + + .. admonition:: Difference to CPython + :class: attention + + Closing the file object returned by makefile() WILL close the + original socket as well. + +.. method:: socket.read([size]) + + Read up to size bytes from the socket. Return a bytes object. If *size* is not given, it + reads all data available from the socket until EOF; as such the method will not return until + the socket is closed. This function tries to read as much data as + requested (no "short reads"). This may be not possible with + non-blocking socket though, and then less data will be returned. + +.. method:: socket.readinto(buf[, nbytes]) + + Read bytes into the *buf*. If *nbytes* is specified then read at most + that many bytes. Otherwise, read at most *len(buf)* bytes. Just as + `read()`, this method follows "no short reads" policy. + + Return value: number of bytes read and stored into *buf*. + +.. method:: socket.readline() + + Read a line, ending in a newline character. + + Return value: the line read. + +.. method:: socket.write(buf) + + Write the buffer of bytes to the socket. This function will try to + write all data to a socket (no "short writes"). This may be not possible + with a non-blocking socket though, and returned value will be less than + the length of *buf*. + + Return value: number of bytes written. + +.. exception:: usocket.error + + MicroPython does NOT have this exception. + + .. admonition:: Difference to CPython + :class: attention + + CPython used to have a ``socket.error`` exception which is now deprecated, + and is an alias of `OSError`. In MicroPython, use `OSError` directly. diff --git a/MicroPython_BUILD/components/micropython/docs/library/ussl.rst b/MicroPython_BUILD/components/micropython/docs/library/ussl.rst new file mode 100644 index 00000000..be84dc05 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/ussl.rst @@ -0,0 +1,48 @@ +:mod:`ussl` -- SSL/TLS module +============================= + +.. module:: ussl + :synopsis: TLS/SSL wrapper for socket objects + +|see_cpython_module| :mod:`python:ssl`. + +This module provides access to Transport Layer Security (previously and +widely known as “Secure Sockets Layer”) encryption and peer authentication +facilities for network sockets, both client-side and server-side. + +Functions +--------- + +.. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None) + + Takes a `stream` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type), + and returns an instance of ssl.SSLSocket, which wraps the underlying stream in + an SSL context. Returned object has the usual `stream` interface methods like + ``read()``, ``write()``, etc. In MicroPython, the returned object does not expose + socket interface and methods like ``recv()``, ``send()``. In particular, a + server-side SSL socket should be created from a normal socket returned from + :meth:`~usocket.socket.accept()` on a non-SSL listening server socket. + + Depending on the underlying module implementation in a particular + `MicroPython port`, some or all keyword arguments above may be not supported. + +.. warning:: + + Some implementations of ``ussl`` module do NOT validate server certificates, + which makes an SSL connection established prone to man-in-the-middle attacks. + +Exceptions +---------- + +.. data:: ssl.SSLError + + This exception does NOT exist. Instead its base class, OSError, is used. + +Constants +--------- + +.. data:: ussl.CERT_NONE + ussl.CERT_OPTIONAL + ussl.CERT_REQUIRED + + Supported values for *cert_reqs* parameter. diff --git a/MicroPython_BUILD/components/micropython/docs/library/ustruct.rst b/MicroPython_BUILD/components/micropython/docs/library/ustruct.rst new file mode 100644 index 00000000..81915d0a --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/ustruct.rst @@ -0,0 +1,42 @@ +:mod:`ustruct` -- pack and unpack primitive data types +====================================================== + +.. module:: ustruct + :synopsis: pack and unpack primitive data types + +|see_cpython_module| :mod:`python:struct`. + +Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``. + +Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, +``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending +on the floating-point support). + +Functions +--------- + +.. function:: calcsize(fmt) + + Return the number of bytes needed to store the given *fmt*. + +.. function:: pack(fmt, v1, v2, ...) + + Pack the values *v1*, *v2*, ... according to the format string *fmt*. + The return value is a bytes object encoding the values. + +.. function:: pack_into(fmt, buffer, offset, v1, v2, ...) + + Pack the values *v1*, *v2*, ... according to the format string *fmt* + into a *buffer* starting at *offset*. *offset* may be negative to count + from the end of *buffer*. + +.. function:: unpack(fmt, data) + + Unpack from the *data* according to the format string *fmt*. + The return value is a tuple of the unpacked values. + +.. function:: unpack_from(fmt, data, offset=0) + + Unpack from the *data* starting at *offset* according to the format string + *fmt*. *offset* may be negative to count from the end of *buffer*. The return + value is a tuple of the unpacked values. diff --git a/MicroPython_BUILD/components/micropython/docs/library/utime.rst b/MicroPython_BUILD/components/micropython/docs/library/utime.rst new file mode 100644 index 00000000..7fe83f5a --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/utime.rst @@ -0,0 +1,229 @@ +:mod:`utime` -- time related functions +====================================== + +.. module:: utime + :synopsis: time related functions + +|see_cpython_module| :mod:`python:time`. + +The ``utime`` module provides functions for getting the current time and date, +measuring time intervals, and for delays. + +**Time Epoch**: Unix port uses standard for POSIX systems epoch of +1970-01-01 00:00:00 UTC. However, embedded ports use epoch of +2000-01-01 00:00:00 UTC. + +**Maintaining actual calendar date/time**: This requires a +Real Time Clock (RTC). On systems with underlying OS (including some +RTOS), an RTC may be implicit. Setting and maintaining actual calendar +time is responsibility of OS/RTOS and is done outside of MicroPython, +it just uses OS API to query date/time. On baremetal ports however +system time depends on ``machine.RTC()`` object. The current calendar time +may be set using ``machine.RTC().datetime(tuple)`` function, and maintained +by following means: + +* By a backup battery (which may be an additional, optional component for + a particular board). +* Using networked time protocol (requires setup by a port/user). +* Set manually by a user on each power-up (many boards then maintain + RTC time across hard resets, though some may require setting it again + in such case). + +If actual calendar time is not maintained with a system/MicroPython RTC, +functions below which require reference to current absolute time may +behave not as expected. + +Functions +--------- + +.. function:: localtime([secs]) + + Convert a time expressed in seconds since the Epoch (see above) into an 8-tuple which + contains: (year, month, mday, hour, minute, second, weekday, yearday) + If secs is not provided or None, then the current time from the RTC is used. + + * year includes the century (for example 2014). + * month is 1-12 + * mday is 1-31 + * hour is 0-23 + * minute is 0-59 + * second is 0-59 + * weekday is 0-6 for Mon-Sun + * yearday is 1-366 + +.. function:: mktime() + + This is inverse function of localtime. It's argument is a full 8-tuple + which expresses a time as per localtime. It returns an integer which is + the number of seconds since Jan 1, 2000. + +.. function:: sleep(seconds) + + Sleep for the given number of seconds. Some boards may accept *seconds* as a + floating-point number to sleep for a fractional number of seconds. Note that + other boards may not accept a floating-point argument, for compatibility with + them use `sleep_ms()` and `sleep_us()` functions. + +.. function:: sleep_ms(ms) + + Delay for given number of milliseconds, should be positive or 0. + +.. function:: sleep_us(us) + + Delay for given number of microseconds, should be positive or 0. + +.. function:: ticks_ms() + + Returns an increasing millisecond counter with an arbitrary reference point, that + wraps around after some value. + + The wrap-around value is not explicitly exposed, but we will + refer to it as *TICKS_MAX* to simplify discussion. Period of the values is + *TICKS_PERIOD = TICKS_MAX + 1*. *TICKS_PERIOD* is guaranteed to be a power of + two, but otherwise may differ from port to port. The same period value is used + for all of `ticks_ms()`, `ticks_us()`, `ticks_cpu()` functions (for + simplicity). Thus, these functions will return a value in range [*0* .. + *TICKS_MAX*], inclusive, total *TICKS_PERIOD* values. Note that only + non-negative values are used. For the most part, you should treat values returned + by these functions as opaque. The only operations available for them are + `ticks_diff()` and `ticks_add()` functions described below. + + Note: Performing standard mathematical operations (+, -) or relational + operators (<, <=, >, >=) directly on these value will lead to invalid + result. Performing mathematical operations and then passing their results + as arguments to `ticks_diff()` or `ticks_add()` will also lead to + invalid results from the latter functions. + +.. function:: ticks_us() + + Just like `ticks_ms()` above, but in microseconds. + +.. function:: ticks_cpu() + + Similar to `ticks_ms()` and `ticks_us()`, but with the highest possible resolution + in the system. This is usually CPU clocks, and that's why the function is named that + way. But it doesn't have to be a CPU clock, some other timing source available in a + system (e.g. high-resolution timer) can be used instead. The exact timing unit + (resolution) of this function is not specified on ``utime`` module level, but + documentation for a specific port may provide more specific information. This + function is intended for very fine benchmarking or very tight real-time loops. + Avoid using it in portable code. + + Availability: Not every port implements this function. + + +.. function:: ticks_add(ticks, delta) + + Offset ticks value by a given number, which can be either positive or negative. + Given a *ticks* value, this function allows to calculate ticks value *delta* + ticks before or after it, following modular-arithmetic definition of tick values + (see `ticks_ms()` above). *ticks* parameter must be a direct result of call + to `ticks_ms()`, `ticks_us()`, or `ticks_cpu()` functions (or from previous + call to `ticks_add()`). However, *delta* can be an arbitrary integer number + or numeric expression. `ticks_add()` is useful for calculating deadlines for + events/tasks. (Note: you must use `ticks_diff()` function to work with + deadlines.) + + Examples:: + + # Find out what ticks value there was 100ms ago + print(ticks_add(time.ticks_ms(), -100)) + + # Calculate deadline for operation and test for it + deadline = ticks_add(time.ticks_ms(), 200) + while ticks_diff(deadline, time.ticks_ms()) > 0: + do_a_little_of_something() + + # Find out TICKS_MAX used by this port + print(ticks_add(0, -1)) + + +.. function:: ticks_diff(ticks1, ticks2) + + Measure ticks difference between values returned from `ticks_ms()`, `ticks_us()`, + or `ticks_cpu()` functions, as a signed value which may wrap around. + + The argument order is the same as for subtraction + operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. + However, values returned by `ticks_ms()`, etc. functions may wrap around, so + directly using subtraction on them will produce incorrect result. That is why + `ticks_diff()` is needed, it implements modular (or more specifically, ring) + arithmetics to produce correct result even for wrap-around values (as long as they not + too distant inbetween, see below). The function returns **signed** value in the range + [*-TICKS_PERIOD/2* .. *TICKS_PERIOD/2-1*] (that's a typical range definition for + two's-complement signed binary integers). If the result is negative, it means that + *ticks1* occurred earlier in time than *ticks2*. Otherwise, it means that + *ticks1* occurred after *ticks2*. This holds **only** if *ticks1* and *ticks2* + are apart from each other for no more than *TICKS_PERIOD/2-1* ticks. If that does + not hold, incorrect result will be returned. Specifically, if two tick values are + apart for *TICKS_PERIOD/2-1* ticks, that value will be returned by the function. + However, if *TICKS_PERIOD/2* of real-time ticks has passed between them, the + function will return *-TICKS_PERIOD/2* instead, i.e. result value will wrap around + to the negative range of possible values. + + Informal rationale of the constraints above: Suppose you are locked in a room with no + means to monitor passing of time except a standard 12-notch clock. Then if you look at + dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a + long sleep), then once you finally look again, it may seem to you that only 1 hour + has passed. To avoid this mistake, just look at the clock regularly. Your application + should do the same. "Too long sleep" metaphor also maps directly to application + behavior: don't let your application run any single task for too long. Run tasks + in steps, and do time-keeping inbetween. + + `ticks_diff()` is designed to accommodate various usage patterns, among them: + + * Polling with timeout. In this case, the order of events is known, and you will deal + only with positive results of `ticks_diff()`:: + + # Wait for GPIO pin to be asserted, but at most 500us + start = time.ticks_us() + while pin.value() == 0: + if time.ticks_diff(time.ticks_us(), start) > 500: + raise TimeoutError + + * Scheduling events. In this case, `ticks_diff()` result may be negative + if an event is overdue:: + + # This code snippet is not optimized + now = time.ticks_ms() + scheduled_time = task.scheduled_time() + if ticks_diff(scheduled_time, now) > 0: + print("Too early, let's nap") + sleep_ms(ticks_diff(scheduled_time, now)) + task.run() + elif ticks_diff(scheduled_time, now) == 0: + print("Right at time!") + task.run() + elif ticks_diff(scheduled_time, now) < 0: + print("Oops, running late, tell task to run faster!") + task.run(run_faster=true) + + Note: Do not pass `time()` values to `ticks_diff()`, you should use + normal mathematical operations on them. But note that `time()` may (and will) + also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem . + + +.. function:: time() + + Returns the number of seconds, as an integer, since the Epoch, assuming that + underlying RTC is set and maintained as described above. If an RTC is not set, this + function returns number of seconds since a port-specific reference point in time (for + embedded boards without a battery-backed RTC, usually since power up or reset). If you + want to develop portable MicroPython application, you should not rely on this function + to provide higher than second precision. If you need higher precision, use + `ticks_ms()` and `ticks_us()` functions, if you need calendar time, + `localtime()` without an argument is a better choice. + + .. admonition:: Difference to CPython + :class: attention + + In CPython, this function returns number of + seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point, + usually having microsecond precision. With MicroPython, only Unix port + uses the same Epoch, and if floating-point precision allows, + returns sub-second precision. Embedded hardware usually doesn't have + floating-point precision to represent both long time ranges and subsecond + precision, so they use integer value with second precision. Some embedded + hardware also lacks battery-powered RTC, so returns number of seconds + since last power-up or from other relative, hardware-specific point + (e.g. reset). diff --git a/MicroPython_BUILD/components/micropython/docs/library/uzlib.rst b/MicroPython_BUILD/components/micropython/docs/library/uzlib.rst new file mode 100644 index 00000000..0b399f22 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/library/uzlib.rst @@ -0,0 +1,38 @@ +:mod:`uzlib` -- zlib decompression +================================== + +.. module:: uzlib + :synopsis: zlib decompression + +|see_cpython_module| :mod:`python:zlib`. + +This module allows to decompress binary data compressed with +`DEFLATE algorithm `_ +(commonly used in zlib library and gzip archiver). Compression +is not yet implemented. + +Functions +--------- + +.. function:: decompress(data, wbits=0, bufsize=0) + + Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window + size used during compression (8-15, the dictionary size is power of 2 of + that value). Additionally, if value is positive, *data* is assumed to be + zlib stream (with zlib header). Otherwise, if it's negative, it's assumed + to be raw DEFLATE stream. *bufsize* parameter is for compatibility with + CPython and is ignored. + +.. class:: DecompIO(stream, wbits=0) + + Create a `stream` wrapper which allows transparent decompression of + compressed data in another *stream*. This allows to process compressed + streams with data larger than available heap size. In addition to + values described in :func:`decompress`, *wbits* may take values + 24..31 (16 + 8..15), meaning that input stream has gzip header. + + .. admonition:: Difference to CPython + :class: attention + + This class is MicroPython extension. It's included on provisional + basis and may be changed considerably or removed in later versions. diff --git a/MicroPython_BUILD/components/micropython/docs/license.rst b/MicroPython_BUILD/components/micropython/docs/license.rst new file mode 100644 index 00000000..73caa903 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/docs/license.rst @@ -0,0 +1,24 @@ +MicroPython license information +=============================== + +The MIT License (MIT) + +Copyright (c) 2013-2017 Damien P. George, and others + +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/MicroPython_BUILD/components/micropython/docs/zones.csv b/MicroPython_BUILD/components/micropython/docs/zones.csv index 5ce55ec0..ae0bc5f9 100644 --- a/MicroPython_BUILD/components/micropython/docs/zones.csv +++ b/MicroPython_BUILD/components/micropython/docs/zones.csv @@ -46,7 +46,7 @@ "Africa/Nouakchott","GMT0" "Africa/Ouagadougou","GMT0" "Africa/Porto-Novo","WAT-1" -"Africa/Sao_Tome","GMT0" +"Africa/Sao_Tome","WAT-1" "Africa/Tripoli","EET-2" "Africa/Tunis","CET-1" "Africa/Windhoek","CAT-2" @@ -80,7 +80,7 @@ "America/Bogota","<-05>5" "America/Boise","MST7MDT,M3.2.0,M11.1.0" "America/Cambridge_Bay","MST7MDT,M3.2.0,M11.1.0" -"America/Campo_Grande","<-04>4<-03>,M10.3.0/0,M2.3.0/0" +"America/Campo_Grande","<-04>4<-03>,M11.1.0/0,M2.3.0/0" "America/Cancun","EST5" "America/Caracas","<-04>4" "America/Cayenne","<-03>3" @@ -89,7 +89,7 @@ "America/Chihuahua","MST7MDT,M4.1.0,M10.5.0" "America/Costa_Rica","CST6" "America/Creston","MST7" -"America/Cuiaba","<-04>4<-03>,M10.3.0/0,M2.3.0/0" +"America/Cuiaba","<-04>4<-03>,M11.1.0/0,M2.3.0/0" "America/Curacao","AST4" "America/Danmarkshavn","GMT0" "America/Dawson","PST8PDT,M3.2.0,M11.1.0" @@ -177,7 +177,7 @@ "America/Santarem","<-03>3" "America/Santiago","<-04>4<-03>,M8.2.6/24,M5.2.6/24" "America/Santo_Domingo","AST4" -"America/Sao_Paulo","<-03>3<-02>,M10.3.0/0,M2.3.0/0" +"America/Sao_Paulo","<-03>3<-02>,M11.1.0/0,M2.3.0/0" "America/Scoresbysund","<-01>1<+00>,M3.5.0/0,M10.5.0/1" "America/Sitka","AKST9AKDT,M3.2.0,M11.1.0" "America/St_Barthelemy","AST4" @@ -198,7 +198,7 @@ "America/Winnipeg","CST6CDT,M3.2.0,M11.1.0" "America/Yakutat","AKST9AKDT,M3.2.0,M11.1.0" "America/Yellowknife","MST7MDT,M3.2.0,M11.1.0" -"Antarctica/Casey","<+11>-11" +"Antarctica/Casey","<+08>-8" "Antarctica/Davis","<+07>-7" "Antarctica/DumontDUrville","<+10>-10" "Antarctica/Macquarie","<+11>-11" @@ -235,8 +235,8 @@ "Asia/Dubai","<+04>-4" "Asia/Dushanbe","<+05>-5" "Asia/Famagusta","EET-2EEST,M3.5.0/3,M10.5.0/4" -"Asia/Gaza","EET-2EEST,M3.5.6/1,M10.5.6/1" -"Asia/Hebron","EET-2EEST,M3.5.6/1,M10.5.6/1" +"Asia/Gaza","EET-2EEST,M3.4.6/1,M10.5.6/1" +"Asia/Hebron","EET-2EEST,M3.4.6/1,M10.5.6/1" "Asia/Ho_Chi_Minh","<+07>-7" "Asia/Hong_Kong","HKT-8" "Asia/Hovd","<+07>-7" diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/cc3000_common.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/cc3000_common.h deleted file mode 100644 index aa162423..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/cc3000_common.h +++ /dev/null @@ -1,365 +0,0 @@ -/***************************************************************************** -* -* cc3000_common.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_COMMON_H__ -#define __CC3000_COMMON_H__ - -#include "data_types.h" - -//****************************************************************************** -// Include files -//****************************************************************************** -#include -#include - -//***************************************************************************** -// Prefix exported names to avoid name clash -//***************************************************************************** -#define CC3000_EXPORT(name) cc3000_ ## name - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -extern int CC3000_EXPORT(errno); - -//***************************************************************************** -// ERROR CODES -//***************************************************************************** -#define ESUCCESS 0 -#define EFAIL -1 -#define EERROR EFAIL - -//***************************************************************************** -// COMMON DEFINES -//***************************************************************************** -#define ERROR_SOCKET_INACTIVE -57 - -#define WLAN_ENABLE (1) -#define WLAN_DISABLE (0) - -#define MAC_ADDR_LEN (6) - -#define SP_PORTION_SIZE (32) - -/*Defines for minimal and maximal RX buffer size. This size includes the spi - header and hci header. - The maximal buffer size derives from: - MTU + HCI header + SPI header + sendto() agrs size - The minimum buffer size derives from: - HCI header + SPI header + max args size - - This buffer is used for receiving events and data. - The packet can not be longer than MTU size and CC3000 does not support - fragmentation. Note that the same buffer is used for reception of the data - and events from CC3000. That is why the minimum is defined. - The calculation for the actual size of buffer for reception is: - Given the maximal data size MAX_DATA that is expected to be received by - application, the required buffer is: - Using recv() or recvfrom(): - - max(CC3000_MINIMAL_RX_SIZE, MAX_DATA + HEADERS_SIZE_DATA + fromlen - + ucArgsize + 1) - - Using gethostbyname() with minimal buffer size will limit the host name - returned to 99 bytes only. - The 1 is used for the overrun detection - - Buffer size increased to 130 following the add_profile() with WEP security - which requires TX buffer size of 130 bytes: - HEADERS_SIZE_EVNT + WLAN_ADD_PROFILE_WEP_PARAM_LEN + MAX SSID LEN + 4 * MAX KEY LEN = 130 - MAX SSID LEN = 32 - MAX SSID LEN = 13 (with add_profile only ascii key setting is supported, - therfore maximum key size is 13) -*/ - -#define CC3000_MINIMAL_RX_SIZE (130 + 1) -#define CC3000_MAXIMAL_RX_SIZE (1519 + 1) - -/*Defines for minimal and maximal TX buffer size. - This buffer is used for sending events and data. - The packet can not be longer than MTU size and CC3000 does not support - fragmentation. Note that the same buffer is used for transmission of the data - and commands. That is why the minimum is defined. - The calculation for the actual size of buffer for transmission is: - Given the maximal data size MAX_DATA, the required buffer is: - Using Sendto(): - - max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE - + SOCKET_SENDTO_PARAMS_LEN + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) - - Using Send(): - - max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE - + HCI_CMND_SEND_ARG_LENGTH + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1) - - The 1 is used for the overrun detection */ - -#define CC3000_MINIMAL_TX_SIZE (130 + 1) -#define CC3000_MAXIMAL_TX_SIZE (1519 + 1) - -//TX and RX buffer sizes, allow to receive and transmit maximum data at length 8. -#ifdef CC3000_TINY_DRIVER -#define TINY_CC3000_MAXIMAL_RX_SIZE 44 -#define TINY_CC3000_MAXIMAL_TX_SIZE 59 -#endif - -/*In order to determine your preferred buffer size, - change CC3000_MAXIMAL_RX_SIZE and CC3000_MAXIMAL_TX_SIZE to a value between - the minimal and maximal specified above. - Note that the buffers are allocated by SPI. - In case you change the size of those buffers, you might need also to change - the linker file, since for example on MSP430 FRAM devices the buffers are - allocated in the FRAM section that is allocated manually and not by IDE. -*/ - -#ifndef CC3000_TINY_DRIVER - - #define CC3000_RX_BUFFER_SIZE (CC3000_MAXIMAL_RX_SIZE) - #define CC3000_TX_BUFFER_SIZE (CC3000_MAXIMAL_TX_SIZE) - -//if defined TINY DRIVER we use smaller RX and TX buffer in order to minimize RAM consumption -#else - #define CC3000_RX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_RX_SIZE) - #define CC3000_TX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_TX_SIZE) - -#endif - -//***************************************************************************** -// Compound Types -//***************************************************************************** -typedef INT32 time_t; -typedef UINT32 clock_t; -typedef INT32 suseconds_t; - -typedef struct cc3000_timeval cc3000_timeval; - -struct cc3000_timeval -{ - time_t tv_sec; /* seconds */ - suseconds_t tv_usec; /* microseconds */ -}; - -typedef CHAR *(*tFWPatches)(UINT32 *usLength); - -typedef CHAR *(*tDriverPatches)(UINT32 *usLength); - -typedef CHAR *(*tBootLoaderPatches)(UINT32 *usLength); - -typedef void (*tWlanCB)(INT32 event_type, CHAR * data, UINT8 length ); - -typedef INT32 (*tWlanReadInteruptPin)(void); - -typedef void (*tWlanInterruptEnable)(void); - -typedef void (*tWlanInterruptDisable)(void); - -typedef void (*tWriteWlanPin)(UINT8 val); - -typedef struct -{ - UINT16 usRxEventOpcode; - UINT16 usEventOrDataReceived; - UINT8 *pucReceivedData; - UINT8 *pucTxCommandBuffer; - - tFWPatches sFWPatches; - tDriverPatches sDriverPatches; - tBootLoaderPatches sBootLoaderPatches; - tWlanCB sWlanCB; - tWlanReadInteruptPin ReadWlanInterruptPin; - tWlanInterruptEnable WlanInterruptEnable; - tWlanInterruptDisable WlanInterruptDisable; - tWriteWlanPin WriteWlanPin; - - INT32 slTransmitDataError; - UINT16 usNumberOfFreeBuffers; - UINT16 usSlBufferLength; - UINT16 usBufferSize; - UINT16 usRxDataPending; - - UINT32 NumberOfSentPackets; - UINT32 NumberOfReleasedPackets; - - UINT8 InformHostOnTxComplete; -}sSimplLinkInformation; - -extern volatile sSimplLinkInformation tSLInformation; - - -//***************************************************************************** -// Prototypes for the APIs. -//***************************************************************************** - - - -//***************************************************************************** -// -//! SimpleLinkWaitEvent -//! -//! @param usOpcode command operation code -//! @param pRetParams command return parameters -//! -//! @return none -//! -//! @brief Wait for event, pass it to the hci_event_handler and -//! update the event opcode in a global variable. -// -//***************************************************************************** - -extern void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams); - -//***************************************************************************** -// -//! SimpleLinkWaitData -//! -//! @param pBuf data buffer -//! @param from from information -//! @param fromlen from information length -//! -//! @return none -//! -//! @brief Wait for data, pass it to the hci_event_handler -//! and update in a global variable that there is -//! data to read. -// -//***************************************************************************** - -extern void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen); - -//***************************************************************************** -// -//! UINT32_TO_STREAM_f -//! -//! \param p pointer to the new stream -//! \param u32 pointer to the 32 bit -//! -//! \return pointer to the new stream -//! -//! \brief This function is used for copying 32 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -extern UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32); - -//***************************************************************************** -// -//! UINT16_TO_STREAM_f -//! -//! \param p pointer to the new stream -//! \param u32 pointer to the 16 bit -//! -//! \return pointer to the new stream -//! -//! \brief This function is used for copying 16 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -extern UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16); - -//***************************************************************************** -// -//! STREAM_TO_UINT16_f -//! -//! \param p pointer to the stream -//! \param offset offset in the stream -//! -//! \return pointer to the new 16 bit -//! -//! \brief This function is used for copying received stream to -//! 16 bit in little endian format. -// -//***************************************************************************** - -extern UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset); - -//***************************************************************************** -// -//! STREAM_TO_UINT32_f -//! -//! \param p pointer to the stream -//! \param offset offset in the stream -//! -//! \return pointer to the new 32 bit -//! -//! \brief This function is used for copying received stream to -//! 32 bit in little endian format. -// -//***************************************************************************** - -extern UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset); - - -//***************************************************************************** -// COMMON MACROs -//***************************************************************************** - - -//This macro is used for copying 8 bit to stream while converting to little endian format. -#define UINT8_TO_STREAM(_p, _val) {*(_p)++ = (_val);} -//This macro is used for copying 16 bit to stream while converting to little endian format. -#define UINT16_TO_STREAM(_p, _u16) (UINT16_TO_STREAM_f(_p, _u16)) -//This macro is used for copying 32 bit to stream while converting to little endian format. -#define UINT32_TO_STREAM(_p, _u32) (UINT32_TO_STREAM_f(_p, _u32)) -//This macro is used for copying a specified value length bits (l) to stream while converting to little endian format. -#define ARRAY_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(p)++ = ((UINT8 *) a)[_i];} -//This macro is used for copying received stream to 8 bit in little endian format. -#define STREAM_TO_UINT8(_p, _offset, _u8) {_u8 = (UINT8)(*(_p + _offset));} -//This macro is used for copying received stream to 16 bit in little endian format. -#define STREAM_TO_UINT16(_p, _offset, _u16) {_u16 = STREAM_TO_UINT16_f(_p, _offset);} -//This macro is used for copying received stream to 32 bit in little endian format. -#define STREAM_TO_UINT32(_p, _offset, _u32) {_u32 = STREAM_TO_UINT32_f(_p, _offset);} -#define STREAM_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(a)++= ((UINT8 *) p)[_i];} - - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_COMMON_H__ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/ccspi.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/ccspi.h deleted file mode 100644 index 8fa3ecd1..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/ccspi.h +++ /dev/null @@ -1,84 +0,0 @@ -/***************************************************************************** -* -* spi.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - - -#ifndef __CC3000_SPI_H__ -#define __CC3000_SPI_H__ - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*gcSpiHandleRx)(void *p); -typedef void (*gcSpiHandleTx)(void); -extern unsigned char wlan_tx_buffer[]; - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* -extern void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq); - -extern void SpiOpen(gcSpiHandleRx pfRxHandler); -extern void SpiClose(void); -extern void SpiPauseSpi(void); -extern void SpiResumeSpi(void); -extern long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength); -extern void SpiConfigureHwMapping(void); -extern void SpiCleanGPIOISR(void); -extern void SSIConfigure(unsigned long ulSSIFreq, unsigned long bForceGpioConfiguration, unsigned long uiReconfigureSysClock); -extern int init_spi(void); -extern long ReadWlanInterruptPin(void); -extern void WriteWlanPin(unsigned char val); -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/data_types.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/data_types.h deleted file mode 100644 index 0520a920..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/data_types.h +++ /dev/null @@ -1,107 +0,0 @@ -/***************************************************************************** -* -* data_types.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_DATA_TYPES__ -#define __CC3000_DATA_TYPES__ - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef NULL -#define NULL (0) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#ifndef OK -#define OK (0) -#endif - -#ifndef _INT8 -#define _INT8 -typedef signed char INT8; -#endif - -#ifndef _UINT8 -#define _UINT8 -typedef unsigned char UINT8; -#endif - -#ifndef _INT16 -#define _INT16 -typedef signed short INT16; -#endif - -#ifndef _UINT16 -#define _UINT16 -typedef unsigned short UINT16; -#endif - -#ifndef _BOOLEAN -#define _BOOLEAN -typedef unsigned char BOOLEAN; -#endif - -#ifndef _INT32 -#define _INT32 -typedef signed long INT32; -#endif - -#ifndef _UINT32 -#define _UINT32 -typedef unsigned long UINT32; -#endif - -typedef int INT; -typedef char CHAR; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CC3000_DATA_TYPES__ */ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/evnt_handler.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/evnt_handler.h deleted file mode 100644 index d05a442f..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/evnt_handler.h +++ /dev/null @@ -1,166 +0,0 @@ -/***************************************************************************** -* -* evnt_handler.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_EVENT_HANDLER_H__ -#define __CC3000_EVENT_HANDLER_H__ -#include "hci.h" -#include "socket.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! hci_event_handler -//! -//! @param pRetParams incoming data buffer -//! @param from from information (in case of data received) -//! @param fromlen from information length (in case of data received) -//! -//! @return none -//! -//! @brief Parse the incoming events packets and issues corresponding -//! event handler from global array of handlers pointers -// -//***************************************************************************** -extern UINT8 *hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen); - -//***************************************************************************** -// -//! hci_unsol_event_handler -//! -//! @param event_hdr event header -//! -//! @return 1 if event supported and handled -//! 0 if event is not supported -//! -//! @brief Handle unsolicited events -// -//***************************************************************************** -extern INT32 hci_unsol_event_handler(CHAR *event_hdr); - -//***************************************************************************** -// -//! hci_unsolicited_event_handler -//! -//! @param None -//! -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Parse the incoming unsolicited event packets and issues -//! corresponding event handler. -// -//***************************************************************************** -extern INT32 hci_unsolicited_event_handler(void); - -#define M_BSD_RESP_PARAMS_OFFSET(hci_event_hdr)((CHAR *)(hci_event_hdr) + HCI_EVENT_HEADER_SIZE) - -#define SOCKET_STATUS_ACTIVE 0 -#define SOCKET_STATUS_INACTIVE 1 -/* Init socket_active_status = 'all ones': init all sockets with SOCKET_STATUS_INACTIVE. - Will be changed by 'set_socket_active_status' upon 'connect' and 'accept' calls */ -#define SOCKET_STATUS_INIT_VAL 0xFFFF -#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7)) -#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE)) - -extern UINT32 socket_active_status; - -extern void set_socket_active_status(INT32 Sd, INT32 Status); -extern INT32 get_socket_active_status(INT32 Sd); - -typedef struct _bsd_accept_return_t -{ - INT32 iSocketDescriptor; - INT32 iStatus; - sockaddr tSocketAddress; - -} tBsdReturnParams; - - -typedef struct _bsd_read_return_t -{ - INT32 iSocketDescriptor; - INT32 iNumberOfBytes; - UINT32 uiFlags; -} tBsdReadReturnParams; - -#define BSD_RECV_FROM_FROMLEN_OFFSET (4) -#define BSD_RECV_FROM_FROM_OFFSET (16) - - -typedef struct _bsd_select_return_t -{ - INT32 iStatus; - UINT32 uiRdfd; - UINT32 uiWrfd; - UINT32 uiExfd; -} tBsdSelectRecvParams; - - -typedef struct _bsd_getsockopt_return_t -{ - UINT8 ucOptValue[4]; - CHAR iStatus; -} tBsdGetSockOptReturnParams; - -typedef struct _bsd_gethostbyname_return_t -{ - INT32 retVal; - INT32 outputAddress; -} tBsdGethostbynameParams; - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_EVENT_HANDLER_H__ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/hci.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/hci.h deleted file mode 100644 index f12b00e9..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/hci.h +++ /dev/null @@ -1,330 +0,0 @@ -/***************************************************************************** -* -* hci.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_HCI_H__ -#define __CC3000_HCI_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#define SPI_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_CMND_HEADER_SIZE (4) -#define HEADERS_SIZE_CMD (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) -#define SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_DATA_HEADER_SIZE (5) -#define SIMPLE_LINK_HCI_PATCH_HEADER_SIZE (2) - - -//***************************************************************************** -// -// Values that can be used as HCI Commands and HCI Packet header defines -// -//***************************************************************************** -#define HCI_TYPE_CMND 0x1 -#define HCI_TYPE_DATA 0x2 -#define HCI_TYPE_PATCH 0x3 -#define HCI_TYPE_EVNT 0x4 - - -#define HCI_EVENT_PATCHES_DRV_REQ (1) -#define HCI_EVENT_PATCHES_FW_REQ (2) -#define HCI_EVENT_PATCHES_BOOTLOAD_REQ (3) - - -#define HCI_CMND_WLAN_BASE (0x0000) -#define HCI_CMND_WLAN_CONNECT 0x0001 -#define HCI_CMND_WLAN_DISCONNECT 0x0002 -#define HCI_CMND_WLAN_IOCTL_SET_SCANPARAM 0x0003 -#define HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY 0x0004 -#define HCI_CMND_WLAN_IOCTL_ADD_PROFILE 0x0005 -#define HCI_CMND_WLAN_IOCTL_DEL_PROFILE 0x0006 -#define HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS 0x0007 -#define HCI_CMND_EVENT_MASK 0x0008 -#define HCI_CMND_WLAN_IOCTL_STATUSGET 0x0009 -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START 0x000A -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP 0x000B -#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX 0x000C -#define HCI_CMND_WLAN_CONFIGURE_PATCH 0x000D - - -#define HCI_CMND_SOCKET_BASE 0x1000 -#define HCI_CMND_SOCKET 0x1001 -#define HCI_CMND_BIND 0x1002 -#define HCI_CMND_RECV 0x1004 -#define HCI_CMND_ACCEPT 0x1005 -#define HCI_CMND_LISTEN 0x1006 -#define HCI_CMND_CONNECT 0x1007 -#define HCI_CMND_BSD_SELECT 0x1008 -#define HCI_CMND_SETSOCKOPT 0x1009 -#define HCI_CMND_GETSOCKOPT 0x100A -#define HCI_CMND_CLOSE_SOCKET 0x100B -#define HCI_CMND_RECVFROM 0x100D -#define HCI_CMND_GETHOSTNAME 0x1010 -#define HCI_CMND_MDNS_ADVERTISE 0x1011 -#define HCI_CMND_GETMSSVALUE 0x1012 - - -#define HCI_DATA_BASE 0x80 - -#define HCI_CMND_SEND (0x01 + HCI_DATA_BASE) -#define HCI_CMND_SENDTO (0x03 + HCI_DATA_BASE) -#define HCI_DATA_BSD_RECVFROM (0x04 + HCI_DATA_BASE) -#define HCI_DATA_BSD_RECV (0x05 + HCI_DATA_BASE) - - -#define HCI_CMND_NVMEM_CBASE (0x0200) - - -#define HCI_CMND_NVMEM_CREATE_ENTRY (0x0203) -#define HCI_CMND_NVMEM_SWAP_ENTRY (0x0205) -#define HCI_CMND_NVMEM_READ (0x0201) -#define HCI_CMND_NVMEM_WRITE (0x0090) -#define HCI_CMND_NVMEM_WRITE_PATCH (0x0204) -#define HCI_CMND_READ_SP_VERSION (0x0207) - -#define HCI_CMND_READ_BUFFER_SIZE 0x400B -#define HCI_CMND_SIMPLE_LINK_START 0x4000 - -#define HCI_CMND_NETAPP_BASE 0x2000 - -#define HCI_NETAPP_DHCP (0x0001 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_SEND (0x0002 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_REPORT (0x0003 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_PING_STOP (0x0004 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_IPCONFIG (0x0005 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_ARP_FLUSH (0x0006 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_SET_DEBUG_LEVEL (0x0008 + HCI_CMND_NETAPP_BASE) -#define HCI_NETAPP_SET_TIMERS (0x0009 + HCI_CMND_NETAPP_BASE) - - - - - - -//***************************************************************************** -// -// Values that can be used as HCI Events defines -// -//***************************************************************************** -#define HCI_EVNT_WLAN_BASE 0x0000 -#define HCI_EVNT_WLAN_CONNECT 0x0001 -#define HCI_EVNT_WLAN_DISCONNECT \ - 0x0002 -#define HCI_EVNT_WLAN_IOCTL_ADD_PROFILE \ - 0x0005 - - -#define HCI_EVNT_SOCKET HCI_CMND_SOCKET -#define HCI_EVNT_BIND HCI_CMND_BIND -#define HCI_EVNT_RECV HCI_CMND_RECV -#define HCI_EVNT_ACCEPT HCI_CMND_ACCEPT -#define HCI_EVNT_LISTEN HCI_CMND_LISTEN -#define HCI_EVNT_CONNECT HCI_CMND_CONNECT -#define HCI_EVNT_SELECT HCI_CMND_BSD_SELECT -#define HCI_EVNT_CLOSE_SOCKET HCI_CMND_CLOSE_SOCKET -#define HCI_EVNT_RECVFROM HCI_CMND_RECVFROM -#define HCI_EVNT_SETSOCKOPT HCI_CMND_SETSOCKOPT -#define HCI_EVNT_GETSOCKOPT HCI_CMND_GETSOCKOPT -#define HCI_EVNT_BSD_GETHOSTBYNAME HCI_CMND_GETHOSTNAME -#define HCI_EVNT_MDNS_ADVERTISE HCI_CMND_MDNS_ADVERTISE -#define HCI_EVNT_GETMSSVALUE HCI_CMND_GETMSSVALUE - -#define HCI_EVNT_SEND 0x1003 -#define HCI_EVNT_WRITE 0x100E -#define HCI_EVNT_SENDTO 0x100F - -#define HCI_EVNT_PATCHES_REQ 0x1000 - -#define HCI_EVNT_UNSOL_BASE 0x4000 - -#define HCI_EVNT_WLAN_UNSOL_BASE (0x8000) - -#define HCI_EVNT_WLAN_UNSOL_CONNECT (0x0001 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_DISCONNECT (0x0002 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_INIT (0x0004 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_TX_COMPLETE (0x0008 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_UNSOL_DHCP (0x0010 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_ASYNC_PING_REPORT (0x0040 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE (0x0080 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_WLAN_KEEPALIVE (0x0200 + HCI_EVNT_WLAN_UNSOL_BASE) -#define HCI_EVNT_BSD_TCP_CLOSE_WAIT (0x0800 + HCI_EVNT_WLAN_UNSOL_BASE) - -#define HCI_EVNT_DATA_UNSOL_FREE_BUFF \ - 0x4100 - -#define HCI_EVNT_NVMEM_CREATE_ENTRY \ - HCI_CMND_NVMEM_CREATE_ENTRY -#define HCI_EVNT_NVMEM_SWAP_ENTRY HCI_CMND_NVMEM_SWAP_ENTRY - -#define HCI_EVNT_NVMEM_READ HCI_CMND_NVMEM_READ -#define HCI_EVNT_NVMEM_WRITE (0x0202) - -#define HCI_EVNT_READ_SP_VERSION \ - HCI_CMND_READ_SP_VERSION - -#define HCI_EVNT_INPROGRESS 0xFFFF - - -#define HCI_DATA_RECVFROM 0x84 -#define HCI_DATA_RECV 0x85 -#define HCI_DATA_NVMEM 0x91 - -#define HCI_EVENT_CC3000_CAN_SHUT_DOWN 0x99 - -//***************************************************************************** -// -// Prototypes for the structures for APIs. -// -//***************************************************************************** - -#define HCI_DATA_HEADER_SIZE (5) -#define HCI_EVENT_HEADER_SIZE (5) -#define HCI_DATA_CMD_HEADER_SIZE (5) -#define HCI_PATCH_HEADER_SIZE (6) - -#define HCI_PACKET_TYPE_OFFSET (0) -#define HCI_PACKET_ARGSIZE_OFFSET (2) -#define HCI_PACKET_LENGTH_OFFSET (3) - - -#define HCI_EVENT_OPCODE_OFFSET (1) -#define HCI_EVENT_LENGTH_OFFSET (3) -#define HCI_EVENT_STATUS_OFFSET (4) -#define HCI_DATA_LENGTH_OFFSET (3) - - - - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! hci_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param ucArgsLength length of the arguments -//! -//! @return none -//! -//! @brief Initiate an HCI command. -// -//***************************************************************************** -extern UINT16 hci_command_send(UINT16 usOpcode, - UINT8 *ucArgs, - UINT8 ucArgsLength); - - -//***************************************************************************** -// -//! hci_data_send -//! -//! @param usOpcode command operation code -//! @param ucArgs pointer to the command's arguments buffer -//! @param usArgsLength length of the arguments -//! @param ucTail pointer to the data buffer -//! @param usTailLength buffer length -//! -//! @return none -//! -//! @brief Initiate an HCI data write operation -// -//***************************************************************************** -extern INT32 hci_data_send(UINT8 ucOpcode, - UINT8 *ucArgs, - UINT16 usArgsLength, - UINT16 usDataLength, - const UINT8 *ucTail, - UINT16 usTailLength); - - -//***************************************************************************** -// -//! hci_data_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the data buffer -//! @param ucArgsLength arguments length -//! @param ucDataLength data length -//! -//! @return none -//! -//! @brief Prepare HCI header and initiate an HCI data write operation -// -//***************************************************************************** -extern void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, - UINT8 ucArgsLength, UINT16 ucDataLength); - -//***************************************************************************** -// -//! hci_patch_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param patch pointer to patch content buffer -//! @param usDataLength data length -//! -//! @return none -//! -//! @brief Prepare HCI header and initiate an HCI patch write operation -// -//***************************************************************************** -extern void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength); - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_HCI_H__ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/host_driver_version.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/host_driver_version.h deleted file mode 100644 index a28d21f1..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/host_driver_version.h +++ /dev/null @@ -1,40 +0,0 @@ -/***************************************************************************** -* -* host_driver_version.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_HOST_DRIVER_VERSION_H__ -#define __CC3000_HOST_DRIVER_VERSION_H__ - -#define DRIVER_VERSION_NUMBER 15 - -#endif // __CC3000_HOST_DRIVER_VERSION_H__ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/inet_ntop.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/inet_ntop.h deleted file mode 100644 index fa708062..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/inet_ntop.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __INET_NTOP_H -#define __INET_NTOP_H -char *inet_ntop(int af, const void *addr, char *buf, size_t size); -#endif /* __INET_NTOP_H */ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/inet_pton.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/inet_pton.h deleted file mode 100644 index 0896d5d2..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/inet_pton.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __INET_PTON_H -#define __INET_PTON_H -int inet_pton(int, const char *, void *); -#endif /* __INET_PTON_H */ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/netapp.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/netapp.h deleted file mode 100644 index 1e4f2658..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/netapp.h +++ /dev/null @@ -1,343 +0,0 @@ -/***************************************************************************** -* -* netapp.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_NETAPP_H__ -#define __CC3000_NETAPP_H__ - -#include "data_types.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -//***************************************************************************** -// -//! \addtogroup netapp_api -//! @{ -// -//***************************************************************************** - -typedef struct _netapp_dhcp_ret_args_t -{ - UINT8 aucIP[4]; - UINT8 aucSubnetMask[4]; - UINT8 aucDefaultGateway[4]; - UINT8 aucDHCPServer[4]; - UINT8 aucDNSServer[4]; -}tNetappDhcpParams; - -typedef struct _netapp_ipconfig_ret_args_t -{ - UINT8 aucIP[4]; - UINT8 aucSubnetMask[4]; - UINT8 aucDefaultGateway[4]; - UINT8 aucDHCPServer[4]; - UINT8 aucDNSServer[4]; - UINT8 uaMacAddr[6]; - UINT8 uaSSID[32]; -}tNetappIpconfigRetArgs; - - -/*Ping send report parameters*/ -typedef struct _netapp_pingreport_args -{ - UINT32 packets_sent; - UINT32 packets_received; - UINT32 min_round_time; - UINT32 max_round_time; - UINT32 avg_round_time; -} netapp_pingreport_args_t; - - -//***************************************************************************** -// -//! netapp_config_mac_adrress -//! -//! @param mac device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Configure device MAC address and store it in NVMEM. -//! The value of the MAC address configured through the API will -//! be stored in CC3000 non volatile memory, thus preserved -//! over resets. -// -//***************************************************************************** -extern INT32 netapp_config_mac_adrress( UINT8 *mac ); - -//***************************************************************************** -// -//! netapp_dhcp -//! -//! @param aucIP device mac address, 6 bytes. Saved: yes -//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes -//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes -//! @param aucDNSServer device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief netapp_dhcp is used to configure the network interface, -//! static or dynamic (DHCP).\n In order to activate DHCP mode, -//! aucIP, aucSubnetMask, aucDefaultGateway must be 0. -//! The default mode of CC3000 is DHCP mode. -//! Note that the configuration is saved in non volatile memory -//! and thus preserved over resets. -//! -//! @note If the mode is altered a reset of CC3000 device is required -//! in order to apply changes.\nAlso note that asynchronous event -//! of DHCP_EVENT, which is generated when an IP address is -//! allocated either by the DHCP server or due to static -//! allocation is generated only upon a connection to the -//! AP was established. -//! -//***************************************************************************** -extern INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer); - - - -//***************************************************************************** -// -//! netapp_timeout_values -//! -//! @param aucDHCP DHCP lease time request, also impact -//! the DHCP renew timeout. Range: [0-0xffffffff] seconds, -//! 0 or 0xffffffff == infinity lease timeout. -//! Resolution:10 seconds. Influence: only after -//! reconnecting to the AP. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 14400 seconds. -//! -//! @param aucARP ARP refresh timeout, if ARP entry is not updated by -//! incoming packet, the ARP entry will be deleted by -//! the end of the timeout. -//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 3600 seconds. -//! -//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout -//! Range: [0-0xffffffff] seconds, 0 == infinity timeout -//! Resolution: 10 seconds. -//! Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 10 seconds. -//! -//! @param aucInactivity Socket inactivity timeout, socket timeout is -//! refreshed by incoming or outgoing packet, by the -//! end of the socket timeout the socket will be closed -//! Range: [0-0xffffffff] sec, 0 == infinity timeout. -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 60 seconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Set new timeout values. Function set new timeout values for: -//! DHCP lease timeout, ARP refresh timeout, keepalive event -//! timeout and socket inactivity timeout -//! -//! @note If a parameter set to non zero value which is less than 10s, -//! it will be set automatically to 10s. -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP, UINT32 *aucKeepalive, UINT32 *aucInactivity); -#endif - -//***************************************************************************** -// -//! netapp_ping_send -//! -//! @param ip destination IP address -//! @param pingAttempts number of echo requests to send -//! @param pingSize send buffer size which may be up to 1400 bytes -//! @param pingTimeout Time to wait for a response,in milliseconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief send ICMP ECHO_REQUEST to network hosts -//! -//! @note If an operation finished successfully asynchronous ping report -//! event will be generated. The report structure is as defined -//! by structure netapp_pingreport_args_t. -//! -//! @warning Calling this function while a previous Ping Requests are in -//! progress will stop the previous ping request. -//***************************************************************************** - - #ifndef CC3000_TINY_DRIVER -extern INT32 netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout); -#endif - -//***************************************************************************** -// -//! netapp_ping_stop -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief Stop any ping request. -//! -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_ping_stop(); -#endif -//***************************************************************************** -// -//! netapp_ping_report -//! -//! @param none -//! -//! @return none -//! -//! @brief Request for ping status. This API triggers the CC3000 to send -//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. -//! This event will carry the report structure: -//! netapp_pingreport_args_t. This structure is filled in with ping -//! results up till point of triggering API. -//! netapp_pingreport_args_t:\n packets_sent - echo sent, -//! packets_received - echo reply, min_round_time - minimum -//! round time, max_round_time - max round time, -//! avg_round_time - average round time -//! -//! @note When a ping operation is not active, the returned structure -//! fields are 0. -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern void netapp_ping_report(); -#endif - - -//***************************************************************************** -// -//! netapp_ipconfig -//! -//! @param[out] ipconfig This argument is a pointer to a -//! tNetappIpconfigRetArgs structure. This structure is -//! filled in with the network interface configuration. -//! tNetappIpconfigRetArgs:\n aucIP - ip address, -//! aucSubnetMask - mask, aucDefaultGateway - default -//! gateway address, aucDHCPServer - dhcp server address -//! aucDNSServer - dns server address, uaMacAddr - mac -//! address, uaSSID - connected AP ssid -//! -//! @return none -//! -//! @brief Obtain the CC3000 Network interface information. -//! Note that the information is available only after the WLAN -//! connection was established. Calling this function before -//! associated, will cause non-defined values to be returned. -//! -//! @note The function is useful for figuring out the IP Configuration of -//! the device when DHCP is used and for figuring out the SSID of -//! the Wireless network the device is associated with. -//! -//***************************************************************************** - -extern void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ); - - -//***************************************************************************** -// -//! netapp_arp_flush -//! -//! @param none -//! -//! @return none -//! -//! @brief Flushes ARP table -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -extern INT32 netapp_arp_flush(); -#endif - - -//***************************************************************************** -// -//! netapp_set_debug_level -//! -//! @param[in] level debug level. Bitwise [0-8], -//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical -//! message, 1 information message, 2 - core messages, 3 - -//! HCI messages, 4 - Network stack messages, 5 - wlan -//! messages, 6 - wlan driver messages, 7 - epprom messages, -//! 8 - general messages. Default: 0x13f. Saved: no -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Debug messages sent via the UART debug channel, this function -//! enable/disable the debug level -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_set_debug_level(UINT32 ulLevel); -#endif -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_NETAPP_H__ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/nvmem.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/nvmem.h deleted file mode 100644 index b99a2e7b..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/nvmem.h +++ /dev/null @@ -1,248 +0,0 @@ -/***************************************************************************** -* -* nvmem.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_NVRAM_H__ -#define __CC3000_NVRAM_H__ - -#include "cc3000_common.h" - - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -//***************************************************************************** -// -//! \addtogroup nvmem_api -//! @{ -// -//***************************************************************************** - -/**************************************************************************** -** -** Definitions for File IDs -** -****************************************************************************/ -/* NVMEM file ID - system files*/ -#define NVMEM_NVS_FILEID (0) -#define NVMEM_NVS_SHADOW_FILEID (1) -#define NVMEM_WLAN_CONFIG_FILEID (2) -#define NVMEM_WLAN_CONFIG_SHADOW_FILEID (3) -#define NVMEM_WLAN_DRIVER_SP_FILEID (4) -#define NVMEM_WLAN_FW_SP_FILEID (5) -#define NVMEM_MAC_FILEID (6) -#define NVMEM_FRONTEND_VARS_FILEID (7) -#define NVMEM_IP_CONFIG_FILEID (8) -#define NVMEM_IP_CONFIG_SHADOW_FILEID (9) -#define NVMEM_BOOTLOADER_SP_FILEID (10) -#define NVMEM_RM_FILEID (11) - -/* NVMEM file ID - user files*/ -#define NVMEM_AES128_KEY_FILEID (12) -#define NVMEM_SHARED_MEM_FILEID (13) - -/* max entry in order to invalid nvmem */ -#define NVMEM_MAX_ENTRY (16) - - -//***************************************************************************** -// -//! nvmem_read -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, -//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, -//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, -//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to read -//! @param ulOffset ulOffset in file from where to read -//! @param buff output buffer pointer -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads data from the file referred by the ulFileId parameter. -//! Reads data from file ulOffset till length. Err if the file can't -//! be used, is invalid, or if the read is out of bounds. -//! -//***************************************************************************** - -extern INT32 nvmem_read(UINT32 file_id, UINT32 length, UINT32 offset, UINT8 *buff); - -//***************************************************************************** -// -//! nvmem_write -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to write -//! @param ulEntryOffset offset in file to start write operation from -//! @param buff data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write data to nvmem. -//! writes data to file referred by the ulFileId parameter. -//! Writes data to file ulOffset till ulLength.The file id will be -//! marked invalid till the write is done. The file entry doesn't -//! need to be valid - only allocated. -//! -//***************************************************************************** - -extern INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff); - - -//***************************************************************************** -// -//! nvmem_set_mac_address -//! -//! @param mac mac address to be set -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write MAC address to EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** -extern UINT8 nvmem_set_mac_address(UINT8 *mac); - - -//***************************************************************************** -// -//! nvmem_get_mac_address -//! -//! @param[out] mac mac address -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read MAC address from EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** -extern UINT8 nvmem_get_mac_address(UINT8 *mac); - - -//***************************************************************************** -// -//! nvmem_write_patch -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! @param spLength number of bytes to write -//! @param spData SP data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief program a patch to a specific file ID. -//! The SP data is assumed to be organized in 2-dimensional. -//! Each line is SP_PORTION_SIZE bytes long. Actual programming is -//! applied in SP_PORTION_SIZE bytes portions. -//! -//***************************************************************************** -extern UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData); - - -//***************************************************************************** -// -//! nvmem_read_sp_version -//! -//! @param[out] patchVer first number indicates package ID and the second -//! number indicates package build number -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read patch version. read package version (WiFi FW patch, -//! driver-supplicant-NS patch, bootloader patch) -//! -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern UINT8 nvmem_read_sp_version(UINT8* patchVer); -#endif - -//***************************************************************************** -// -//! nvmem_create_entry -//! -//! @param ulFileId nvmem file Id:\n -//! * NVMEM_AES128_KEY_FILEID: 12 -//! * NVMEM_SHARED_MEM_FILEID: 13 -//! * and fileIDs 14 and 15 -//! @param ulNewLen entry ulLength -//! -//! @return on success 0, error otherwise. -//! -//! @brief Create new file entry and allocate space on the NVMEM. -//! Applies only to user files. -//! Modify the size of file. -//! If the entry is unallocated - allocate it to size -//! ulNewLen (marked invalid). -//! If it is allocated then deallocate it first. -//! To just mark the file as invalid without resizing - -//! set ulNewLen=0. -//! -//***************************************************************************** -extern INT32 nvmem_create_entry(UINT32 file_id, UINT32 newlen); - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_NVRAM_H__ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/patch_prog.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/patch_prog.h deleted file mode 100644 index 0a141a0c..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/patch_prog.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __CC3000_PATCH_PROG_H__ -#define __CC3000_PATCH_PROG_H__ -extern unsigned short fw_length; -extern const unsigned char fw_patch[]; - -extern unsigned short drv_length; -extern const unsigned char wlan_drv_patch[]; -extern const unsigned char cRMdefaultParams[128]; - -void patch_prog_start(); -#endif //__CC3000_PATCH_PROG_H__ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/security.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/security.h deleted file mode 100644 index cd1baf55..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/security.h +++ /dev/null @@ -1,130 +0,0 @@ -/***************************************************************************** -* -* security.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_SECURITY__ -#define __CC3000_SECURITY__ - -#include "nvmem.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - - -#define AES128_KEY_SIZE 16 - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG - - -//***************************************************************************** -// -//! aes_encrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief AES128 encryption: -//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes -//! is computed. The AES implementation is in mode ECB (Electronic -//! Code Book). -//! -//! -//***************************************************************************** -extern void aes_encrypt(UINT8 *state, UINT8 *key); - -//***************************************************************************** -// -//! aes_decrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief AES128 decryption: -//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes -//! is computed The AES implementation is in mode ECB -//! (Electronic Code Book). -//! -//! -//***************************************************************************** -extern void aes_decrypt(UINT8 *state, UINT8 *key); - - -//***************************************************************************** -// -//! aes_read_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads AES128 key from EEPROM -//! Reads the AES128 key from fileID #12 in EEPROM -//! returns an error if the key does not exist. -//! -//! -//***************************************************************************** -extern INT32 aes_read_key(UINT8 *key); - -//***************************************************************************** -// -//! aes_write_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief writes AES128 key from EEPROM -//! Writes the AES128 key to fileID #12 in EEPROM -//! -//! -//***************************************************************************** -extern INT32 aes_write_key(UINT8 *key); - -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/socket.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/socket.h deleted file mode 100644 index 96c814bf..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/socket.h +++ /dev/null @@ -1,676 +0,0 @@ -/***************************************************************************** -* -* socket.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_SOCKET_H__ -#define __CC3000_SOCKET_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -//! \addtogroup socket_api -//! @{ -// -//***************************************************************************** - - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -#define HOSTNAME_MAX_LENGTH (230) // 230 bytes + header shouldn't exceed 8 bit value - -//--------- Address Families -------- - -#define AF_INET 2 -#define AF_INET6 23 - -//------------ Socket Types ------------ - -#define SOCK_STREAM 1 -#define SOCK_DGRAM 2 -#define SOCK_RAW 3 // Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers -#define SOCK_RDM 4 -#define SOCK_SEQPACKET 5 - -//----------- Socket Protocol ---------- - -#define IPPROTO_IP 0 // dummy for IP -#define IPPROTO_ICMP 1 // control message protocol -#define IPPROTO_IPV4 IPPROTO_IP // IP inside IP -#define IPPROTO_TCP 6 // tcp -#define IPPROTO_UDP 17 // user datagram protocol -#define IPPROTO_IPV6 41 // IPv6 in IPv6 -#define IPPROTO_NONE 59 // No next header -#define IPPROTO_RAW 255 // raw IP packet -#define IPPROTO_MAX 256 - -//----------- Socket retunr codes ----------- - -#define SOC_ERROR (-1) // error -#define SOC_IN_PROGRESS (-2) // socket in progress - -//----------- Socket Options ----------- -#define SOL_SOCKET 0xffff // socket level -#define SOCKOPT_RECV_NONBLOCK 0 // recv non block mode, set SOCK_ON or SOCK_OFF (default block mode) -#define SOCKOPT_RECV_TIMEOUT 1 // optname to configure recv and recvfromtimeout -#define SOCKOPT_ACCEPT_NONBLOCK 2 // accept non block mode, set SOCK_ON or SOCK_OFF (default block mode) -#define SOCK_ON 0 // socket non-blocking mode is enabled -#define SOCK_OFF 1 // socket blocking mode is enabled - -#define MAX_PACKET_SIZE 1500 -#define MAX_LISTEN_QUEUE 4 - -#define IOCTL_SOCKET_EVENTMASK - -#define ENOBUFS 55 // No buffer space available - -#define __FD_SETSIZE 32 - -#define ASIC_ADDR_LEN 8 - -#define NO_QUERY_RECIVED -3 - - -typedef struct _in_addr_t -{ - UINT32 s_addr; // load with inet_aton() -} in_addr; - -typedef struct _sockaddr_t -{ - UINT16 sa_family; - UINT8 sa_data[14]; -} sockaddr; - -typedef struct _sockaddr_in_t -{ - INT16 sin_family; // e.g. AF_INET - UINT16 sin_port; // e.g. htons(3490) - in_addr sin_addr; // see struct in_addr, below - CHAR sin_zero[8]; // zero this if you want to -} sockaddr_in; - -typedef UINT32 socklen_t; - -// The fd_set member is required to be an array of INT32s. -typedef INT32 __fd_mask; - -// It's easier to assume 8-bit bytes than to get CHAR_BIT. -#define __NFDBITS (8 * sizeof (__fd_mask)) -#define __FDELT(d) ((d) / __NFDBITS) -#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) - -// fd_set for select and pselect. -typedef struct -{ - __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; -#define __FDS_BITS(set) ((set)->fds_bits) -} fd_set; - -// We don't use `memset' because this would require a prototype and -// the array isn't too big. -#define __FD_ZERO(set) \ - do { \ - UINT16 __i; \ - fd_set *__arr = (set); \ - for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ - __FDS_BITS (__arr)[__i] = 0; \ - } while (0) -#define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d)) -#define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d)) -#define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d)) - -// Access macros for 'fd_set'. -#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) -#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) -#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) -#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp) - -//Use in case of Big Endian only - -#define htonl(A) ((((UINT32)(A) & 0xff000000) >> 24) | \ - (((UINT32)(A) & 0x00ff0000) >> 8) | \ - (((UINT32)(A) & 0x0000ff00) << 8) | \ - (((UINT32)(A) & 0x000000ff) << 24)) - -#define ntohl htonl - -//Use in case of Big Endian only -#define htons(A) ((((UINT32)(A) & 0xff00) >> 8) | \ - (((UINT32)(A) & 0x00ff) << 8)) - - -#define ntohs htons - -// mDNS port - 5353 mDNS multicast address - 224.0.0.251 -#define SET_mDNS_ADD(sockaddr) sockaddr.sa_data[0] = 0x14; \ - sockaddr.sa_data[1] = 0xe9; \ - sockaddr.sa_data[2] = 0xe0; \ - sockaddr.sa_data[3] = 0x0; \ - sockaddr.sa_data[4] = 0x0; \ - sockaddr.sa_data[5] = 0xfb; - - -//***************************************************************************** -// -// Prototypes for the APIs. -// -//***************************************************************************** - -//***************************************************************************** -// -//! socket -//! -//! @param domain selects the protocol family which will be used for -//! communication. On this version only AF_INET is supported -//! @param type specifies the communication semantics. On this version -//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported -//! @param protocol specifies a particular protocol to be used with the -//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are -//! supported. -//! -//! @return On success, socket handle that is used for consequent socket -//! operations. On error, -1 is returned. -//! -//! @brief create an endpoint for communication -//! The socket function creates a socket that is bound to a specific -//! transport service provider. This function is called by the -//! application layer to obtain a socket handle. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol); - -//***************************************************************************** -// -//! closesocket -//! -//! @param sd socket handle. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief The socket function closes a created socket. -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(closesocket)(INT32 sd); - -//***************************************************************************** -// -//! accept -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr the argument addr is a pointer to a sockaddr structure -//! This structure is filled in with the address of the -//! peer socket, as known to the communications layer. -//! determined. The exact format of the address returned -//! addr is by the socket's address sockaddr. -//! On this version only AF_INET is supported. -//! This argument returns in network order. -//! @param[out] addrlen the addrlen argument is a value-result argument: -//! it should initially contain the size of the structure -//! pointed to by addr. -//! -//! @return For socket in blocking mode: -//! On success, socket handle. on failure negative -//! For socket in non-blocking mode: -//! - On connection establishment, socket handle -//! - On connection pending, SOC_IN_PROGRESS (-2) -//! - On failure, SOC_ERROR (-1) -//! -//! @brief accept a connection on a socket: -//! This function is used with connection-based socket types -//! (SOCK_STREAM). It extracts the first connection request on the -//! queue of pending connections, creates a new connected socket, and -//! returns a new file descriptor referring to that socket. -//! The newly created socket is not in the listening state. -//! The original socket sd is unaffected by this call. -//! The argument sd is a socket that has been created with socket(), -//! bound to a local address with bind(), and is listening for -//! connections after a listen(). The argument addr is a pointer -//! to a sockaddr structure. This structure is filled in with the -//! address of the peer socket, as known to the communications layer. -//! The exact format of the address returned addr is determined by the -//! socket's address family. The addrlen argument is a value-result -//! argument: it should initially contain the size of the structure -//! pointed to by addr, on return it will contain the actual -//! length (in bytes) of the address returned. -//! -//! @sa socket ; bind ; listen -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen); - -//***************************************************************************** -// -//! bind -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr specifies the destination address. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief assign a name to a socket -//! This function gives the socket the local address addr. -//! addr is addrlen bytes long. Traditionally, this is called when a -//! socket is created with socket, it exists in a name space (address -//! family) but has no name assigned. -//! It is necessary to assign a local address before a SOCK_STREAM -//! socket may receive connections. -//! -//! @sa socket ; accept ; listen -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen); - -//***************************************************************************** -// -//! listen -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] backlog specifies the listen queue depth. On this version -//! backlog is not supported. -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief listen for connections on a socket -//! The willingness to accept incoming connections and a queue -//! limit for incoming connections are specified with listen(), -//! and then the connections are accepted with accept. -//! The listen() call applies only to sockets of type SOCK_STREAM -//! The backlog parameter defines the maximum length the queue of -//! pending connections may grow to. -//! -//! @sa socket ; accept ; bind -//! -//! @note On this version, backlog is not supported -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog); - -//***************************************************************************** -// -//! gethostbyname -//! -//! @param[in] hostname host name -//! @param[in] usNameLen name length -//! @param[out] out_ip_addr This parameter is filled in with host IP address. -//! In case that host name is not resolved, -//! out_ip_addr is zero. -//! @return On success, positive is returned. On error, negative is returned -//! -//! @brief Get host IP by name. Obtain the IP Address of machine on network, -//! by its name. -//! -//! @note On this version, only blocking mode is supported. Also note that -//! the function requires DNS server to be configured prior to its usage. -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, UINT32* out_ip_addr); -#endif - - -//***************************************************************************** -// -//! connect -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] addr specifies the destination addr. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief initiate a connection on a socket -//! Function connects the socket referred to by the socket descriptor -//! sd, to the address specified by addr. The addrlen argument -//! specifies the size of addr. The format of the address in addr is -//! determined by the address space of the socket. If it is of type -//! SOCK_DGRAM, this call specifies the peer with which the socket is -//! to be associated; this address is that to which datagrams are to be -//! sent, and the only address from which datagrams are to be received. -//! If the socket is of type SOCK_STREAM, this call attempts to make a -//! connection to another socket. The other socket is specified by -//! address, which is an address in the communications space of the -//! socket. Note that the function implements only blocking behavior -//! thus the caller will be waiting either for the connection -//! establishment or for the connection establishment failure. -//! -//! @sa socket -// -//***************************************************************************** -extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen); - -//***************************************************************************** -// -//! select -//! -//! @param[in] nfds the highest-numbered file descriptor in any of the -//! three sets, plus 1. -//! @param[out] writesds socket descriptors list for write monitoring -//! @param[out] readsds socket descriptors list for read monitoring -//! @param[out] exceptsds socket descriptors list for exception monitoring -//! @param[in] timeout is an upper bound on the amount of time elapsed -//! before select() returns. Null means infinity -//! timeout. The minimum timeout is 5 milliseconds, -//! less than 5 milliseconds will be set -//! automatically to 5 milliseconds. -//! @return On success, select() returns the number of file descriptors -//! contained in the three returned descriptor sets (that is, the -//! total number of bits that are set in readfds, writefds, -//! exceptfds) which may be zero if the timeout expires before -//! anything interesting happens. -//! On error, -1 is returned. -//! *readsds - return the sockets on which Read request will -//! return without delay with valid data. -//! *writesds - return the sockets on which Write request -//! will return without delay. -//! *exceptsds - return the sockets which closed recently. -//! -//! @brief Monitor socket activity -//! Select allow a program to monitor multiple file descriptors, -//! waiting until one or more of the file descriptors become -//! "ready" for some class of I/O operation -//! -//! @Note If the timeout value set to less than 5ms it will automatically set -//! to 5ms to prevent overload of the system -//! -//! @sa socket -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, - fd_set *exceptsds, struct cc3000_timeval *timeout); - -//***************************************************************************** -// -//! setsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[in] optval specifies a value for the option -//! @param[in] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa getsockopt -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, - socklen_t optlen); -#endif -//***************************************************************************** -// -//! getsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[out] optval specifies a value for the option -//! @param[out] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa setsockopt -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(getsockopt)(INT32 sd, INT32 level, INT32 optname, void *optval, - socklen_t *optlen); - -//***************************************************************************** -// -//! recv -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief function receives a message from a connection-mode socket -//! -//! @sa recvfrom -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags); - -//***************************************************************************** -// -//! recvfrom -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! @param[in] from pointer to an address structure indicating the source -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param[in] fromlen source address structure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief read data from socket -//! function receives a message from a connection-mode or -//! connectionless-mode socket. Note that raw sockets are not -//! supported. -//! -//! @sa recv -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen); - -//***************************************************************************** -// -//! send -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa sendto -// -//***************************************************************************** - -extern INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags); - -//***************************************************************************** -// -//! sendto -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating the destination -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa send -// -//***************************************************************************** - -extern INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, - const sockaddr *to, socklen_t tolen); - -//***************************************************************************** -// -//! mdnsAdvertiser -//! -//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature -//! @param[in] deviceServiceName Service name as part of the published -//! canonical domain name -//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars -//! -//! -//! @return On success, zero is returned, return SOC_ERROR if socket was not -//! opened successfully, or if an error occurred. -//! -//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. -// -//***************************************************************************** -extern INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength); - - -//***************************************************************************** -// -//! getmssvalue -//! -//! @param[in] sd socket descriptor -//! -//! @return On success, returns the MSS value of a TCP connection -//! -//! @brief Returns the MSS value of a TCP connection according to the socket descriptor -// -//***************************************************************************** -extern UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd); - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __SOCKET_H__ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/wlan.h b/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/wlan.h deleted file mode 100644 index 48d195b3..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/inc/wlan.h +++ /dev/null @@ -1,518 +0,0 @@ -/***************************************************************************** -* -* wlan.h - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -#ifndef __CC3000_WLAN_H__ -#define __CC3000_WLAN_H__ - -#include "cc3000_common.h" - -//***************************************************************************** -// -// If building with a C++ compiler, make all of the definitions in this header -// have a C binding. -// -//***************************************************************************** -#ifdef __cplusplus -extern "C" { -#endif - -#define WLAN_SEC_UNSEC (0) -#define WLAN_SEC_WEP (1) -#define WLAN_SEC_WPA (2) -#define WLAN_SEC_WPA2 (3) -//***************************************************************************** -// -//! \addtogroup wlan_api -//! @{ -// -//***************************************************************************** - - -//***************************************************************************** -// -//! wlan_init -//! -//! @param sWlanCB Asynchronous events callback. -//! 0 no event call back. -//! -call back parameters: -//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR -//! HCI_EVNT_WLAN_KEEPALIVE keepalive. -//! 2) data: pointer to extra data that received by the event -//! (NULL no data). -//! 3) length: data length. -//! -Events with extra data: -//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, -//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes -//! for DNS server. -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, -//! 4 bytes Packets received, 4 bytes Min round time, -//! 4 bytes Max round time and 4 bytes for Avg round time. -//! -//! @param sFWPatches 0 no patch or pointer to FW patches -//! @param sDriverPatches 0 no patch or pointer to driver patches -//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches -//! @param sReadWlanInterruptPin init callback. the callback read wlan -//! interrupt status. -//! @param sWlanInterruptEnable init callback. the callback enable wlan -//! interrupt. -//! @param sWlanInterruptDisable init callback. the callback disable wlan -//! interrupt. -//! @param sWriteWlanPin init callback. the callback write value -//! to device pin. -//! -//! @return none -//! -//! @sa wlan_set_event_mask , wlan_start , wlan_stop -//! -//! @brief Initialize wlan driver -//! -//! @warning This function must be called before ANY other wlan driver function -// -//***************************************************************************** -extern void wlan_init( tWlanCB sWlanCB, - tFWPatches sFWPatches, - tDriverPatches sDriverPatches, - tBootLoaderPatches sBootLoaderPatches, - tWlanReadInteruptPin sReadWlanInterruptPin, - tWlanInterruptEnable sWlanInterruptEnable, - tWlanInterruptDisable sWlanInterruptDisable, - tWriteWlanPin sWriteWlanPin); - - - -//***************************************************************************** -// -//! wlan_start -//! -//! @param usPatchesAvailableAtHost - flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Start WLAN device. This function asserts the enable pin of -//! the device (WLAN_EN), starting the HW initialization process. -//! The function blocked until device Initialization is completed. -//! Function also configure patches (FW, driver or bootloader) -//! and calls appropriate device callbacks. -//! -//! @Note Prior calling the function wlan_init shall be called. -//! @Warning This function must be called after wlan_init and before any -//! other wlan API -//! @sa wlan_init , wlan_stop -//! -// -//***************************************************************************** -extern int wlan_start(UINT16 usPatchesAvailableAtHost); - -//***************************************************************************** -// -//! wlan_stop -//! -//! @param none -//! -//! @return none -//! -//! @brief Stop WLAN device by putting it into reset state. -//! -//! @sa wlan_start -// -//***************************************************************************** -extern void wlan_stop(void); - -//***************************************************************************** -// -//! wlan_connect -//! -//! @param sec_type security options: -//! WLAN_SEC_UNSEC, -//! WLAN_SEC_WEP (ASCII support only), -//! WLAN_SEC_WPA or WLAN_SEC_WPA2 -//! @param ssid up to 32 bytes and is ASCII SSID of the AP -//! @param ssid_len length of the SSID -//! @param bssid 6 bytes specified the AP bssid -//! @param key up to 32 bytes specified the AP security key -//! @param key_len key length -//! -//! @return On success, zero is returned. On error, negative is returned. -//! Note that even though a zero is returned on success to trigger -//! connection operation, it does not mean that CCC3000 is already -//! connected. An asynchronous "Connected" event is generated when -//! actual association process finishes and CC3000 is connected to -//! the AP. If DHCP is set, An asynchronous "DHCP" event is -//! generated when DHCP process is finish. -//! -//! -//! @brief Connect to AP -//! @warning Please Note that when connection to AP configured with security -//! type WEP, please confirm that the key is set as ASCII and not -//! as HEX. -//! @sa wlan_disconnect -// -//***************************************************************************** -#ifndef CC3000_TINY_DRIVER -extern INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, - UINT8 *bssid, UINT8 *key, INT32 key_len); -#else -extern INT32 wlan_connect(CHAR *ssid, INT32 ssid_len); - -#endif - -//***************************************************************************** -// -//! wlan_disconnect -//! -//! @return 0 disconnected done, other CC3000 already disconnected -//! -//! @brief Disconnect connection from AP. -//! -//! @sa wlan_connect -// -//***************************************************************************** - -extern INT32 wlan_disconnect(void); - -//***************************************************************************** -// -//! wlan_add_profile -//! -//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 -//! @param ucSsid ssid SSID up to 32 bytes -//! @param ulSsidLen ssid length -//! @param ucBssid bssid 6 bytes -//! @param ulPriority ulPriority profile priority. Lowest priority:0. -//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security -//! @param ulGroupCipher_TxKeyIndex key index -//! @param ulKeyMgmt KEY management -//! @param ucPf_OrKey security key -//! @param ulPassPhraseLen security key length for WPA\WPA2 -//! -//! @return On success, index (1-7) of the stored profile is returned. -//! On error, -1 is returned. -//! -//! @brief When auto start is enabled, the device connects to -//! station from the profiles table. Up to 7 profiles are supported. -//! If several profiles configured the device choose the highest -//! priority profile, within each priority group, device will choose -//! profile based on security policy, signal strength, etc -//! parameters. All the profiles are stored in CC3000 NVMEM. -//! -//! @sa wlan_ioctl_del_profile -// -//***************************************************************************** - -extern INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_Key, - UINT32 ulGroupCipher_TxKeyLen, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen); - - - -//***************************************************************************** -// -//! wlan_ioctl_del_profile -//! -//! @param index number of profile to delete -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Delete WLAN profile -//! -//! @Note In order to delete all stored profile, set index to 255. -//! -//! @sa wlan_add_profile -// -//***************************************************************************** -extern INT32 wlan_ioctl_del_profile(UINT32 ulIndex); - -//***************************************************************************** -// -//! wlan_set_event_mask -//! -//! @param mask mask option: -//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done -//! HCI_EVNT_WLAN_UNSOL_INIT init done -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report -//! HCI_EVNT_WLAN_KEEPALIVE keepalive -//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission -//! Saved: no. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Mask event according to bit mask. In case that event is -//! masked (1), the device will not send the masked event to host. -// -//***************************************************************************** -extern INT32 wlan_set_event_mask(UINT32 ulMask); - -//***************************************************************************** -// -//! wlan_ioctl_statusget -//! -//! @param none -//! -//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, -//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED -//! -//! @brief get wlan status: disconnected, scanning, connecting or connected -// -//***************************************************************************** -extern INT32 wlan_ioctl_statusget(void); - - -//***************************************************************************** -// -//! wlan_ioctl_set_connection_policy -//! -//! @param should_connect_to_open_ap enable(1), disable(0) connect to any -//! available AP. This parameter corresponds to the configuration of -//! item # 3 in the brief description. -//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries -//! to connect to the last connected AP. This parameter corresponds -//! to the configuration of item # 1 in the brief description. -//! @param auto_start enable(1), disable(0) auto connect -//! after reset and periodically reconnect if needed. This -//! configuration configures option 2 in the above description. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief When auto is enabled, the device tries to connect according -//! the following policy: -//! 1) If fast connect is enabled and last connection is valid, -//! the device will try to connect to it without the scanning -//! procedure (fast). The last connection will be marked as -//! invalid, due to adding/removing profile. -//! 2) If profile exists, the device will try to connect it -//! (Up to seven profiles). -//! 3) If fast and profiles are not found, and open mode is -//! enabled, the device will try to connect to any AP. -//! * Note that the policy settings are stored in the CC3000 NVMEM. -//! -//! @sa wlan_add_profile , wlan_ioctl_del_profile -// -//***************************************************************************** -extern INT32 wlan_ioctl_set_connection_policy( - UINT32 should_connect_to_open_ap, - UINT32 should_use_fast_connect, - UINT32 ulUseProfiles); - -//***************************************************************************** -// -//! wlan_ioctl_get_scan_results -//! -//! @param[in] scan_timeout parameter not supported -//! @param[out] ucResults scan result (_wlan_full_scan_results_args_t) -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Gets entry from scan result table. -//! The scan results are returned one by one, and each entry -//! represents a single AP found in the area. The following is a -//! format of the scan result: -//! - 4 Bytes: number of networks found -//! - 4 Bytes: The status of the scan: 0 - aged results, -//! 1 - results valid, 2 - no results -//! - 42 bytes: Result entry, where the bytes are arranged as follows: -//! -//! - 1 bit isValid - is result valid or not -//! - 7 bits rssi - RSSI value; -//! - 2 bits: securityMode - security mode of the AP: -//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 -//! - 6 bits: SSID name length -//! - 2 bytes: the time at which the entry has entered into -//! scans result table -//! - 32 bytes: SSID name -//! - 6 bytes: BSSID -//! -//! @Note scan_timeout, is not supported on this version. -//! -//! @sa wlan_ioctl_set_scan_params -// -//***************************************************************************** - - -extern INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, - UINT8 *ucResults); - -//***************************************************************************** -// -//! wlan_ioctl_set_scan_params -//! -//! @param uiEnable - start/stop application scan: -//! 1 = start scan with default interval value of 10 min. -//! in order to set a different scan interval value apply the value -//! in milliseconds. minimum 1 second. 0=stop). Wlan reset -//! (wlan_stop() wlan_start()) is needed when changing scan interval -//! value. Saved: No -//! @param uiMinDwellTime minimum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 20) -//! @param uiMaxDwellTime maximum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 30) -//! @param uiNumOfProbeRequests max probe request between dwell time. -//! Saved: yes. Recommended Value: 5 (Default:2) -//! @param uiChannelMask bitwise, up to 13 channels (0x1fff). -//! Saved: yes. Default: 0x7ff -//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) -//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) -//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) -//! @param aiIntervalList pointer to array with 16 entries (16 channels) -//! each entry (UINT32) holds timeout between periodic scan -//! (connection scan) - in milliseconds. Saved: yes. Default 2000ms. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief start and stop scan procedure. Set scan parameters. -//! -//! @Note uiDefaultTxPower, is not supported on this version. -//! -//! @sa wlan_ioctl_get_scan_results -// -//***************************************************************************** -extern INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 - uiMinDwellTime,UINT32 uiMaxDwellTime, - UINT32 uiNumOfProbeRequests, - UINT32 uiChannelMask, - INT32 iRSSIThreshold,UINT32 uiSNRThreshold, - UINT32 uiDefaultTxPower, - UINT32 *aiIntervalList); - - -//***************************************************************************** -// -//! wlan_smart_config_start -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Start to acquire device profile. The device acquire its own -//! profile, if profile message is found. The acquired AP information -//! is stored in CC3000 EEPROM only in case AES128 encryption is used. -//! In case AES128 encryption is not used, a profile is created by -//! CC3000 internally. -//! -//! @Note An asynchronous event - Smart Config Done will be generated as soon -//! as the process finishes successfully. -//! -//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop -// -//***************************************************************************** -extern INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag); - - -//***************************************************************************** -// -//! wlan_smart_config_stop -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Stop the acquire profile procedure -//! -//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix -// -//***************************************************************************** -extern INT32 wlan_smart_config_stop(void); - -//***************************************************************************** -// -//! wlan_smart_config_set_prefix -//! -//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Configure station ssid prefix. The prefix is used internally -//! in CC3000. It should always be TTT. -//! -//! @Note The prefix is stored in CC3000 NVMEM -//! -//! @sa wlan_smart_config_start , wlan_smart_config_stop -// -//***************************************************************************** -extern INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix); - -//***************************************************************************** -// -//! wlan_smart_config_process -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief process the acquired data and store it as a profile. The acquired -//! AP information is stored in CC3000 EEPROM encrypted. -//! The encrypted data is decrypted and stored as a profile. -//! behavior is as defined by connection policy. -// -//***************************************************************************** -extern INT32 wlan_smart_config_process(void); - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** - - - -//***************************************************************************** -// -// Mark the end of the C bindings section for C++ compilers. -// -//***************************************************************************** -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif // __CC3000_WLAN_H__ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/cc3000_common.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/cc3000_common.c deleted file mode 100644 index b4c87848..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/cc3000_common.c +++ /dev/null @@ -1,164 +0,0 @@ -/***************************************************************************** -* -* cc3000_common.c.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -//***************************************************************************** -// -//! \addtogroup common_api -//! @{ -// -//***************************************************************************** -/****************************************************************************** -* -* Include files -* -*****************************************************************************/ - -#include "cc3000_common.h" -#include "socket.h" -#include "wlan.h" -#include "evnt_handler.h" - -//***************************************************************************** -// -//! __error__ -//! -//! @param pcFilename - file name, where error occurred -//! @param ulLine - line number, where error occurred -//! -//! @return none -//! -//! @brief stub function for ASSERT macro -// -//***************************************************************************** -void __error__(CHAR *pcFilename, UINT32 ulLine) -{ - //TODO full up function -} - - - -//***************************************************************************** -// -//! UINT32_TO_STREAM_f -//! -//! @param p pointer to the new stream -//! @param u32 pointer to the 32 bit -//! -//! @return pointer to the new stream -//! -//! @brief This function is used for copying 32 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32) -{ - *(p)++ = (UINT8)(u32); - *(p)++ = (UINT8)((u32) >> 8); - *(p)++ = (UINT8)((u32) >> 16); - *(p)++ = (UINT8)((u32) >> 24); - return p; -} - -//***************************************************************************** -// -//! UINT16_TO_STREAM_f -//! -//! @param p pointer to the new stream -//! @param u32 pointer to the 16 bit -//! -//! @return pointer to the new stream -//! -//! @brief This function is used for copying 16 bit to stream -//! while converting to little endian format. -// -//***************************************************************************** - -UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16) -{ - *(p)++ = (UINT8)(u16); - *(p)++ = (UINT8)((u16) >> 8); - return p; -} - -//***************************************************************************** -// -//! STREAM_TO_UINT16_f -//! -//! @param p pointer to the stream -//! @param offset offset in the stream -//! -//! @return pointer to the new 16 bit -//! -//! @brief This function is used for copying received stream to -//! 16 bit in little endian format. -// -//***************************************************************************** - -UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset) -{ - return (UINT16)((UINT16)((UINT16) - (*(p + offset + 1)) << 8) + (UINT16)(*(p + offset))); -} - -//***************************************************************************** -// -//! STREAM_TO_UINT32_f -//! -//! @param p pointer to the stream -//! @param offset offset in the stream -//! -//! @return pointer to the new 32 bit -//! -//! @brief This function is used for copying received stream to -//! 32 bit in little endian format. -// -//***************************************************************************** - -UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset) -{ - return (UINT32)((UINT32)((UINT32) - (*(p + offset + 3)) << 24) + (UINT32)((UINT32) - (*(p + offset + 2)) << 16) + (UINT32)((UINT32) - (*(p + offset + 1)) << 8) + (UINT32)(*(p + offset))); -} - - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/ccspi.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/ccspi.c deleted file mode 100644 index 820be809..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/ccspi.c +++ /dev/null @@ -1,454 +0,0 @@ -/***************************************************************************** - * - * spi.c - CC3000 Host Driver Implementation. - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include - -#include "py/runtime.h" -#include "pin.h" -#include "led.h" -#include "extint.h" -#include "spi.h" -#include "ccspi.h" -#include "evnt_handler.h" - -#if 0 // print debugging info -#include -#define DEBUG_printf(args...) printf(args) -#else // don't print debugging info -#define DEBUG_printf(args...) (void)0 -#endif - -// these need to be set to valid values before anything in this file will work -STATIC SPI_HandleTypeDef *SPI_HANDLE = NULL; -STATIC const pin_obj_t *PIN_CS = NULL; -STATIC const pin_obj_t *PIN_EN = NULL; -STATIC const pin_obj_t *PIN_IRQ = NULL; - -#define CS_LOW() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_RESET) -#define CS_HIGH() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET) - -#define READ 3 -#define WRITE 1 - -#define HI(value) (((value) & 0xFF00) >> 8) -#define LO(value) ((value) & 0x00FF) - -#define SPI_TIMEOUT (1000) -#define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5) - -/* SPI bus states */ -#define eSPI_STATE_POWERUP (0) -#define eSPI_STATE_INITIALIZED (1) -#define eSPI_STATE_IDLE (2) -#define eSPI_STATE_WRITE_IRQ (3) -#define eSPI_STATE_WRITE_FIRST_PORTION (4) -#define eSPI_STATE_WRITE_EOT (5) -#define eSPI_STATE_READ_IRQ (6) -#define eSPI_STATE_READ_FIRST_PORTION (7) -#define eSPI_STATE_READ_EOT (8) - -// The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) -// for the purpose of detection of the overrun. The location of the memory where the magic number -// resides shall never be written. In case it is written - the overrun occured and either recevie function -// or send function will stuck forever. -#define CC3000_BUFFER_MAGIC_NUMBER (0xDE) - -typedef struct { - gcSpiHandleRx SPIRxHandler; - unsigned short usTxPacketLength; - unsigned short usRxPacketLength; - unsigned long ulSpiState; - unsigned char *pTxPacket; - unsigned char *pRxPacket; -} tSpiInformation; -STATIC tSpiInformation sSpiInformation; - -STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE]; -unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE]; - -STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj; - -// set the pins to use to communicate with the CC3000 -// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* -void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) { - SPI_HANDLE = spi; - PIN_CS = pin_cs; - PIN_EN = pin_en; - PIN_IRQ = pin_irq; -} - -void SpiClose(void) -{ - if (sSpiInformation.pRxPacket) { - sSpiInformation.pRxPacket = 0; - } - - tSLInformation.WlanInterruptDisable(); - - //HAL_SPI_DeInit(SPI_HANDLE); -} - -void SpiOpen(gcSpiHandleRx pfRxHandler) -{ - DEBUG_printf("SpiOpen\n"); - - /* initialize SPI state */ - sSpiInformation.ulSpiState = eSPI_STATE_POWERUP; - sSpiInformation.SPIRxHandler = pfRxHandler; - sSpiInformation.usTxPacketLength = 0; - sSpiInformation.pTxPacket = NULL; - sSpiInformation.pRxPacket = (unsigned char *)spi_buffer; - sSpiInformation.usRxPacketLength = 0; - spi_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; - wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; - - /* SPI configuration */ - SPI_HANDLE->Init.Mode = SPI_MODE_MASTER; - SPI_HANDLE->Init.Direction = SPI_DIRECTION_2LINES; - SPI_HANDLE->Init.DataSize = SPI_DATASIZE_8BIT; - SPI_HANDLE->Init.CLKPolarity = SPI_POLARITY_LOW; - SPI_HANDLE->Init.CLKPhase = SPI_PHASE_2EDGE; - SPI_HANDLE->Init.NSS = SPI_NSS_SOFT; - SPI_HANDLE->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; - SPI_HANDLE->Init.FirstBit = SPI_FIRSTBIT_MSB; - SPI_HANDLE->Init.TIMode = SPI_TIMODE_DISABLED; - SPI_HANDLE->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; - SPI_HANDLE->Init.CRCPolynomial = 7; - spi_init(SPI_HANDLE, false); - - // configure wlan CS and EN pins - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Speed = GPIO_SPEED_FAST; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = 0; - - GPIO_InitStructure.Pin = PIN_CS->pin_mask; - HAL_GPIO_Init(PIN_CS->gpio, &GPIO_InitStructure); - - GPIO_InitStructure.Pin = PIN_EN->pin_mask; - HAL_GPIO_Init(PIN_EN->gpio, &GPIO_InitStructure); - - HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET); - HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, GPIO_PIN_RESET); - - /* do a dummy read, this ensures SCLK is low before - actual communications start, it might be required */ - CS_LOW(); - uint8_t buf[1]; - HAL_SPI_Receive(SPI_HANDLE, buf, sizeof(buf), SPI_TIMEOUT); - CS_HIGH(); - - // register EXTI - extint_register((mp_obj_t)PIN_IRQ, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t)&irq_callback_obj, true); - extint_enable(PIN_IRQ->pin); - - DEBUG_printf("SpiOpen finished; IRQ.pin=%d IRQ_LINE=%d\n", PIN_IRQ->pin, PIN_IRQ->pin); -} - -long ReadWlanInterruptPin(void) -{ - return HAL_GPIO_ReadPin(PIN_IRQ->gpio, PIN_IRQ->pin_mask); -} - -void WriteWlanPin(unsigned char val) -{ - HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, - (WLAN_ENABLE)? GPIO_PIN_SET:GPIO_PIN_RESET); -} - -STATIC void SpiWriteDataSynchronous(unsigned char *data, unsigned short size) -{ - DEBUG_printf("SpiWriteDataSynchronous(data=%p [%x %x %x %x], size=%u)\n", data, data[0], data[1], data[2], data[3], size); - __disable_irq(); - if (HAL_SPI_TransmitReceive(SPI_HANDLE, data, data, size, SPI_TIMEOUT) != HAL_OK) { - //BREAK(); - } - __enable_irq(); - DEBUG_printf(" - rx data = [%x %x %x %x]\n", data[0], data[1], data[2], data[3]); -} - -STATIC void SpiReadDataSynchronous(unsigned char *data, unsigned short size) -{ - memset(data, READ, size); - __disable_irq(); - if (HAL_SPI_TransmitReceive(SPI_HANDLE, data, data, size, SPI_TIMEOUT) != HAL_OK) { - //BREAK(); - } - __enable_irq(); -} - -STATIC void __delay_cycles(volatile int x) -{ - x *= 6; // for 168 MHz CPU - while (x--); -} - -STATIC long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength) -{ - DEBUG_printf("SpiFirstWrite %lu\n", sSpiInformation.ulSpiState); - - CS_LOW(); - - // Assuming we are running on 24 MHz ~50 micro delay is 1200 cycles; - __delay_cycles(1200); - - // SPI writes first 4 bytes of data - SpiWriteDataSynchronous(ucBuf, 4); - - __delay_cycles(1200); - - SpiWriteDataSynchronous(ucBuf + 4, usLength - 4); - - // From this point on - operate in a regular way - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - - return(0); -} - -long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength) -{ - DEBUG_printf("SpiWrite %lu\n", sSpiInformation.ulSpiState); - - unsigned char ucPad = 0; - - // Figure out the total length of the packet in order to figure out if there - // is padding or not - if(!(usLength & 0x0001)) { - ucPad++; - } - - pUserBuffer[0] = WRITE; - pUserBuffer[1] = HI(usLength + ucPad); - pUserBuffer[2] = LO(usLength + ucPad); - pUserBuffer[3] = 0; - pUserBuffer[4] = 0; - - usLength += (SPI_HEADER_SIZE + ucPad); - - // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) - // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun - // occurred - and we will stuck here forever! - if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { - while (1); - } - - if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) { - while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED); - } - - if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) { - // This is time for first TX/RX transactions over SPI: - // the IRQ is down - so need to send read buffer size command - SpiFirstWrite(pUserBuffer, usLength); - } else { - // - // We need to prevent here race that can occur in case 2 back to back packets are sent to the - // device, so the state will move to IDLE and once again to not IDLE due to IRQ - // - tSLInformation.WlanInterruptDisable(); - - while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE); - - sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ; - sSpiInformation.pTxPacket = pUserBuffer; - sSpiInformation.usTxPacketLength = usLength; - - // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation - CS_LOW(); - - // Re-enable IRQ - if it was not disabled - this is not a problem... - tSLInformation.WlanInterruptEnable(); - - // check for a missing interrupt between the CS assertion and enabling back the interrupts - if (tSLInformation.ReadWlanInterruptPin() == 0) { - SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - } - } - - // Due to the fact that we are currently implementing a blocking situation - // here we will wait till end of transaction - while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState); - - return(0); -} - -#if 0 -unused -STATIC void SpiReadPacket(void) -{ - int length; - - /* read SPI header */ - SpiReadDataSynchronous(sSpiInformation.pRxPacket, SPI_HEADER_SIZE); - - /* parse data length */ - STREAM_TO_UINT8(sSpiInformation.pRxPacket, SPI_HEADER_SIZE-1, length); - - /* read the remainder of the packet */ - SpiReadDataSynchronous(sSpiInformation.pRxPacket + SPI_HEADER_SIZE, length); - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; -} -#endif - -STATIC void SpiReadHeader(void) -{ - SpiReadDataSynchronous(sSpiInformation.pRxPacket, 10); -} - -STATIC void SpiTriggerRxProcessing(void) -{ - SpiPauseSpi(); - CS_HIGH(); - - // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) - // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun - // occurred - and we will stuck here forever! - if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) { - while (1); - } - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE); -} - - -STATIC long SpiReadDataCont(void) -{ - long data_to_recv=0; - unsigned char *evnt_buff, type; - - //determine what type of packet we have - evnt_buff = sSpiInformation.pRxPacket; - STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); - - switch (type) { - case HCI_TYPE_DATA:{ - // We need to read the rest of data.. - STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE), - HCI_DATA_LENGTH_OFFSET, data_to_recv); - if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) { - data_to_recv++; - } - - if (data_to_recv) { - SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); - } - break; - } - case HCI_TYPE_EVNT: { - // Calculate the rest length of the data - STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), - HCI_EVENT_LENGTH_OFFSET, data_to_recv); - data_to_recv -= 1; - - // Add padding byte if needed - if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) { - data_to_recv++; - } - - if (data_to_recv) { - SpiReadDataSynchronous(evnt_buff + 10, data_to_recv); - } - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; - break; - } - } - - return 0; -} - -STATIC void SSIContReadOperation(void) -{ - // The header was read - continue with the payload read - if (!SpiReadDataCont()) { - /* All the data was read - finalize handling by switching - to the task and calling from task Event Handler */ - SpiTriggerRxProcessing(); - } -} - -STATIC mp_obj_t irq_callback(mp_obj_t line) { - DEBUG_printf("<< IRQ; state=%lu >>\n", sSpiInformation.ulSpiState); - switch (sSpiInformation.ulSpiState) { - case eSPI_STATE_POWERUP: - /* This means IRQ line was low call a callback of HCI Layer to inform on event */ - DEBUG_printf(" - POWERUP\n"); - sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED; - break; - case eSPI_STATE_IDLE: - DEBUG_printf(" - IDLE\n"); - sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ; - - /* IRQ line goes down - we are start reception */ - CS_LOW(); - - // Wait for TX/RX Compete which will come as DMA interrupt - SpiReadHeader(); - - sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT; - - SSIContReadOperation(); - break; - case eSPI_STATE_WRITE_IRQ: - DEBUG_printf(" - WRITE IRQ\n"); - SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength); - - sSpiInformation.ulSpiState = eSPI_STATE_IDLE; - - CS_HIGH(); - break; - } - return mp_const_none; -} - -STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback); - -void SpiPauseSpi(void) { - DEBUG_printf("SpiPauseSpi\n"); - extint_disable(PIN_IRQ->pin); -} - -void SpiResumeSpi(void) { - DEBUG_printf("SpiResumeSpi\n"); - extint_enable(PIN_IRQ->pin); -} diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/evnt_handler.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/evnt_handler.c deleted file mode 100644 index 80f34e46..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/evnt_handler.c +++ /dev/null @@ -1,849 +0,0 @@ -/***************************************************************************** -* -* evnt_handler.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ -//***************************************************************************** -// -//! \addtogroup evnt_handler_api -//! @{ -// -//****************************************************************************** - -//****************************************************************************** -// INCLUDE FILES -//****************************************************************************** - -#include "cc3000_common.h" -#include "string.h" -#include "hci.h" -#include "evnt_handler.h" -#include "wlan.h" -#include "socket.h" -#include "netapp.h" -#include "ccspi.h" - - - -//***************************************************************************** -// COMMON DEFINES -//***************************************************************************** - -#define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0) -#define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1) -#define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2) -#define FLOW_CONTROL_EVENT_SIZE (4) - -#define BSD_RSP_PARAMS_SOCKET_OFFSET (0) -#define BSD_RSP_PARAMS_STATUS_OFFSET (4) - -#define GET_HOST_BY_NAME_RETVAL_OFFSET (0) -#define GET_HOST_BY_NAME_ADDR_OFFSET (4) - -#define ACCEPT_SD_OFFSET (0) -#define ACCEPT_RETURN_STATUS_OFFSET (4) -#define ACCEPT_ADDRESS__OFFSET (8) - -#define SL_RECEIVE_SD_OFFSET (0) -#define SL_RECEIVE_NUM_BYTES_OFFSET (4) -#define SL_RECEIVE__FLAGS__OFFSET (8) - - -#define SELECT_STATUS_OFFSET (0) -#define SELECT_READFD_OFFSET (4) -#define SELECT_WRITEFD_OFFSET (8) -#define SELECT_EXFD_OFFSET (12) - - -#define NETAPP_IPCONFIG_IP_OFFSET (0) -#define NETAPP_IPCONFIG_SUBNET_OFFSET (4) -#define NETAPP_IPCONFIG_GW_OFFSET (8) -#define NETAPP_IPCONFIG_DHCP_OFFSET (12) -#define NETAPP_IPCONFIG_DNS_OFFSET (16) -#define NETAPP_IPCONFIG_MAC_OFFSET (20) -#define NETAPP_IPCONFIG_SSID_OFFSET (26) - -#define NETAPP_IPCONFIG_IP_LENGTH (4) -#define NETAPP_IPCONFIG_MAC_LENGTH (6) -#define NETAPP_IPCONFIG_SSID_LENGTH (32) - - -#define NETAPP_PING_PACKETS_SENT_OFFSET (0) -#define NETAPP_PING_PACKETS_RCVD_OFFSET (4) -#define NETAPP_PING_MIN_RTT_OFFSET (8) -#define NETAPP_PING_MAX_RTT_OFFSET (12) -#define NETAPP_PING_AVG_RTT_OFFSET (16) - -#define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0) -#define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4) -#define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8) -#define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10) -#define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38) - -#define GET_MSS_VAL_RETVAL_OFFSET (0) - -//***************************************************************************** -// GLOBAL VARAIABLES -//***************************************************************************** - -UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL; - - -//***************************************************************************** -// Prototypes for the static functions -//***************************************************************************** - -static INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent); - -static void update_socket_active_status(CHAR *resp_params); - - -//***************************************************************************** -// -//! hci_unsol_handle_patch_request -//! -//! @param event_hdr event header -//! -//! @return none -//! -//! @brief Handle unsolicited event from type patch request -// -//***************************************************************************** -void hci_unsol_handle_patch_request(CHAR *event_hdr) -{ - CHAR *params = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; - UINT32 ucLength = 0; - CHAR *patch; - - switch (*params) - { - case HCI_EVENT_PATCHES_DRV_REQ: - - if (tSLInformation.sDriverPatches) - { - patch = tSLInformation.sDriverPatches(&ucLength); - - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - - case HCI_EVENT_PATCHES_FW_REQ: - - if (tSLInformation.sFWPatches) - { - patch = tSLInformation.sFWPatches(&ucLength); - - // Build and send a patch - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_FW_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - - case HCI_EVENT_PATCHES_BOOTLOAD_REQ: - - if (tSLInformation.sBootLoaderPatches) - { - patch = tSLInformation.sBootLoaderPatches(&ucLength); - - if (patch) - { - hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, - tSLInformation.pucTxCommandBuffer, patch, ucLength); - return; - } - } - - // Send 0 length Patches response event - hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, - tSLInformation.pucTxCommandBuffer, 0, 0); - break; - } -} - - - -//***************************************************************************** -// -//! hci_event_handler -//! -//! @param pRetParams incoming data buffer -//! @param from from information (in case of data received) -//! @param fromlen from information length (in case of data received) -//! -//! @return none -//! -//! @brief Parse the incoming events packets and issues corresponding -//! event handler from global array of handlers pointers -// -//***************************************************************************** - - -UINT8 * hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen) -{ - UINT8 *pucReceivedData, ucArgsize; - UINT16 usLength; - UINT8 *pucReceivedParams; - UINT16 usReceivedEventOpcode = 0; - UINT32 retValue32; - UINT8 * RecvParams; - UINT8 *RetParams; - - - while (1) - { - if (tSLInformation.usEventOrDataReceived != 0) - { - pucReceivedData = (tSLInformation.pucReceivedData); - - if (*pucReceivedData == HCI_TYPE_EVNT) - { - // Event Received - STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET, - usReceivedEventOpcode); - pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE; - RecvParams = pucReceivedParams; - RetParams = pRetParams; - - // In case unsolicited event received - here the handling finished - if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 0) - { - STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength); - - switch(usReceivedEventOpcode) - { - case HCI_CMND_READ_BUFFER_SIZE: - { - STREAM_TO_UINT8((CHAR *)pucReceivedParams, 0, - tSLInformation.usNumberOfFreeBuffers); - STREAM_TO_UINT16((CHAR *)pucReceivedParams, 1, - tSLInformation.usSlBufferLength); - } - break; - - case HCI_CMND_WLAN_CONFIGURE_PATCH: - case HCI_NETAPP_DHCP: - case HCI_NETAPP_PING_SEND: - case HCI_NETAPP_PING_STOP: - case HCI_NETAPP_ARP_FLUSH: - case HCI_NETAPP_SET_DEBUG_LEVEL: - case HCI_NETAPP_SET_TIMERS: - case HCI_EVNT_NVMEM_READ: - case HCI_EVNT_NVMEM_CREATE_ENTRY: - case HCI_CMND_NVMEM_WRITE_PATCH: - case HCI_NETAPP_PING_REPORT: - case HCI_EVNT_MDNS_ADVERTISE: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET - ,*(UINT8 *)pRetParams); - break; - - case HCI_CMND_SETSOCKOPT: - case HCI_CMND_WLAN_CONNECT: - case HCI_CMND_WLAN_IOCTL_STATUSGET: - case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE: - case HCI_CMND_WLAN_IOCTL_DEL_PROFILE: - case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: - case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP: - case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: - case HCI_CMND_EVENT_MASK: - case HCI_EVNT_WLAN_DISCONNECT: - case HCI_EVNT_SOCKET: - case HCI_EVNT_BIND: - case HCI_CMND_LISTEN: - case HCI_EVNT_CLOSE_SOCKET: - case HCI_EVNT_CONNECT: - case HCI_EVNT_NVMEM_WRITE: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams,0 - ,*(UINT32 *)pRetParams); - break; - - case HCI_EVNT_READ_SP_VERSION: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET - ,*(UINT8 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 1; - STREAM_TO_UINT32((CHAR *)pucReceivedParams, 0, retValue32); - UINT32_TO_STREAM((UINT8 *)pRetParams, retValue32); - break; - - case HCI_EVNT_BSD_GETHOSTBYNAME: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,GET_HOST_BY_NAME_RETVAL_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,GET_HOST_BY_NAME_ADDR_OFFSET,*(UINT32 *)pRetParams); - break; - - case HCI_EVNT_GETMSSVALUE: - - STREAM_TO_UINT16((CHAR *)pucReceivedParams - ,GET_MSS_VAL_RETVAL_OFFSET,*(UINT16 *)pRetParams); - - break; - - case HCI_EVNT_ACCEPT: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,ACCEPT_SD_OFFSET - ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams - ,ACCEPT_RETURN_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - - //This argument returns in network order - memcpy((UINT8 *)pRetParams, - pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr)); - break; - } - - case HCI_EVNT_RECV: - case HCI_EVNT_RECVFROM: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(UINT32 *)pRetParams); - - if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE) - { - set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE); - } - break; - } - - case HCI_EVNT_SEND: - case HCI_EVNT_SENDTO: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - - break; - } - - case HCI_EVNT_SELECT: - { - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_READFD_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_EXFD_OFFSET,*(UINT32 *)pRetParams); - break; - } - - case HCI_CMND_GETSOCKOPT: - - STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus); - //This argument returns in network order - memcpy((UINT8 *)pRetParams, pucReceivedParams, 4); - break; - - case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS: - - STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 4; - STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 2; - STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(UINT32 *)pRetParams); - pRetParams = ((CHAR *)pRetParams) + 2; - memcpy((UINT8 *)pRetParams, (CHAR *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH); - break; - - case HCI_CMND_SIMPLE_LINK_START: - break; - - case HCI_NETAPP_IPCONFIG: - - //Read IP address - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read subnet - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read default GW - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read DHCP server - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read DNS server - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); - RecvParams += 4; - - //Read Mac address - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH); - RecvParams += 6; - - //Read SSID - STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH); - - } - } - - if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode) - { - tSLInformation.usRxEventOpcode = 0; - } - } - else - { - pucReceivedParams = pucReceivedData; - STREAM_TO_UINT8((CHAR *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize); - - STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength); - - // Data received: note that the only case where from and from length - // are not null is in recv from, so fill the args accordingly - if (from) - { - STREAM_TO_UINT32((CHAR *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(UINT32 *)fromlen); - memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen); - } - - memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize, - usLength - ucArgsize); - - tSLInformation.usRxDataPending = 0; - } - - tSLInformation.usEventOrDataReceived = 0; - - SpiResumeSpi(); - - // Since we are going to TX - we need to handle this event after the - // ResumeSPi since we need interrupts - if ((*pucReceivedData == HCI_TYPE_EVNT) && - (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ)) - { - hci_unsol_handle_patch_request((CHAR *)pucReceivedData); - } - - if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0)) - { - return NULL; - } - } - } - -} - -//***************************************************************************** -// -//! hci_unsol_event_handler -//! -//! @param event_hdr event header -//! -//! @return 1 if event supported and handled -//! 0 if event is not supported -//! -//! @brief Handle unsolicited events -// -//***************************************************************************** -INT32 hci_unsol_event_handler(CHAR *event_hdr) -{ - CHAR * data = NULL; - INT32 event_type; - UINT32 NumberOfReleasedPackets; - UINT32 NumberOfSentPackets; - - STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type); - - if (event_type & HCI_EVNT_UNSOL_BASE) - { - switch(event_type) - { - - case HCI_EVNT_DATA_UNSOL_FREE_BUFF: - { - hci_event_unsol_flowcontrol_handler(event_hdr); - - NumberOfReleasedPackets = tSLInformation.NumberOfReleasedPackets; - NumberOfSentPackets = tSLInformation.NumberOfSentPackets; - - if (NumberOfReleasedPackets == NumberOfSentPackets) - { - if (tSLInformation.InformHostOnTxComplete) - { - tSLInformation.sWlanCB(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0); - } - } - return 1; - - } - } - } - - if(event_type & HCI_EVNT_WLAN_UNSOL_BASE) - { - switch(event_type) - { - case HCI_EVNT_WLAN_KEEPALIVE: - case HCI_EVNT_WLAN_UNSOL_CONNECT: - case HCI_EVNT_WLAN_UNSOL_DISCONNECT: - case HCI_EVNT_WLAN_UNSOL_INIT: - case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE: - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, 0, 0); - } - break; - - case HCI_EVNT_WLAN_UNSOL_DHCP: - { - UINT8 params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status - UINT8 *recParams = params; - - data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; - - //Read IP address - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read subnet - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read default GW - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read DHCP server - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - data += 4; - //Read DNS server - STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); - // read the status - STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams); - - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, (CHAR *)params, sizeof(params)); - } - } - break; - - case HCI_EVNT_WLAN_ASYNC_PING_REPORT: - { - netapp_pingreport_args_t params; - data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE; - STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent); - STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received); - STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time); - STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time); - STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time); - - if( tSLInformation.sWlanCB ) - { - tSLInformation.sWlanCB(event_type, (CHAR *)¶ms, sizeof(params)); - } - } - break; - case HCI_EVNT_BSD_TCP_CLOSE_WAIT: - { - data = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE; - if( tSLInformation.sWlanCB ) - { - //data[0] represents the socket id, for which FIN was received by remote. - //Upon receiving this event, the user can close the socket, or else the - //socket will be closded after inacvitity timeout (by default 60 seconds) - tSLInformation.sWlanCB(event_type, data, 1); - } - } - break; - - //'default' case which means "event not supported" - default: - return (0); - } - return(1); - } - - if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO) - || (event_type == HCI_EVNT_WRITE)) - { - CHAR *pArg; - INT32 status; - - pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr); - STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status); - - if (ERROR_SOCKET_INACTIVE == status) - { - // The only synchronous event that can come from SL device in form of - // command complete is "Command Complete" on data sent, in case SL device - // was unable to transmit - STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, tSLInformation.slTransmitDataError); - update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr)); - - return (1); - } - else - return (0); - } - - //handle a case where unsolicited event arrived, but was not handled by any of the cases above - if ((event_type != tSLInformation.usRxEventOpcode) && (event_type != HCI_EVNT_PATCHES_REQ)) - { - return(1); - } - - return(0); -} - -//***************************************************************************** -// -//! hci_unsolicited_event_handler -//! -//! @param None -//! -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Parse the incoming unsolicited event packets and issues -//! corresponding event handler. -// -//***************************************************************************** -INT32 hci_unsolicited_event_handler(void) -{ - UINT32 res = 0; - UINT8 *pucReceivedData; - - if (tSLInformation.usEventOrDataReceived != 0) - { - pucReceivedData = (tSLInformation.pucReceivedData); - - if (*pucReceivedData == HCI_TYPE_EVNT) - { - - // In case unsolicited event received - here the handling finished - if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 1) - { - - // There was an unsolicited event received - we can release the buffer - // and clean the event received - tSLInformation.usEventOrDataReceived = 0; - - res = 1; - SpiResumeSpi(); - } - } - } - - return res; -} - -//***************************************************************************** -// -//! set_socket_active_status -//! -//! @param Sd -//! @param Status -//! @return none -//! -//! @brief Check if the socket ID and status are valid and set -//! accordingly the global socket status -// -//***************************************************************************** -void set_socket_active_status(INT32 Sd, INT32 Status) -{ - if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status)) - { - socket_active_status &= ~(1 << Sd); /* clean socket's mask */ - socket_active_status |= (Status << Sd); /* set new socket's mask */ - } -} - - -//***************************************************************************** -// -//! hci_event_unsol_flowcontrol_handler -//! -//! @param pEvent pointer to the string contains parameters for IPERF -//! @return ESUCCESS if successful, EFAIL if an error occurred -//! -//! @brief Called in case unsolicited event from type -//! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received. -//! Keep track on the number of packets transmitted and update the -//! number of free buffer in the SL device. -// -//***************************************************************************** -INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent) -{ - - INT32 temp, value; - UINT16 i; - UINT16 pusNumberOfHandles=0; - CHAR *pReadPayload; - - STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles); - pReadPayload = ((CHAR *)pEvent + - HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles)); - temp = 0; - - for(i = 0; i < pusNumberOfHandles ; i++) - { - STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value); - temp += value; - pReadPayload += FLOW_CONTROL_EVENT_SIZE; - } - - tSLInformation.usNumberOfFreeBuffers += temp; - tSLInformation.NumberOfReleasedPackets += temp; - - return(ESUCCESS); -} - -//***************************************************************************** -// -//! get_socket_active_status -//! -//! @param Sd Socket IS -//! @return Current status of the socket. -//! -//! @brief Retrieve socket status -// -//***************************************************************************** - -INT32 get_socket_active_status(INT32 Sd) -{ - if(M_IS_VALID_SD(Sd)) - { - return (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE; - } - return SOCKET_STATUS_INACTIVE; -} - -//***************************************************************************** -// -//! update_socket_active_status -//! -//! @param resp_params Socket IS -//! @return Current status of the socket. -//! -//! @brief Retrieve socket status -// -//***************************************************************************** -void update_socket_active_status(CHAR *resp_params) -{ - INT32 status, sd; - - STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd); - STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status); - - if(ERROR_SOCKET_INACTIVE == status) - { - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - } -} - - -//***************************************************************************** -// -//! SimpleLinkWaitEvent -//! -//! @param usOpcode command operation code -//! @param pRetParams command return parameters -//! -//! @return none -//! -//! @brief Wait for event, pass it to the hci_event_handler and -//! update the event opcode in a global variable. -// -//***************************************************************************** - -void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams) -{ - // In the blocking implementation the control to caller will be returned only - // after the end of current transaction - tSLInformation.usRxEventOpcode = usOpcode; - hci_event_handler(pRetParams, 0, 0); -} - -//***************************************************************************** -// -//! SimpleLinkWaitData -//! -//! @param pBuf data buffer -//! @param from from information -//! @param fromlen from information length -//! -//! @return none -//! -//! @brief Wait for data, pass it to the hci_event_handler -//! and update in a global variable that there is -//! data to read. -// -//***************************************************************************** - -void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen) -{ - // In the blocking implementation the control to caller will be returned only - // after the end of current transaction, i.e. only after data will be received - tSLInformation.usRxDataPending = 1; - hci_event_handler(pBuf, from, fromlen); -} - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/hci.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/hci.c deleted file mode 100644 index 4391692b..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/hci.c +++ /dev/null @@ -1,225 +0,0 @@ -/***************************************************************************** -* -* hci.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup hci_app -//! @{ -// -//***************************************************************************** - -#include -#include "cc3000_common.h" -#include "hci.h" -#include "ccspi.h" -#include "evnt_handler.h" -#include "wlan.h" - -#define SL_PATCH_PORTION_SIZE (1000) - - -//***************************************************************************** -// -//! hci_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param ucArgsLength length of the arguments -//! -//! @return none -//! -//! @brief Initiate an HCI command. -// -//***************************************************************************** -UINT16 hci_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength) -{ - UINT8 *stream; - - stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_CMND); - stream = UINT16_TO_STREAM(stream, usOpcode); - UINT8_TO_STREAM(stream, ucArgsLength); - - //Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE); - - return(0); -} - -//***************************************************************************** -// -//! hci_data_send -//! -//! @param usOpcode command operation code -//! @param ucArgs pointer to the command's arguments buffer -//! @param usArgsLength length of the arguments -//! @param ucTail pointer to the data buffer -//! @param usTailLength buffer length -//! -//! @return none -//! -//! @brief Initiate an HCI data write operation -// -//***************************************************************************** -INT32 hci_data_send(UINT8 ucOpcode, - UINT8 *ucArgs, - UINT16 usArgsLength, - UINT16 usDataLength, - const UINT8 *ucTail, - UINT16 usTailLength) -{ - UINT8 *stream; - - stream = ((ucArgs) + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_DATA); - UINT8_TO_STREAM(stream, ucOpcode); - UINT8_TO_STREAM(stream, usArgsLength); - stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength); - - // Send the packet over the SPI - SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength); - - return(ESUCCESS); -} - - -//***************************************************************************** -// -//! hci_data_command_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the data buffer -//! @param ucArgsLength arguments length -//! @param ucDataLength data length -//! -//! @return none -//! -//! @brief Prepeare HCI header and initiate an HCI data write operation -// -//***************************************************************************** -void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength,UINT16 ucDataLength) -{ - UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_DATA); - UINT8_TO_STREAM(stream, usOpcode); - UINT8_TO_STREAM(stream, ucArgsLength); - stream = UINT16_TO_STREAM(stream, ucArgsLength + ucDataLength); - - // Send the command over SPI on data channel - SpiWrite(pucBuff, ucArgsLength + ucDataLength + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE); - - return; -} - -//***************************************************************************** -// -//! hci_patch_send -//! -//! @param usOpcode command operation code -//! @param pucBuff pointer to the command's arguments buffer -//! @param patch pointer to patch content buffer -//! @param usDataLength data length -//! -//! @return none -//! -//! @brief Prepeare HCI header and initiate an HCI patch write operation -// -//***************************************************************************** -void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength) -{ - UINT8 *data_ptr = (pucBuff + SPI_HEADER_SIZE); - UINT16 usTransLength; - UINT8 *stream = (pucBuff + SPI_HEADER_SIZE); - - UINT8_TO_STREAM(stream, HCI_TYPE_PATCH); - UINT8_TO_STREAM(stream, ucOpcode); - stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); - - if (usDataLength <= SL_PATCH_PORTION_SIZE) - { - UINT16_TO_STREAM(stream, usDataLength); - stream = UINT16_TO_STREAM(stream, usDataLength); - memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength); - - // Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE); - } - else - { - - usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE); - UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); - stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE); - memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE); - usDataLength -= SL_PATCH_PORTION_SIZE; - patch += SL_PATCH_PORTION_SIZE; - - // Update the opcode of the event we will be waiting for - SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE); - - while (usDataLength) - { - if (usDataLength <= SL_PATCH_PORTION_SIZE) - { - usTransLength = usDataLength; - usDataLength = 0; - - } - else - { - usTransLength = SL_PATCH_PORTION_SIZE; - usDataLength -= usTransLength; - } - - *(UINT16 *)data_ptr = usTransLength; - memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength); - patch += usTransLength; - - // Update the opcode of the event we will be waiting for - SpiWrite((UINT8 *)data_ptr, usTransLength + sizeof(usTransLength)); - } - } -} - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -// -//***************************************************************************** diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/inet_ntop.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/inet_ntop.c deleted file mode 100644 index 83242efa..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/inet_ntop.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 1996-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM - * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL - * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "cc3000_common.h" -#include "socket.h" -#include "inet_ntop.h" - -// We can't include stdio.h because it defines _types_fd_set, but we -// need to use the CC3000 version of this type. So we must provide -// our own declaration of snprintf. Grrr. -int snprintf(char *str, size_t size, const char *fmt, ...); - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -#define ENOSPC (28) -#define EAFNOSUPPORT (106) -#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) - -/* - * Format an IPv4 address, more or less like inet_ntoa(). - * - * Returns `dst' (as a const) - * Note: - * - uses no statics - * - takes a unsigned char* not an in_addr as input - */ -static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size) -{ - size_t len; - char tmp[sizeof "255.255.255.255"]; - - tmp[0] = '\0'; - (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d", - ((int)((unsigned char)src[3])) & 0xff, - ((int)((unsigned char)src[2])) & 0xff, - ((int)((unsigned char)src[1])) & 0xff, - ((int)((unsigned char)src[0])) & 0xff); - - len = strlen(tmp); - if(len == 0 || len >= size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} - -#ifdef ENABLE_IPV6 -/* - * Convert IPv6 binary address into presentation (printable) format. - */ -static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) -{ - /* - * Note that int32_t and int16_t need only be "at least" large enough - * to contain a value of the specified size. On some systems, like - * Crays, there is no such thing as an integer variable with 16 bits. - * Keep this in mind if you think this function should have been coded - * to use pointer overlays. All the world's not a VAX. - */ - char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; - char *tp; - struct { - long base; - long len; - } best, cur; - unsigned long words[IN6ADDRSZ / INT16SZ]; - int i; - - /* Preprocess: - * Copy the input (bytewise) array into a wordwise array. - * Find the longest run of 0x00's in src[] for :: shorthanding. - */ - memset(words, '\0', sizeof(words)); - for (i = 0; i < IN6ADDRSZ; i++) - words[i/2] |= (src[i] << ((1 - (i % 2)) << 3)); - - best.base = -1; - cur.base = -1; - best.len = 0; - cur.len = 0; - - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - if(words[i] == 0) - { - if(cur.base == -1) - cur.base = i, cur.len = 1; - else - cur.len++; - } - else if(cur.base != -1) - { - if(best.base == -1 || cur.len > best.len) - best = cur; - cur.base = -1; - } - } - if((cur.base != -1) && (best.base == -1 || cur.len > best.len)) - best = cur; - if(best.base != -1 && best.len < 2) - best.base = -1; - - /* Format the result. - */ - tp = tmp; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) - { - /* Are we inside the best run of 0x00's? - */ - if(best.base != -1 && i >= best.base && i < (best.base + best.len)) - { - if(i == best.base) - *tp++ = ':'; - continue; - } - - /* Are we following an initial run of 0x00s or any real hex? - */ - if(i != 0) - *tp++ = ':'; - - /* Is this address an encapsulated IPv4? - */ - if(i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) - { - if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - tp += strlen(tp); - break; - } - tp += snprintf(tp, 5, "%lx", words[i]); - } - - /* Was it a trailing run of 0x00's? - */ - if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) - *tp++ = ':'; - *tp++ = '\0'; - - /* Check for overflow, copy, and we're done. - */ - if((size_t)(tp - tmp) > size) - { - SET_ERRNO(ENOSPC); - return (NULL); - } - strcpy(dst, tmp); - return dst; -} -#endif /* ENABLE_IPV6 */ - -/* - * Convert a network format address to presentation format. - * - * Returns pointer to presentation format address (`buf'). - * Returns NULL on error and errno set with the specific - * error, EAFNOSUPPORT or ENOSPC. - * - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid loosing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this funtion sets when returning NULL, not SOCKERRNO. - */ -char *inet_ntop(int af, const void *src, char *buf, size_t size) -{ - switch (af) { - case AF_INET: - return inet_ntop4((const unsigned char*)src, buf, size); -#ifdef ENABLE_IPV6 - case AF_INET6: - return inet_ntop6((const unsigned char*)src, buf, size); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return NULL; - } -} diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/inet_pton.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/inet_pton.c deleted file mode 100644 index 5f5ae5f9..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/inet_pton.c +++ /dev/null @@ -1,216 +0,0 @@ -/* This is from the BIND 4.9.4 release, modified to compile by itself */ - -/* Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include -#include "cc3000_common.h" -#include "socket.h" -#include "inet_pton.h" - -#define IN6ADDRSZ 16 -#define INADDRSZ 4 -#define INT16SZ 2 - -static int inet_pton4(const char *src, unsigned char *dst); -#ifdef ENABLE_IPV6 -static int inet_pton6(const char *src, unsigned char *dst); -#endif - -#define EAFNOSUPPORT (106) -#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err) - -/* int - * inet_pton(af, src, dst) - * convert from presentation format (which usually means ASCII printable) - * to network format (which is usually some kind of binary format). - * return: - * 1 if the address was valid for the specified address family - * 0 if the address wasn't valid (`dst' is untouched in this case) - * -1 if some other error occurred (`dst' is untouched in this case, too) - * notice: - * On Windows we store the error in the thread errno, not - * in the winsock error code. This is to avoid loosing the - * actual last winsock error. So use macro ERRNO to fetch the - * errno this funtion sets when returning (-1), not SOCKERRNO. - * author: - * Paul Vixie, 1996. - */ -int inet_pton(int af, const char *src, void *dst) -{ - switch (af) { - case AF_INET: - return (inet_pton4(src, (unsigned char *)dst)); -#ifdef ENABLE_IPV6 - case AF_INET6: - return (inet_pton6(src, (unsigned char *)dst)); -#endif - default: - SET_ERRNO(EAFNOSUPPORT); - return (-1); - } - /* NOTREACHED */ -} - -/* int - * inet_pton4(src, dst) - * like inet_aton() but without all the hexadecimal and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton4(const char *src, unsigned char *dst) -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - unsigned char tmp[INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - tp = tmp; - *tp = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr(digits, ch)) != NULL) { - unsigned int val = *tp * 10 + (unsigned int)(pch - digits); - - if(saw_digit && *tp == 0) - return (0); - if(val > 255) - return (0); - *tp = (unsigned char)val; - if(! saw_digit) { - if(++octets > 4) - return (0); - saw_digit = 1; - } - } - else if(ch == '.' && saw_digit) { - if(octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } - else - return (0); - } - if(octets < 4) - return (0); - memcpy(dst, tmp, INADDRSZ); - return (1); -} - -#ifdef ENABLE_IPV6 -/* int - * inet_pton6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton6(const char *src, unsigned char *dst) -{ - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; - const char *xdigits, *curtok; - int ch, saw_xdigit; - unsigned int val; - - memset((tp = tmp), 0, IN6ADDRSZ); - endp = tp + IN6ADDRSZ; - colonp = NULL; - /* Leading :: requires some special handling. */ - if(*src == ':') - if(*++src != ':') - return (0); - curtok = src; - saw_xdigit = 0; - val = 0; - while((ch = *src++) != '\0') { - const char *pch; - - if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if(pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if(++saw_xdigit > 4) - return (0); - continue; - } - if(ch == ':') { - curtok = src; - if(!saw_xdigit) { - if(colonp) - return (0); - colonp = tp; - continue; - } - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if(ch == '.' && ((tp + INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { - tp += INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return (0); - } - if(saw_xdigit) { - if(tp + INT16SZ > endp) - return (0); - *tp++ = (unsigned char) (val >> 8) & 0xff; - *tp++ = (unsigned char) val & 0xff; - } - if(colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const long n = tp - colonp; - long i; - - if(tp == endp) - return (0); - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if(tp != endp) - return (0); - memcpy(dst, tmp, IN6ADDRSZ); - return (1); -} -#endif /* ENABLE_IPV6 */ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/netapp.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/netapp.c deleted file mode 100644 index a6f60fed..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/netapp.c +++ /dev/null @@ -1,459 +0,0 @@ -/***************************************************************************** -* -* netapp.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -#include -#include "netapp.h" -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" -#include "nvmem.h" - -#define MIN_TIMER_VAL_SECONDS 10 -#define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \ - { \ - t = MIN_TIMER_VAL_SECONDS; \ - } - - -#define NETAPP_DHCP_PARAMS_LEN (20) -#define NETAPP_SET_TIMER_PARAMS_LEN (20) -#define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4) -#define NETAPP_PING_SEND_PARAMS_LEN (16) - - -//***************************************************************************** -// -//! netapp_config_mac_adrress -//! -//! @param mac device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Configure device MAC address and store it in NVMEM. -//! The value of the MAC address configured through the API will -//! be stored in CC3000 non volatile memory, thus preserved -//! over resets. -// -//***************************************************************************** -INT32 netapp_config_mac_adrress(UINT8 * mac) -{ - return nvmem_set_mac_address(mac); -} - -//***************************************************************************** -// -//! netapp_dhcp -//! -//! @param aucIP device mac address, 6 bytes. Saved: yes -//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes -//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes -//! @param aucDNSServer device mac address, 6 bytes. Saved: yes -//! -//! @return return on success 0, otherwise error. -//! -//! @brief netapp_dhcp is used to configure the network interface, -//! static or dynamic (DHCP).\n In order to activate DHCP mode, -//! aucIP, aucSubnetMask, aucDefaultGateway must be 0. -//! The default mode of CC3000 is DHCP mode. -//! Note that the configuration is saved in non volatile memory -//! and thus preserved over resets. -//! -//! @note If the mode is altered a reset of CC3000 device is required -//! in order to apply changes.\nAlso note that asynchronous event -//! of DHCP_EVENT, which is generated when an IP address is -//! allocated either by the DHCP server or due to static -//! allocation is generated only upon a connection to the -//! AP was established. -//! -//***************************************************************************** -INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer) -{ - INT8 scRet; - UINT8 *ptr; - UINT8 *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - ARRAY_TO_STREAM(args,aucIP,4); - ARRAY_TO_STREAM(args,aucSubnetMask,4); - ARRAY_TO_STREAM(args,aucDefaultGateway,4); - args = UINT32_TO_STREAM(args, 0); - ARRAY_TO_STREAM(args,aucDNSServer,4); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet); - - return(scRet); -} - - -//***************************************************************************** -// -//! netapp_timeout_values -//! -//! @param aucDHCP DHCP lease time request, also impact -//! the DHCP renew timeout. Range: [0-0xffffffff] seconds, -//! 0 or 0xffffffff == infinity lease timeout. -//! Resolution:10 seconds. Influence: only after -//! reconnecting to the AP. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds. -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 14400 seconds. -//! -//! @param aucARP ARP refresh timeout, if ARP entry is not updated by -//! incoming packet, the ARP entry will be deleted by -//! the end of the timeout. -//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 3600 seconds. -//! -//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout -//! Range: [0-0xffffffff] seconds, 0 == infinity timeout -//! Resolution: 10 seconds. -//! Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 10 seconds. -//! -//! @param aucInactivity Socket inactivity timeout, socket timeout is -//! refreshed by incoming or outgoing packet, by the -//! end of the socket timeout the socket will be closed -//! Range: [0-0xffffffff] sec, 0 == infinity timeout. -//! Resolution: 10 seconds. Influence: on runtime. -//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec -//! The parameter is saved into the CC3000 NVMEM. -//! The default value on CC3000 is 60 seconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief Set new timeout values. Function set new timeout values for: -//! DHCP lease timeout, ARP refresh timeout, keepalive event -//! timeout and socket inactivity timeout -//! -//! @note If a parameter set to non zero value which is less than 10s, -//! it will be set automatically to 10s. -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP,UINT32 *aucKeepalive, UINT32 *aucInactivity) -{ - INT8 scRet; - UINT8 *ptr; - UINT8 *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Set minimal values of timers - MIN_TIMER_SET(*aucDHCP) - MIN_TIMER_SET(*aucARP) - MIN_TIMER_SET(*aucKeepalive) - MIN_TIMER_SET(*aucInactivity) - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, *aucDHCP); - args = UINT32_TO_STREAM(args, *aucARP); - args = UINT32_TO_STREAM(args, *aucKeepalive); - args = UINT32_TO_STREAM(args, *aucInactivity); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet); - - return(scRet); -} -#endif - - -//***************************************************************************** -// -//! netapp_ping_send -//! -//! @param ip destination IP address -//! @param pingAttempts number of echo requests to send -//! @param pingSize send buffer size which may be up to 1400 bytes -//! @param pingTimeout Time to wait for a response,in milliseconds. -//! -//! @return return on success 0, otherwise error. -//! -//! @brief send ICMP ECHO_REQUEST to network hosts -//! -//! @note If an operation finished successfully asynchronous ping report -//! event will be generated. The report structure is as defined -//! by structure netapp_pingreport_args_t. -//! -//! @warning Calling this function while a previous Ping Requests are in -//! progress will stop the previous ping request. -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 - netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout) -{ - INT8 scRet; - UINT8 *ptr, *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, *ip); - args = UINT32_TO_STREAM(args, ulPingAttempts); - args = UINT32_TO_STREAM(args, ulPingSize); - args = UINT32_TO_STREAM(args, ulPingTimeout); - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ping_report -//! -//! @param none -//! -//! @return none -//! -//! @brief Request for ping status. This API triggers the CC3000 to send -//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT. -//! This event will carry the report structure: -//! netapp_pingreport_args_t. This structure is filled in with ping -//! results up till point of triggering API. -//! netapp_pingreport_args_t:\n packets_sent - echo sent, -//! packets_received - echo reply, min_round_time - minimum -//! round time, max_round_time - max round time, -//! avg_round_time - average round time -//! -//! @note When a ping operation is not active, the returned structure -//! fields are 0. -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -void netapp_ping_report() -{ - UINT8 *ptr; - ptr = tSLInformation.pucTxCommandBuffer; - INT8 scRet; - - scRet = EFAIL; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_REPORT, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ping_stop -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief Stop any ping request. -//! -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_ping_stop() -{ - INT8 scRet; - UINT8 *ptr; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_PING_STOP, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_ipconfig -//! -//! @param[out] ipconfig This argument is a pointer to a -//! tNetappIpconfigRetArgs structure. This structure is -//! filled in with the network interface configuration. -//! tNetappIpconfigRetArgs:\n aucIP - ip address, -//! aucSubnetMask - mask, aucDefaultGateway - default -//! gateway address, aucDHCPServer - dhcp server address -//! aucDNSServer - dns server address, uaMacAddr - mac -//! address, uaSSID - connected AP ssid -//! -//! @return none -//! -//! @brief Obtain the CC3000 Network interface information. -//! Note that the information is available only after the WLAN -//! connection was established. Calling this function before -//! associated, will cause non-defined values to be returned. -//! -//! @note The function is useful for figuring out the IP Configuration of -//! the device when DHCP is used and for figuring out the SSID of -//! the Wireless network the device is associated with. -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) -{ - UINT8 *ptr; - - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_IPCONFIG, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig ); - -} -#else -void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig ) -{ - -} -#endif - -//***************************************************************************** -// -//! netapp_arp_flush -//! -//! @param none -//! -//! @return none -//! -//! @brief Flushes ARP table -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_arp_flush(void) -{ - INT8 scRet; - UINT8 *ptr; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command - hci_command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet); - - return(scRet); -} -#endif - -//***************************************************************************** -// -//! netapp_set_debug_level -//! -//! @param[in] level debug level. Bitwise [0-8], -//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical -//! message, 1 information message, 2 - core messages, 3 - -//! HCI messages, 4 - Network stack messages, 5 - wlan -//! messages, 6 - wlan driver messages, 7 - epprom messages, -//! 8 - general messages. Default: 0x13f. Saved: no -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Debug messages sent via the UART debug channel, this function -//! enable/disable the debug level -//! -//***************************************************************************** - - -#ifndef CC3000_TINY_DRIVER -INT32 netapp_set_debug_level(UINT32 ulLevel) -{ - INT8 scRet; - UINT8 *ptr, *args; - - scRet = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // - // Fill in temporary command buffer - // - args = UINT32_TO_STREAM(args, ulLevel); - - - // - // Initiate a HCI command - // - hci_command_send(HCI_NETAPP_SET_DEBUG_LEVEL, ptr, NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN); - - // - // Wait for command complete event - // - SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet); - - return(scRet); - -} -#endif diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/nvmem.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/nvmem.c deleted file mode 100644 index c6e170a7..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/nvmem.c +++ /dev/null @@ -1,334 +0,0 @@ -/***************************************************************************** -* -* nvmem.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup nvmem_api -//! @{ -// -//***************************************************************************** - -#include -#include "nvmem.h" -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" - -//***************************************************************************** -// -// Prototypes for the structures for APIs. -// -//***************************************************************************** - -#define NVMEM_READ_PARAMS_LEN (12) -#define NVMEM_CREATE_PARAMS_LEN (8) -#define NVMEM_WRITE_PARAMS_LEN (16) - -//***************************************************************************** -// -//! nvmem_read -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID, -//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID, -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID, -//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID, -//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to read -//! @param ulOffset ulOffset in file from where to read -//! @param buff output buffer pointer -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads data from the file referred by the ulFileId parameter. -//! Reads data from file ulOffset till length. Err if the file can't -//! be used, is invalid, or if the read is out of bounds. -//! -//***************************************************************************** - -INT32 nvmem_read(UINT32 ulFileId, UINT32 ulLength, UINT32 ulOffset, UINT8 *buff) -{ - UINT8 ucStatus = 0xFF; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, ulLength); - args = UINT32_TO_STREAM(args, ulOffset); - - // Initiate a HCI command - hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN); - SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus); - - // In case there is data - read it - even if an error code is returned - // Note: It is the user responsibility to ignore the data in case of an error code - - // Wait for the data in a synchronous way. Here we assume that the buffer is - // big enough to store also parameters of nvmem - - SimpleLinkWaitData(buff, 0, 0); - - return(ucStatus); -} - -//***************************************************************************** -// -//! nvmem_write -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID, -//! and user files 12-15. -//! @param ulLength number of bytes to write -//! @param ulEntryOffset offset in file to start write operation from -//! @param buff data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write data to nvmem. -//! writes data to file referred by the ulFileId parameter. -//! Writes data to file ulOffset till ulLength.The file id will be -//! marked invalid till the write is done. The file entry doesn't -//! need to be valid - only allocated. -//! -//***************************************************************************** - -INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff) -{ - INT32 iRes; - UINT8 *ptr; - UINT8 *args; - - iRes = EFAIL; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, 12); - args = UINT32_TO_STREAM(args, ulLength); - args = UINT32_TO_STREAM(args, ulEntryOffset); - - memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE + - NVMEM_WRITE_PARAMS_LEN),buff,ulLength); - - // Initiate a HCI command but it will come on data channel - hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN, - ulLength); - - SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes); - - return(iRes); -} - - -//***************************************************************************** -// -//! nvmem_set_mac_address -//! -//! @param mac mac address to be set -//! -//! @return on success 0, error otherwise. -//! -//! @brief Write MAC address to EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** - -UINT8 nvmem_set_mac_address(UINT8 *mac) -{ - return nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); -} - -//***************************************************************************** -// -//! nvmem_get_mac_address -//! -//! @param[out] mac mac address -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read MAC address from EEPROM. -//! mac address as appears over the air (OUI first) -//! -//***************************************************************************** - -UINT8 nvmem_get_mac_address(UINT8 *mac) -{ - return nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); -} - -//***************************************************************************** -// -//! nvmem_write_patch -//! -//! @param ulFileId nvmem file id:\n -//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID, -//! @param spLength number of bytes to write -//! @param spData SP data to write -//! -//! @return on success 0, error otherwise. -//! -//! @brief program a patch to a specific file ID. -//! The SP data is assumed to be organized in 2-dimensional. -//! Each line is SP_PORTION_SIZE bytes long. Actual programming is -//! applied in SP_PORTION_SIZE bytes portions. -//! -//***************************************************************************** - -UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData) -{ - UINT8 status = 0; - UINT16 offset = 0; - UINT8* spDataPtr = (UINT8*)spData; - - while ((status == 0) && (spLength >= SP_PORTION_SIZE)) - { - status = nvmem_write(ulFileId, SP_PORTION_SIZE, offset, spDataPtr); - offset += SP_PORTION_SIZE; - spLength -= SP_PORTION_SIZE; - spDataPtr += SP_PORTION_SIZE; - } - - if (status !=0) - { - // NVMEM error occurred - return status; - } - - if (spLength != 0) - { - // if reached here, a reminder is left - status = nvmem_write(ulFileId, spLength, offset, spDataPtr); - } - - return status; -} - -//***************************************************************************** -// -//! nvmem_read_sp_version -//! -//! @param[out] patchVer first number indicates package ID and the second -//! number indicates package build number -//! -//! @return on success 0, error otherwise. -//! -//! @brief Read patch version. read package version (WiFi FW patch, -//! driver-supplicant-NS patch, bootloader patch) -//! -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -UINT8 nvmem_read_sp_version(UINT8* patchVer) -{ - UINT8 *ptr; - // 1st byte is the status and the rest is the SP version - UINT8 retBuf[5]; - - ptr = tSLInformation.pucTxCommandBuffer; - - // Initiate a HCI command, no args are required - hci_command_send(HCI_CMND_READ_SP_VERSION, ptr, 0); - SimpleLinkWaitEvent(HCI_CMND_READ_SP_VERSION, retBuf); - - // package ID - *patchVer = retBuf[3]; - // package build number - *(patchVer+1) = retBuf[4]; - - return(retBuf[0]); -} -#endif - -//***************************************************************************** -// -//! nvmem_create_entry -//! -//! @param ulFileId nvmem file Id:\n -//! * NVMEM_AES128_KEY_FILEID: 12 -//! * NVMEM_SHARED_MEM_FILEID: 13 -//! * and fileIDs 14 and 15 -//! @param ulNewLen entry ulLength -//! -//! @return on success 0, error otherwise. -//! -//! @brief Create new file entry and allocate space on the NVMEM. -//! Applies only to user files. -//! Modify the size of file. -//! If the entry is unallocated - allocate it to size -//! ulNewLen (marked invalid). -//! If it is allocated then deallocate it first. -//! To just mark the file as invalid without resizing - -//! set ulNewLen=0. -//! -//***************************************************************************** - -INT32 nvmem_create_entry(UINT32 ulFileId, UINT32 ulNewLen) -{ - UINT8 *ptr; - UINT8 *args; - UINT8 retval; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulFileId); - args = UINT32_TO_STREAM(args, ulNewLen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN); - - SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval); - - return(retval); -} - - - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/patch.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/patch.c deleted file mode 100644 index 227be3c9..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/patch.c +++ /dev/null @@ -1,117 +0,0 @@ -/***************************************************************************** - * - * {PatchProgrammer_DR_Patch.c} - * - * Burn Patches to EEPROM - * - * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ - * ALL RIGHTS RESERVED - * - *****************************************************************************/ -// -// Service Pack version P1.13.7.15.28 - Driver patches -// This file contains the CC3K driver and firmware patches -// From CC3000-FRAM-PATCH V:1.13.7 15-MAY-2014 - -unsigned short fw_length = 5700; -unsigned short drv_length = 8024; - -const unsigned char wlan_drv_patch[8024] = { 0x00, 0x01, 0x00, 0x00, 0x50, 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x18, 0x00, 0xE4, 0x62, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7A, 0x63, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x0C, 0x49, 0x08, 0x60, 0x0C, 0x48, 0x19, 0x30, 0xF7, 0x46, 0x30, 0xB5, 0x05, 0x1C, 0xAC, 0x69, 0x68, 0x68, 0x5F, 0x30, 0x09, 0xD1, 0x60, 0x6B, 0x0C, 0x38, 0x01, 0x21, 0x8E, 0x46, 0x06, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x00, 0x20, 0x60, 0x63, 0xAC, 0x69, 0x6C, 0x60, 0x04, 0x48, 0x5B, 0x30, 0x30, 0xBD, 0x40, 0x3B, 0x08, 0x00, 0x49, 0xD0, 0x01, 0x00, 0x09, 0xEA, 0x02, 0x00, 0x91, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x05, 0x1C, 0xA8, 0x88, 0x00, 0x90, 0x28, 0x89, 0x01, 0x90, 0xE9, 0x68, 0x02, 0x91, 0x28, 0x7C, 0x03, 0x90, 0x2A, 0x6A, 0x00, 0x20, 0x17, 0x56, 0x68, 0x60, 0x00, 0x29, 0x4C, 0xD0, 0x00, 0x2F, 0x4A, 0xDC , -0xCA, 0x49, 0x0C, 0x1C, 0x08, 0x26, 0x04, 0x90, 0x21, 0x88, 0x00, 0x98, 0x81, 0x42, 0x0C, 0xD1, 0x62, 0x88, 0x01, 0x98, 0x82, 0x42, 0x08, 0xD1, 0x46, 0x20, 0x02, 0x5D, 0x03, 0x98, 0x82, 0x42, 0x03, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xB8, 0x42, 0x0A, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x22, 0xD1, 0x00, 0x98, 0x81, 0x42, 0x1F, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xFF, 0xFF, 0xD2, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB8, 0x42, 0x1B, 0xD1, 0x04, 0x20, 0x02, 0x1C, 0x02, 0x98, 0xB9, 0x49, 0x01, 0x23, 0x9E, 0x46, 0xEC, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x17, 0xD0, 0x20, 0x1D, 0x02, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x0D, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x09, 0xD0, 0xA0, 0x6D, 0x00, 0x28, 0x06, 0xD0, 0xAC, 0x34, 0x04, 0x98, 0x01, 0x30, 0x04, 0x90, 0x01, 0x3E, 0xC1, 0xD1, 0x07, 0xE0, 0x04, 0x98, 0x00, 0x06, 0x00, 0x0E , -0xAC, 0x21, 0x41, 0x43, 0xA6, 0x48, 0x40, 0x18, 0x68, 0x60, 0xA6, 0x48, 0xAD, 0x30, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xB5, 0xC2, 0x68, 0x90, 0x69, 0x02, 0x21, 0x01, 0x23, 0x9E, 0x46, 0xA2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xA2, 0x48, 0x61, 0x30, 0x00, 0xBD, 0x01, 0x79, 0x0B, 0x29, 0x03, 0xD0, 0x89, 0x00, 0x9F, 0x4A, 0x51, 0x5A, 0x01, 0xE0, 0x01, 0x21, 0x49, 0x02, 0x41, 0x60, 0x9D, 0x48, 0x0D, 0x30, 0xF7, 0x46, 0x01, 0x1C, 0xFF, 0xFF, 0x68, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x9C, 0x48, 0x02, 0x68, 0x9C, 0x48, 0x01, 0x2A, 0x01, 0xD1, 0x25, 0x30, 0xF7, 0x46, 0x9B, 0x4A, 0x12, 0x68, 0x4A, 0x60, 0x19, 0x30, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x99, 0x48, 0x98, 0x49, 0x08, 0x18, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x97, 0x48, 0xE7, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xFF, 0xB5, 0x46, 0x69, 0x40, 0x68, 0x01, 0x90, 0x94, 0x49, 0x0A, 0x7C, 0x9A, 0x4F, 0x01, 0x2A, 0x63, 0xD0, 0x09, 0x7C, 0x03, 0x29 , -0x60, 0xD0, 0x91, 0x4A, 0x92, 0x4B, 0x00, 0x21, 0x02, 0x91, 0x59, 0x56, 0x24, 0x23, 0x59, 0x43, 0x53, 0x18, 0x03, 0x93, 0x01, 0x28, 0x17, 0xD1, 0x8A, 0x18, 0x04, 0x23, 0x6C, 0x46, 0x8C, 0x49, 0x15, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x28, 0x43, 0x20, 0x70, 0x01, 0x32, 0x01, 0x31, 0x01, 0x34, 0x01, 0x3B, 0xF5, 0xD1, 0x31, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x40, 0xD0, 0x35, 0x1D, 0x82, 0x48, 0x00, 0x78, 0xFF, 0x28, 0xFF, 0xFF, 0xFE, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x11, 0xD0, 0x00, 0x28, 0x0F, 0xD0, 0x03, 0x98, 0x01, 0x1D, 0x28, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x7E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x00, 0x28, 0x05, 0xD1, 0x7A, 0x48, 0xA6, 0x46, 0x7B, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x05, 0xE0, 0x28, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0x78, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x99, 0x01, 0x29, 0x01, 0xD1, 0x00, 0x28, 0x1E, 0xD1 , -0x01, 0x99, 0x5F, 0x31, 0x01, 0xD0, 0x00, 0x28, 0x0F, 0xD1, 0xA8, 0x20, 0x81, 0x5D, 0x00, 0x29, 0x08, 0xD0, 0x49, 0x1E, 0x81, 0x55, 0x80, 0x5D, 0x00, 0x28, 0x09, 0xD1, 0x38, 0x1C, 0xFF, 0x30, 0x08, 0x30, 0x11, 0xE0, 0x03, 0x21, 0x02, 0x91, 0x00, 0xE0, 0xA8, 0x20, 0x02, 0x99, 0x81, 0x55, 0x38, 0x1C, 0xFF, 0x30, 0x16, 0x30, 0x07, 0xE0, 0x01, 0x98, 0x01, 0x28, 0x02, 0xD1, 0x38, 0x1C, 0xA3, 0x30, 0x01, 0xE0, 0x38, 0x1C, 0x9F, 0x30, 0x00, 0x90, 0xFF, 0xBD, 0x00, 0xB5, 0x02, 0x1C, 0x10, 0x6A, 0xD1, 0x69, 0x52, 0x69, 0xC3, 0x69, 0x5A, 0x60, 0xFF, 0xFF, 0x94, 0x67, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x22, 0x96, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5E, 0x48, 0xFF, 0x30, 0x6E, 0x30, 0x00, 0xBD, 0x10, 0xB5, 0x0A, 0x1C, 0x41, 0x69, 0x00, 0x6A, 0x93, 0x69, 0xDB, 0x69, 0x58, 0x60, 0x90, 0x69, 0x01, 0x24, 0xA6, 0x46, 0x56, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xA6, 0x46, 0x56, 0x48, 0xFE, 0x44 , -0x00, 0x47, 0x55, 0x48, 0xFF, 0x30, 0xB6, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0x6E, 0x69, 0x53, 0x48, 0x02, 0x68, 0x5C, 0x21, 0x88, 0x5D, 0x04, 0x28, 0x15, 0xD1, 0x07, 0x20, 0x88, 0x55, 0x10, 0x0B, 0x11, 0xD2, 0x01, 0x24, 0xA6, 0x46, 0x4E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x0A, 0xD0, 0x47, 0x21, 0x89, 0x57, 0xC1, 0x60, 0x11, 0x21, 0xC9, 0x02, 0x00, 0x22, 0x04, 0x23, 0xA6, 0x46, 0xE8, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x01, 0x20, 0x68, 0x60, 0x43, 0x48, 0xED, 0x49, 0x08, 0x18, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0xAE, 0x69, 0x9C, 0x20, 0x80, 0x19, 0x4B, 0x21, 0x89, 0x00, 0x01, 0x24, 0xFF, 0xFF, 0x2A, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA6, 0x46, 0xE8, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5C, 0x21, 0x88, 0x5D, 0x07, 0x28, 0x01, 0xD1, 0x09, 0x20, 0x00, 0xE0, 0x05, 0x20, 0xAA, 0x69, 0x88, 0x54, 0x30, 0x1C, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x68, 0x60, 0xE8, 0x48 , -0x4D, 0x30, 0x70, 0xBD, 0xF0, 0xB5, 0x41, 0x68, 0x82, 0x68, 0x88, 0x23, 0x5E, 0x18, 0x37, 0x88, 0x0B, 0x6F, 0x00, 0x2B, 0x01, 0xD1, 0x00, 0x2F, 0x10, 0xD1, 0x06, 0x2F, 0x02, 0xDD, 0x00, 0x21, 0xC9, 0x43, 0x07, 0xE0, 0x33, 0x88, 0x9B, 0x00, 0xC9, 0x18, 0x0A, 0x67, 0x31, 0x88, 0x01, 0x31, 0x31, 0x80, 0x01, 0x21, 0x81, 0x60, 0xE1, 0x48, 0x1D, 0x30, 0xF0, 0xBD, 0x0B, 0x1C, 0x01, 0x24, 0x5D, 0x6F, 0x1D, 0x67, 0x04, 0x33, 0x01, 0x34, 0x06, 0x2C, 0xE1, 0xDA, 0xF8, 0xE7, 0x00, 0xB5, 0x00, 0x21, 0xC1, 0x60, 0xE9, 0x48, 0x01, 0x68, 0x10, 0x31, 0xE6, 0x48, 0x20, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE5, 0x48, 0xFB, 0x30, 0x00, 0xBD, 0xFF, 0xFF, 0xC0, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0x54, 0x19, 0x1B, 0x00, 0x91, 0x1A, 0x01, 0x00, 0x4B, 0xAD, 0x03, 0x00, 0x61, 0x4E, 0x01, 0x00, 0x06, 0x32, 0x08, 0x00, 0x1F, 0x0B, 0x02, 0x00, 0x54, 0x3F , -0x08, 0x00, 0x45, 0xC1, 0x00, 0x00, 0x84, 0x3C, 0x08, 0x00, 0x1B, 0x02, 0x00, 0x00, 0xED, 0x17, 0x00, 0x00, 0xF3, 0xC1, 0x01, 0x00, 0x34, 0x19, 0x1B, 0x00, 0x08, 0x19, 0x1B, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xCB, 0x67, 0x03, 0x00, 0x0D, 0x47, 0x02, 0x00, 0x39, 0x42, 0x03, 0x00, 0xBD, 0xE7, 0x02, 0x00, 0xB1, 0x40, 0x03, 0x00, 0xB9, 0xEA, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0x24, 0x41, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0xF0, 0xB5, 0x88, 0xB0, 0x06, 0x91, 0x07, 0x90, 0x86, 0x69, 0xF0, 0x1C, 0xD9, 0xA1, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x14, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x32, 0xD1, 0xF2, 0x79, 0xD7, 0x48, 0x02, 0x70, 0x35, 0x7A, 0x77, 0x7A, 0x78, 0x1B, 0xFF, 0xFF, 0x56, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x43, 0x1C, 0x93, 0x42, 0x1D, 0xD0, 0x16, 0x2A, 0x0C, 0xDB, 0x00, 0x2D, 0x0A, 0xD1, 0xD6, 0x48, 0x04, 0x70, 0x0A, 0x20 , -0x81, 0x19, 0xD0, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x74, 0xE0, 0xD2, 0x48, 0x04, 0x70, 0xCC, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0xB1, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x67, 0xE0, 0x8F, 0xC6, 0x03, 0x00, 0xC9, 0x48, 0x04, 0x70, 0xC9, 0x48, 0x04, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xC2, 0x48, 0xA6, 0x46, 0xAA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x59, 0xE0, 0xF0, 0x1C, 0x03, 0x21, 0x0A, 0x1C, 0xBC, 0xA1, 0xA6, 0x46, 0xC6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x4F, 0xD1, 0xF1, 0x79, 0xBB, 0x48, 0x01, 0x70, 0xBB, 0x4D, 0xB2, 0x79, 0x2A, 0x70, 0x03, 0x20, 0x17, 0x49, 0xF4, 0x31, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x28, 0x78, 0x00, 0x28, 0x0B, 0xD1, 0xFF, 0xE7, 0xB8, 0x49, 0x0C, 0x70, 0xB8, 0x49, 0xFF, 0xFF, 0xEC, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x03, 0x20, 0x0F, 0x49, 0xF5, 0x31, 0xA6, 0x46 , -0xB6, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x20, 0x1C, 0xF2, 0x79, 0x35, 0x7A, 0x77, 0x7A, 0x79, 0x1B, 0x4B, 0x1C, 0x93, 0x42, 0x20, 0xD0, 0xA9, 0x49, 0x09, 0x78, 0x16, 0x29, 0x0F, 0xDB, 0x00, 0x2D, 0x0D, 0xD1, 0xAB, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xE9, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0x8B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x1A, 0xE0, 0xC0, 0x46, 0xC7, 0x04, 0x00, 0x00, 0xA5, 0x49, 0x08, 0x70, 0xE3, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0A, 0xE0, 0x9E, 0x49, 0x08, 0x70, 0x9E, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xDB, 0x48, 0xA6, 0x46, 0x7D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x96, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x06, 0xD0, 0x94, 0x48, 0x00, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x93, 0x48, 0x00, 0x78, 0x00, 0x28, 0xFF, 0xFF, 0x82, 0x6A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , -0x00, 0xD1, 0x8C, 0xE0, 0x03, 0x20, 0x17, 0x21, 0x89, 0x01, 0xA6, 0x46, 0x90, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x87, 0x48, 0x01, 0x78, 0x87, 0x48, 0x07, 0x78, 0x84, 0x4E, 0x83, 0x4D, 0xE0, 0x48, 0x00, 0x68, 0x00, 0x28, 0x2E, 0xD1, 0x07, 0x98, 0x41, 0x61, 0x06, 0x62, 0xC6, 0x48, 0x06, 0x9A, 0x10, 0x64, 0x02, 0x2F, 0x01, 0xD0, 0x03, 0x2F, 0x01, 0xD1, 0x03, 0x22, 0x00, 0xE0, 0x3A, 0x1C, 0x06, 0x9B, 0xDA, 0x63, 0x2A, 0x78, 0x9A, 0x63, 0x01, 0x2F, 0x03, 0xD1, 0x05, 0x29, 0x04, 0xD0, 0x0D, 0x29, 0x02, 0xD0, 0xEC, 0x48, 0xDB, 0x30, 0x64, 0xE0, 0x00, 0x25, 0x00, 0x95, 0x01, 0x91, 0x02, 0x96, 0x03, 0x95, 0x04, 0x90, 0x2B, 0x1C, 0x20, 0x1C, 0x01, 0x1C, 0x8E, 0x46, 0xE6, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0xE6, 0x48, 0x04, 0x60, 0x28, 0x1C, 0xA6, 0x46, 0xE5, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x4C, 0xE0, 0x0D, 0x27, 0x00, 0x20, 0x39, 0x1C, 0x05, 0xAA, 0xA6, 0x46, 0xE3, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x46 , -0xFF, 0xFF, 0x18, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x80, 0x8A, 0x40, 0x08, 0x05, 0xD2, 0x38, 0x1C, 0x50, 0x21, 0xA6, 0x46, 0xDC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x38, 0x1C, 0x21, 0x1C, 0x0B, 0x1C, 0x29, 0x1C, 0x00, 0x22, 0xA6, 0x46, 0xD9, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x2B, 0x78, 0x0D, 0x20, 0x31, 0x1C, 0x22, 0x1C, 0xA6, 0x46, 0xD5, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x28, 0x78, 0x01, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x57, 0x49, 0x23, 0x1C, 0xA6, 0x46, 0xD0, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x55, 0x4E, 0x28, 0x78, 0x02, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x31, 0x1C, 0x23, 0x1C, 0xA6, 0x46, 0xCA, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x30, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x28, 0x78, 0x03, 0x30, 0x02, 0x1C, 0x4C, 0x48, 0x03, 0x78, 0x0D, 0x20, 0x8F, 0x49, 0xA6, 0x46, 0xC3, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xBF, 0x48, 0x04, 0x60, 0x00, 0x20, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xB9, 0x48, 0xEC, 0x49 , -0x08, 0x18, 0x08, 0xB0, 0xF0, 0xBD, 0xC0, 0x46, 0x7B, 0xC0, 0xFF, 0xFF, 0xAE, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x1C, 0xE9, 0x48, 0x02, 0x68, 0xE9, 0x48, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x22, 0x0A, 0x62, 0x8A, 0x61, 0x1D, 0x30, 0xF7, 0x46, 0xD7, 0x30, 0xF7, 0x46, 0xC0, 0x46, 0x9F, 0x03, 0x00, 0x00, 0x7D, 0xB8, 0x03, 0x00, 0x01, 0x1C, 0xE2, 0x48, 0x02, 0x68, 0xE2, 0x48, 0x00, 0x2A, 0x02, 0xD0, 0xFF, 0x30, 0xB4, 0x30, 0xF7, 0x46, 0x00, 0x22, 0xCA, 0x61, 0x8A, 0x61, 0x4F, 0x30, 0xF7, 0x46, 0xC9, 0x21, 0x01, 0x00, 0x91, 0xE1, 0x00, 0x00, 0xDB, 0x48, 0x01, 0x68, 0x8A, 0x69, 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0x88, 0x61, 0x00, 0x20, 0x08, 0x61, 0xD8, 0x48, 0x23, 0x30, 0xF7, 0x46, 0x89, 0x17, 0x02, 0x00, 0x70, 0xB5, 0x05, 0x1C, 0xD5, 0x4E, 0x29, 0x6A, 0xEA, 0x69, 0x30, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x0B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x69, 0xA6, 0x46, 0xD1, 0x49 , -0xFE, 0x44, 0x08, 0x47, 0xA8, 0x69, 0x06, 0x30, 0xA8, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x68, 0x60, 0xEE, 0x60, 0xCE, 0x48, 0xFF, 0xFF, 0x44, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x6D, 0x30, 0x70, 0xBD, 0x46, 0x17, 0x1B, 0x00, 0x30, 0x3F, 0x08, 0x00, 0x41, 0xEB, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x30, 0xB5, 0xEE, 0x48, 0x01, 0x6D, 0x80, 0x6C, 0x08, 0x43, 0x18, 0xD0, 0xEC, 0x49, 0x08, 0x1C, 0x07, 0x22, 0xFF, 0x23, 0x09, 0x33, 0x1B, 0x58, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0x30, 0x1D, 0x30, 0x01, 0x3A, 0xF6, 0xD1, 0x0B, 0xE0, 0x02, 0x20, 0xF0, 0x4A, 0xF1, 0x4B, 0x01, 0x24, 0xA6, 0x46, 0xF0, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xA6, 0x46, 0xEF, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xEF, 0x48, 0xFF, 0x30, 0x5C, 0x30, 0x30, 0xBD, 0xC0, 0x46, 0x53, 0x53, 0x49, 0x44, 0x00, 0xC0, 0x46, 0xC0, 0x4B, 0x45, 0x59, 0x00, 0xEE, 0x62, 0x08, 0x00, 0xF0, 0x62, 0x08, 0x00, 0xEC, 0x62, 0x08, 0x00, 0xED, 0x62, 0x08, 0x00 , -0xE7, 0x7E, 0x03, 0x00, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0xF0, 0xB5, 0xFF, 0xFF, 0xDA, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x87, 0xB0, 0x00, 0x91, 0x01, 0x90, 0x6B, 0x48, 0x01, 0x68, 0xCC, 0x4A, 0x14, 0x1C, 0x02, 0x94, 0x07, 0x26, 0x00, 0x25, 0x03, 0x95, 0x04, 0x94, 0x05, 0x95, 0xDF, 0x48, 0x00, 0x68, 0x08, 0x43, 0x27, 0xD0, 0xE0, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0A, 0xDD, 0x03, 0x90, 0x40, 0x1C, 0x00, 0x99, 0x88, 0x60, 0xC2, 0x49, 0xFF, 0x20, 0x1D, 0x30, 0x68, 0x43, 0x0C, 0x18, 0xE0, 0x68, 0x04, 0x91, 0x02, 0x99, 0xC9, 0x68, 0x88, 0x42, 0x10, 0xDB, 0x88, 0x42, 0x10, 0xD1, 0x02, 0x98, 0x01, 0x27, 0xBE, 0x46, 0xCE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x90, 0x20, 0x1C, 0xBE, 0x46, 0xCB, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x99, 0x88, 0x42, 0x01, 0xDA, 0x05, 0x95, 0x02, 0x94 , -0x51, 0x48, 0x01, 0x68, 0xFF, 0x27, 0x09, 0x37, 0x38, 0x59, 0x00, 0x28, 0x06, 0xD0, 0xC7, 0x48, 0x00, 0x68, 0x07, 0x2E, 0x00, 0xD1, 0x2E, 0x1C, 0x08, 0x43, 0x04, 0xD0, 0xFF, 0x34, 0x1D, 0x34, 0x01, 0x35, 0x07, 0x2D, 0xC2, 0xDB, 0x07, 0x2E, 0xFF, 0xFF, 0x70, 0x6D, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0A, 0xD1, 0xC0, 0x48, 0x00, 0x68, 0x08, 0x43, 0x06, 0xD0, 0x05, 0x9E, 0x30, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0xBA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x98, 0x47, 0x61, 0x00, 0x21, 0x81, 0x61, 0xFF, 0x22, 0x1D, 0x32, 0x72, 0x43, 0x04, 0x99, 0x89, 0x18, 0xC1, 0x61, 0x06, 0x62, 0xB4, 0x48, 0x39, 0x30, 0x07, 0xB0, 0xF0, 0xBD, 0x10, 0xB5, 0x04, 0x1C, 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x40, 0x1E, 0x00, 0xD5, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x61, 0xAE, 0x48, 0x21, 0x30, 0x10, 0xBD, 0xC0, 0x46, 0x10, 0x63, 0x08, 0x00, 0x70, 0xB5, 0x04, 0x1C, 0xE5, 0x69, 0x66, 0x69 , -0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xA7, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x60, 0x60, 0xAB, 0x19, 0xA6, 0x4A, 0xA5, 0x49, 0x93, 0x42, 0x02, 0xD3, 0x9A, 0x1A, 0x82, 0x42, 0x02, 0xD9, 0x08, 0x1C, 0x99, 0x30, 0x70, 0xBD, 0x08, 0x1C, 0xAB, 0x30, 0x70, 0xBD, 0x08, 0x6B, 0x41, 0x7D, 0x02, 0x88, 0x92, 0x00, 0xFF, 0xFF, 0x06, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x51, 0x1A, 0x3C, 0x39, 0xFF, 0x22, 0x5F, 0x32, 0x91, 0x42, 0x03, 0xD9, 0x65, 0x21, 0x01, 0x80, 0x02, 0x21, 0x81, 0x73, 0x9B, 0x48, 0x99, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0xF8, 0xB5, 0x40, 0x68, 0x24, 0x21, 0x41, 0x43, 0x97, 0x48, 0x45, 0x18, 0x28, 0x1D, 0x0C, 0x21, 0x49, 0x19, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x91, 0x4C, 0x00, 0x28, 0x1B, 0xD0, 0x2B, 0x1C, 0x04, 0x22, 0x6E, 0x46, 0x91, 0x49, 0x1F, 0x7B, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33 , -0x01, 0x31, 0x01, 0x36, 0x01, 0x3A, 0xF5, 0xD1, 0x0C, 0x20, 0x41, 0x19, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x87, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x02, 0xD0, 0x20, 0x1C, 0x4A, 0x30, 0xF8, 0xBD, 0x20, 0x1C, 0xF8, 0xBD, 0xB1, 0xBD, 0x00, 0x00, 0x15, 0x95, 0x00, 0x00, 0x58, 0x3F, 0x08, 0x00, 0xF3, 0xF8, 0x00, 0x00, 0xE9, 0x09, 0x02, 0x00, 0xFF, 0xFF, 0x9C, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2B, 0x09, 0x02, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0xF8, 0xB5, 0x05, 0x1C, 0xAA, 0x69, 0x7D, 0x49, 0x00, 0x20, 0x08, 0x56, 0x24, 0x21, 0x41, 0x43, 0x76, 0x48, 0x43, 0x18, 0x04, 0x24, 0x6E, 0x46, 0x76, 0x49, 0x1F, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33, 0x01, 0x31, 0x01, 0x36, 0x01, 0x3C, 0xF5, 0xD1, 0x11, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x6D, 0x48, 0x04, 0xD0, 0x6E, 0x49, 0x09, 0x78 , -0x69, 0x60, 0x45, 0x30, 0xF8, 0xBD, 0xEC, 0x61, 0xAF, 0x30, 0xF8, 0xBD, 0x70, 0xB5, 0xC5, 0x68, 0x81, 0x68, 0x0A, 0x89, 0x6D, 0x4E, 0x00, 0x2A, 0x22, 0xD0, 0x01, 0x24, 0xC2, 0x6D, 0xA2, 0x18, 0xC2, 0x65, 0x08, 0x89, 0x0D, 0x28, 0x1B, 0xD1, 0x68, 0x6B, 0x21, 0x1C, 0xA6, 0x46, 0x63, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x22, 0x1C, 0x28, 0x1C, 0x00, 0x21, 0xA6, 0x46, 0x60, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x2C, 0x60, 0xE9, 0x6B, 0xFF, 0xFF, 0x32, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0x5C, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x1C, 0x3D, 0x30, 0x70, 0xBD, 0x30, 0x1C, 0x23, 0x30, 0x70, 0xBD, 0xC0, 0x46, 0xB1, 0x02, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x19, 0xC6, 0x00, 0x00, 0x5C, 0x3F, 0x08, 0x00, 0x1D, 0xC2, 0x00, 0x00, 0x68, 0x44, 0x08, 0x00, 0x43, 0x12, 0x03, 0x00, 0x34, 0x63, 0x08, 0x00, 0x2F, 0x7A, 0x02, 0x00 , -0xB4, 0x36, 0x08, 0x00, 0x8F, 0xF4, 0x01, 0x00, 0xF0, 0xB5, 0x05, 0x1C, 0xAB, 0x69, 0xEC, 0x69, 0x60, 0x68, 0x00, 0x68, 0x2A, 0x30, 0x01, 0x78, 0x0A, 0x06, 0x41, 0x78, 0x09, 0x04, 0x8A, 0x18, 0x81, 0x78, 0x09, 0x02, 0x8A, 0x18, 0xC1, 0x78, 0x8A, 0x18, 0x8E, 0x26, 0xF1, 0x5A, 0x09, 0x0A, 0x01, 0x70, 0xF0, 0x5C, 0x61, 0x68, 0x09, 0x68, 0x2B, 0x26, 0x70, 0x54, 0x8C, 0x20, 0xC0, 0x18, 0x61, 0x68, 0x0E, 0x68, 0x01, 0x88, 0x09, 0x0A, 0x2C, 0x27, 0xB9, 0x55, 0x61, 0x68, 0x09, 0x68, 0xFF, 0xFF, 0xC8, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2D, 0x26, 0x00, 0x78, 0x70, 0x54, 0x60, 0x68, 0x01, 0x68, 0x32, 0x31, 0x08, 0x78, 0x00, 0x02, 0x49, 0x78, 0x08, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x8C, 0x21, 0xCB, 0x58, 0x35, 0x49, 0x41, 0x40, 0x08, 0x04, 0x00, 0x0C, 0xC0, 0x18, 0x80, 0x1A, 0x01, 0x21, 0x8E, 0x46, 0x32, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x61, 0x68, 0x0A, 0x68, 0x32, 0x23, 0x01, 0x0A, 0x99, 0x54 , -0x61, 0x68, 0x09, 0x68, 0x33, 0x22, 0x50, 0x54, 0x60, 0x68, 0x68, 0x60, 0x2C, 0x48, 0xF0, 0xBD, 0x00, 0x00, 0x1B, 0x00, 0x34, 0x04, 0x1B, 0x00, 0x02, 0x6A, 0x8B, 0x69, 0xDB, 0x69, 0x1B, 0x68, 0x83, 0x60, 0x88, 0x69, 0xC0, 0x69, 0x41, 0x68, 0x8A, 0x42, 0x00, 0xDA, 0x42, 0x60, 0x25, 0x48, 0x79, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x57, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x91, 0x30, 0xF7, 0x46, 0x32, 0x04, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x15, 0x09, 0x02, 0x00, 0xC5, 0x93, 0x00, 0x00, 0x0D, 0x91, 0x00, 0x00, 0x40, 0x1E, 0x80, 0x00, 0x1E, 0x4B, 0xFF, 0xFF, 0x5E, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x19, 0x50, 0x1C, 0x49, 0x0A, 0x50, 0xF7, 0x46, 0xC0, 0x46, 0xBD, 0xB5, 0x00, 0x00, 0x95, 0x92, 0x00, 0x00, 0xFD, 0x93, 0x00, 0x00, 0x54, 0x3F, 0x08, 0x00, 0x29, 0x4F, 0x03, 0x00, 0xDF, 0xE8, 0x02, 0x00, 0x36, 0x89, 0x41, 0x00, 0x81, 0x06, 0x00, 0x00, 0xB1, 0x78, 0x00, 0x00, 0x94, 0xEC, 0x01, 0x00 , -0x08, 0x19, 0x1B, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x67, 0x66, 0x03, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xA7, 0x2F, 0x02, 0x00, 0x91, 0x44, 0x03, 0x00, 0x91, 0x63, 0x03, 0x00, 0x5B, 0x44, 0x03, 0x00, 0xE7, 0x44, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xA2, 0x03, 0x00, 0x6A, 0x1E, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0xD7, 0xE8, 0x01, 0x00, 0xE9, 0x78, 0x02, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x7B, 0x08, 0x00, 0xFC, 0xB5, 0x04, 0x1C, 0xA5, 0x69, 0x60, 0x6A, 0x01, 0x90, 0x20, 0x69, 0x00, 0x28, 0x35, 0xD4, 0x08, 0x28, 0x33, 0xDA, 0xE1, 0x69, 0x09, 0x68, 0xFF, 0xFF, 0xF4, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x2F, 0xD1, 0xAC, 0x21, 0x41, 0x43, 0x9E, 0x4A, 0x51, 0x5C, 0x49, 0x08, 0x27, 0xD3, 0x00, 0x06, 0x00, 0x16, 0xA2, 0x68, 0x69, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x39, 0x30, 0x1F, 0xD0 , -0x00, 0x2E, 0x1D, 0xD0, 0x00, 0x98, 0x07, 0x68, 0x00, 0x99, 0x0C, 0x39, 0x01, 0x98, 0x01, 0x60, 0x28, 0x1D, 0x10, 0x21, 0x79, 0x1A, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x91, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x22, 0x2A, 0x80, 0xA8, 0x1C, 0x08, 0x21, 0x79, 0x1A, 0x01, 0x23, 0x9E, 0x46, 0x8C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x03, 0xE0, 0x38, 0x20, 0x00, 0xE0, 0x00, 0x20, 0xC6, 0x43, 0x26, 0x60, 0x89, 0x48, 0x7C, 0x30, 0x20, 0x62, 0xFC, 0xBD, 0x30, 0xB5, 0x05, 0x1C, 0x28, 0x69, 0xA9, 0x69, 0x90, 0x29, 0x1D, 0xD1, 0x69, 0x69, 0x09, 0x78, 0x04, 0x29, 0x19, 0xD0, 0x05, 0x29, 0x17, 0xD0, 0x0A, 0x29, 0x15, 0xD0, 0x06, 0x29, 0x13, 0xD0, 0x0C, 0x29, 0x01, 0xDB, 0xFF, 0xFF, 0x8A, 0x71, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x0F, 0xD1, 0x01, 0x24, 0xA6, 0x46, 0x7D, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x7C, 0x48, 0x7D, 0x49, 0x00, 0x22, 0xA6, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x7C, 0x48 , -0xFF, 0x30, 0x5F, 0x30, 0x28, 0x62, 0x30, 0xBD, 0xF0, 0xB5, 0x89, 0xB0, 0x05, 0x90, 0x41, 0x69, 0x02, 0x69, 0x75, 0x48, 0x79, 0x4E, 0x82, 0x42, 0x3A, 0xD0, 0x04, 0x30, 0x82, 0x42, 0x25, 0xD0, 0x74, 0x4D, 0xAA, 0x42, 0x00, 0xD0, 0xCC, 0xE0, 0x08, 0x68, 0x06, 0x1C, 0x0C, 0x22, 0x8F, 0x1A, 0x4A, 0x68, 0x89, 0x18, 0x09, 0x1D, 0x10, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x09, 0xD1, 0xAC, 0x22, 0x72, 0x43, 0xCB, 0x48, 0x80, 0x18, 0x46, 0x22, 0x12, 0x5C, 0x11, 0x2A, 0x01, 0xD1, 0x44, 0x22, 0x14, 0x54, 0x28, 0x1C, 0x3A, 0x1C, 0xA6, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x69, 0x48, 0xEC, 0x30, 0xAB, 0xE0, 0x08, 0x68, 0xC0, 0x00, 0x30, 0x18, 0x8A, 0x68, 0x02, 0x2A, 0x02, 0xD0, 0xFF, 0xFF, 0x20, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xE7, 0x20, 0x80, 0x00, 0xA2, 0xE0, 0xCA, 0x68, 0x89, 0x18, 0x09, 0x7B, 0x41, 0x60, 0x80, 0x21, 0x01, 0x60, 0x3B, 0x20 , -0x00, 0x01, 0x99, 0xE0, 0x08, 0x68, 0x06, 0x90, 0xC0, 0x00, 0x34, 0x58, 0x10, 0x20, 0x04, 0x90, 0x01, 0x25, 0xAE, 0x46, 0x57, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x07, 0x90, 0x00, 0x28, 0x00, 0xD1, 0x89, 0xE0, 0x0C, 0x21, 0x07, 0x98, 0x0F, 0x18, 0xB0, 0x49, 0xAC, 0x20, 0x06, 0x9A, 0x50, 0x43, 0x08, 0x18, 0x48, 0x22, 0x13, 0x5C, 0x5B, 0x06, 0x5B, 0x0E, 0x13, 0x54, 0x06, 0x9A, 0xD2, 0x00, 0xB6, 0x18, 0x71, 0x68, 0x00, 0x29, 0x47, 0xD1, 0x00, 0x2C, 0x01, 0xDD, 0x08, 0x2C, 0x21, 0xDB, 0x00, 0x22, 0x69, 0x46, 0x0A, 0x70, 0x01, 0x92, 0x0A, 0x81, 0x8A, 0x72, 0xCD, 0x72, 0x0D, 0x73, 0x4D, 0x73, 0x01, 0x88, 0x44, 0x48, 0x06, 0x23, 0xAE, 0x46, 0x44, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x04, 0x1C, 0x02, 0xDC, 0x00, 0x20, 0xC0, 0x43, 0x36, 0xE0, 0x34, 0x60, 0xAC, 0x20, 0x60, 0x43, 0x9A, 0x49, 0xFF, 0xFF, 0xB6, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x18, 0x5C, 0x22, 0x28, 0x1C, 0x50, 0x54, 0x48, 0x20 , -0x42, 0x5C, 0x52, 0x06, 0x52, 0x0E, 0x42, 0x54, 0xAC, 0x20, 0x60, 0x43, 0x94, 0x49, 0x08, 0x18, 0x5C, 0x21, 0x09, 0x5C, 0x49, 0x1E, 0x02, 0x29, 0x16, 0xD9, 0x03, 0x39, 0x08, 0xD0, 0x00, 0x20, 0x30, 0x56, 0xAE, 0x46, 0xEA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x80, 0x20, 0x30, 0x60, 0xDB, 0xE7, 0x08, 0x94, 0x80, 0x21, 0x31, 0x60, 0x48, 0x22, 0x13, 0x5C, 0x19, 0x43, 0x11, 0x54, 0xAE, 0x46, 0xE4, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0xE0, 0x01, 0x20, 0xCE, 0xE7, 0x06, 0x98, 0x39, 0x1C, 0x04, 0xAA, 0xAE, 0x46, 0xE0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x1C, 0x08, 0x90, 0x06, 0x98, 0x38, 0x60, 0x08, 0x98, 0x78, 0x60, 0x00, 0x28, 0x15, 0xD0, 0xAC, 0x20, 0x60, 0x43, 0x7C, 0x49, 0x09, 0x18, 0x48, 0x88, 0x02, 0x04, 0x02, 0x20, 0x10, 0x43, 0xB8, 0x60, 0x48, 0x68, 0x02, 0x0E, 0x01, 0x02, 0x09, 0x0E, 0x09, 0x02, 0x11, 0x43, 0x02, 0x04, 0x12, 0x0E, 0xFF, 0xFF, 0x4C, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 , -0x12, 0x04, 0x0A, 0x43, 0x00, 0x06, 0x10, 0x43, 0xF8, 0x60, 0x07, 0x98, 0x0D, 0x49, 0x00, 0x22, 0x10, 0x23, 0xAE, 0x46, 0xCE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x13, 0x48, 0x00, 0xE0, 0x16, 0x20, 0xCC, 0x49, 0x09, 0x18, 0x05, 0x98, 0x01, 0x62, 0x09, 0xB0, 0xF0, 0xBD, 0x5D, 0x0D, 0x1B, 0x00, 0x81, 0xE7, 0x02, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x27, 0x1A, 0x02, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0xD5, 0xF4, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x91, 0x19, 0x02, 0x00, 0x50, 0x65, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0x50, 0x19, 0x1B, 0x00, 0x29, 0x16, 0x01, 0x00, 0x2A, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0x8B, 0xB0, 0x07, 0x90, 0x05, 0x69, 0x47, 0x69, 0x0C, 0x20, 0x38, 0x1A, 0x08, 0x90, 0xB6, 0x49, 0x8D, 0x42, 0x16, 0xD1, 0x78, 0x68, 0x0F, 0x30, 0x00, 0x11, 0x00, 0x01, 0x78, 0x60, 0x38, 0x68, 0x0B, 0x28, 0x0E, 0xD8, 0x00, 0x23, 0x68, 0x46 , -0xFF, 0xFF, 0xE2, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x03, 0x70, 0x08, 0x98, 0x05, 0x22, 0x01, 0x24, 0xA6, 0x46, 0xAE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0xAE, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xAC, 0x48, 0x85, 0x42, 0x23, 0xD1, 0xAC, 0x48, 0x02, 0x78, 0x6C, 0x46, 0x22, 0x72, 0x43, 0x78, 0x63, 0x72, 0x81, 0x78, 0xA1, 0x72, 0xC0, 0x78, 0xE0, 0x72, 0x00, 0x91, 0x01, 0x90, 0x03, 0x20, 0xA6, 0x49, 0x01, 0x39, 0x01, 0x26, 0xB6, 0x46, 0xF3, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x04, 0x20, 0x20, 0x70, 0x08, 0x98, 0x9F, 0x49, 0x00, 0x22, 0x02, 0xAB, 0x01, 0x24, 0xA6, 0x46, 0x9B, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x9A, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xEB, 0x49, 0x8D, 0x42, 0x14, 0xD1, 0x02, 0x22, 0x68, 0x46, 0x02, 0x70, 0x3A, 0x68, 0xAC, 0x20, 0x42, 0x43, 0x30, 0x48, 0x68, 0x30, 0x83, 0x18, 0x08, 0x98, 0x00, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x8F, 0x4C, 0xFE, 0x44 , -0x20, 0x47, 0x8E, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0xFF, 0xFF, 0x78, 0x74, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x08, 0x62, 0xEF, 0x48, 0x85, 0x42, 0x00, 0xD0, 0x04, 0xE1, 0x03, 0x20, 0x8C, 0x49, 0x01, 0x22, 0x96, 0x46, 0xEC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x86, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x09, 0x90, 0x38, 0x68, 0xEA, 0x4D, 0x00, 0x28, 0x00, 0xD1, 0xE2, 0xE0, 0x01, 0x24, 0xA6, 0x46, 0xE6, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x00, 0xD1, 0xD6, 0xE0, 0xE4, 0x48, 0x02, 0x68, 0x03, 0x20, 0x7F, 0x49, 0x01, 0x31, 0xA6, 0x46, 0xE2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xDF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x5A, 0xD1, 0xDF, 0x4D, 0x2E, 0x20, 0x41, 0x19, 0xB8, 0x68, 0x03, 0x30, 0x08, 0x70, 0x38, 0x7A, 0x48, 0x70, 0x2E, 0x1C, 0x30, 0x36, 0xB8, 0x68, 0x28, 0x18, 0x30, 0x30, 0xDA, 0x49, 0x0A, 0x68, 0x30, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xD8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18 , -0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xD9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x41, 0x19, 0x97, 0x22, 0xFF, 0xFF, 0x0E, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x30, 0x50, 0x54, 0xB8, 0x68, 0x46, 0x19, 0x9E, 0x36, 0x30, 0x70, 0x01, 0x36, 0xB8, 0x68, 0x01, 0xE0, 0x14, 0x0D, 0x1B, 0x00, 0x30, 0x18, 0xCA, 0x49, 0x0A, 0x68, 0x9E, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xC8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18, 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xC9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x40, 0x00, 0xC0, 0x49, 0x09, 0x68, 0x08, 0x18, 0x28, 0x18, 0xC0, 0x49, 0x0A, 0x79, 0x02, 0x70, 0x4A, 0x79, 0x42, 0x70, 0x8A, 0x79, 0x82, 0x70, 0xC9, 0x79, 0xC1, 0x70, 0x04, 0x30, 0x0F, 0x21, 0x41, 0x1A, 0x0A, 0x78, 0xBB, 0x68, 0x9A, 0x18, 0x0A, 0x70, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x0C, 0xB5, 0x49, 0x08, 0x60, 0xB1, 0x48, 0x04, 0x60, 0x02, 0x20, 0x01, 0x1C , -0x11, 0x22, 0xA6, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x63, 0xD4, 0x03, 0x20, 0xA6, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0x90, 0x00, 0x25, 0x01, 0x1C, 0xFF, 0xFF, 0xA4, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8D, 0x42, 0x50, 0xD0, 0x29, 0x1C, 0x2B, 0x22, 0xA6, 0x46, 0xAD, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0C, 0x20, 0x0A, 0x99, 0x40, 0x18, 0xAC, 0x22, 0x72, 0x43, 0xAB, 0x49, 0x8F, 0x18, 0x78, 0x63, 0x29, 0x1C, 0x18, 0x22, 0xA6, 0x46, 0xA6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x9F, 0x48, 0x02, 0x68, 0x79, 0x6B, 0x4A, 0x60, 0x0A, 0x98, 0xAC, 0x30, 0x08, 0x60, 0x08, 0x68, 0x9A, 0x49, 0xA6, 0x46, 0xA0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x29, 0x1C, 0x03, 0xA8, 0x10, 0x22, 0xA6, 0x46, 0x9C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE0, 0x21, 0x68, 0x46, 0x01, 0x74, 0x45, 0x74, 0x85, 0x74, 0xFB, 0x21, 0xC1, 0x74, 0xEE, 0x49, 0xC1, 0x81, 0x02, 0x21, 0x81, 0x81, 0x79, 0x6B, 0xCA, 0x68 , -0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0xC8, 0x60, 0x48, 0x68, 0x00, 0x90, 0x2A, 0x1C, 0x30, 0x1C, 0x0A, 0x9D, 0x29, 0x1C, 0x03, 0xAB, 0xA6, 0x46, 0xE6, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x07, 0x1C, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xEF, 0x49, 0xFF, 0xFF, 0x3A, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xFE, 0x44, 0x08, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0xEE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x11, 0xE0, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x20, 0xC7, 0x43, 0x08, 0xE0, 0x07, 0x1C, 0x06, 0xE0, 0x00, 0x20, 0x00, 0x21, 0xCF, 0x43, 0x01, 0xE0, 0x00, 0x20, 0x07, 0x1C, 0x28, 0x60, 0x00, 0x23, 0x68, 0x46, 0x03, 0x70, 0x3A, 0x06, 0x12, 0x0E, 0x08, 0x98, 0x6F, 0x49, 0x01, 0x24, 0xA6, 0x46, 0x09, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x07, 0x98, 0x09, 0x99, 0x01, 0x62, 0x0B, 0xB0, 0xF0, 0xBD, 0xC1, 0x18, 0x01, 0x00, 0xF1, 0x1B, 0x01, 0x00, 0xF3, 0x1C, 0x02, 0x00, 0x7B, 0xC0 , -0x02, 0x00, 0x91, 0xF0, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0xA3, 0xC0, 0x02, 0x00, 0xA9, 0xE9, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xAC, 0x05, 0x00, 0x00, 0xFE, 0xB5, 0x07, 0x1C, 0x7D, 0x69, 0xBE, 0x69, 0x0C, 0x20, 0x30, 0x1A, 0x01, 0x90, 0xDF, 0x4C, 0x0A, 0x2D, 0x13, 0xD1, 0xFF, 0xFF, 0xD0, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0x68, 0xDB, 0x49, 0x08, 0x60, 0x01, 0x20, 0x86, 0x46, 0xDA, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x0A, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xE6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x38, 0x62, 0x03, 0x2D, 0x79, 0xD1, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x02, 0x90, 0x70, 0x68, 0x00, 0x28, 0x0C, 0xD1, 0x00, 0x21, 0xCF, 0x48, 0x01, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x61, 0xD0, 0x01, 0x21, 0x8E, 0x46, 0xCD, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x5B, 0xE0, 0xCC, 0x48, 0xB1, 0x68, 0x01, 0x60 , -0xF1, 0x68, 0x41, 0x60, 0x31, 0x69, 0x81, 0x60, 0x71, 0x69, 0xC1, 0x60, 0xB1, 0x69, 0xC1, 0x63, 0xF1, 0x69, 0x01, 0x64, 0x31, 0x6A, 0xC1, 0x64, 0x01, 0x24, 0xA6, 0x46, 0xC5, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xA6, 0x46, 0xC4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x70, 0x68, 0x7D, 0x25, 0xED, 0x00, 0xA8, 0x42, 0x21, 0xD8, 0x01, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xFF, 0xFF, 0x66, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x1C, 0xE0, 0xB9, 0x48, 0x00, 0x23, 0x19, 0x1C, 0x59, 0x43, 0x3E, 0x22, 0x4A, 0x43, 0x82, 0x83, 0x02, 0x30, 0x01, 0x33, 0x10, 0x2B, 0xF6, 0xDB, 0xA6, 0x46, 0xB4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xB5, 0x48, 0x0D, 0xE0, 0xB5, 0x4D, 0x28, 0x1C, 0xA6, 0x46, 0xB2, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x04, 0xE0, 0xA6, 0x46, 0xAF, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x75, 0x68, 0xAE, 0x48, 0x05, 0x60, 0x05, 0x1C, 0xA7, 0x4E, 0x30, 0x68 , -0x00, 0x28, 0x06, 0xD1, 0xAD, 0x48, 0x00, 0x68, 0xA6, 0x46, 0xAC, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x60, 0x00, 0x94, 0x2B, 0x68, 0xAA, 0x49, 0xAB, 0x4A, 0xA6, 0x46, 0xAB, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0x9C, 0x48, 0x04, 0x60, 0x03, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xA7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x38, 0x62, 0xFE, 0xBD, 0xC0, 0x46, 0x13, 0x7F, 0x03, 0x00, 0x12, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x00, 0x20, 0x01, 0x24, 0xA6, 0x46, 0xA0, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9F, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x7D, 0x21, 0xC9, 0x00, 0xA6, 0x46, 0x9E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x9B, 0x49, 0x08, 0x18, 0x99, 0x49, 0x08, 0x80, 0x9B, 0x48, 0x0A, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x11, 0x10, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xB9, 0x90 , -0x00, 0x00, 0x6C, 0x64, 0x08, 0x00, 0xE7, 0x7E, 0x03, 0x00, 0x74, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0x6D, 0xC6, 0x03, 0x00, 0x08, 0x19, 0x1B, 0x00, 0x11, 0x18, 0x02, 0x00, 0xD1, 0x78, 0x02, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0xFE, 0xB5, 0x02, 0x90, 0x45, 0x69, 0x68, 0x46, 0x01, 0x21, 0x8E, 0x46, 0x89, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x89, 0x48, 0x04, 0x1C, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x00, 0x27, 0x3E, 0x1C, 0x20, 0x88, 0xFF, 0xFF, 0x92, 0x78, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x40, 0x08, 0x22, 0xD3, 0x20, 0x1D, 0x89, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x07, 0xD1, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x21, 0x88, 0x09, 0x04, 0x89, 0x16, 0x81, 0x42, 0x3D, 0xD0, 0x02, 0x20, 0x00, 0x5F, 0x00, 0x99, 0x08, 0x1A, 0x00, 0x04, 0x00, 0x14, 0x3C, 0x28, 0x03, 0xDD, 0x20, 0x88, 0x40, 0x10, 0x40, 0x00 , -0x20, 0x80, 0x78, 0x1C, 0x07, 0x06, 0x3F, 0x0E, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x2A, 0x34, 0x01, 0x36, 0x14, 0x2E, 0xD5, 0xDB, 0x00, 0x2A, 0x02, 0xD1, 0xAB, 0x20, 0x40, 0x00, 0x50, 0xE0, 0x00, 0x9B, 0x6D, 0x48, 0x14, 0x21, 0x00, 0x22, 0x04, 0x88, 0x64, 0x08, 0x03, 0xD3, 0x2A, 0x30, 0x01, 0x32, 0x01, 0x39, 0xF8, 0xD1, 0x12, 0x06, 0x12, 0x0E, 0x14, 0x2F, 0x16, 0xD1, 0x66, 0x48, 0x00, 0x88, 0x00, 0x06, 0x44, 0x16, 0x64, 0x49, 0x00, 0x22, 0x01, 0x20, 0x4E, 0x8D, 0x36, 0x06, 0x76, 0x16, 0xA6, 0x42, 0x02, 0xDD, 0x34, 0x1C, 0x02, 0x06, 0xFF, 0xFF, 0x28, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x2A, 0x31, 0x01, 0x30, 0x14, 0x28, 0xF3, 0xDB, 0x02, 0xE0, 0x32, 0x06, 0x12, 0x0E, 0x00, 0x9B, 0x2A, 0x20, 0x42, 0x43, 0x5A, 0x48, 0x11, 0x18, 0x0C, 0x88, 0x01, 0x20, 0x20, 0x43, 0x00, 0x04, 0x00, 0x0C, 0x08, 0x80, 0xFE, 0x24, 0xA0, 0x43, 0x14, 0x24, 0x64, 0x57, 0x64, 0x06, 0x24, 0x0E , -0x04, 0x43, 0x52, 0x48, 0x14, 0x52, 0x14, 0x18, 0x63, 0x80, 0x08, 0x88, 0x80, 0x05, 0x82, 0x0D, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x80, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x68, 0x02, 0x69, 0x20, 0x1D, 0x91, 0x1C, 0x52, 0x78, 0x01, 0x23, 0x9E, 0x46, 0x4B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x04, 0x61, 0xFE, 0x20, 0x47, 0x49, 0x09, 0x18, 0x02, 0x98, 0x01, 0x62, 0xFE, 0xBD, 0x82, 0x69, 0x41, 0x69, 0x03, 0x69, 0x02, 0x2B, 0x0A, 0xD1, 0x01, 0x2A, 0x01, 0xD1, 0x00, 0x29, 0x05, 0xD0, 0x02, 0x2A, 0x04, 0xD1, 0x00, 0x29, 0x02, 0xD1, 0x11, 0x21, 0x00, 0xE0, 0x06, 0x21, 0x41, 0x61, 0xF7, 0x46, 0xFF, 0xFF, 0xBE, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xC0, 0x46, 0x14, 0xE9, 0x00, 0x00, 0xC9, 0x18, 0x02, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x3A, 0x48, 0x00, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x01, 0x20, 0x86, 0x46, 0x38, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x01, 0x24, 0xA6, 0x46, 0x37, 0x48, 0xFE, 0x44 , -0x00, 0x47, 0xA6, 0x46, 0x36, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x35, 0x48, 0x0E, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x49, 0x19, 0x01, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x18, 0xB5, 0x43, 0x69, 0x81, 0x69, 0x31, 0x48, 0x81, 0x29, 0x00, 0xD1, 0x0B, 0x38, 0x00, 0x21, 0x00, 0x91, 0x1A, 0x68, 0x9B, 0x68, 0x01, 0x24, 0xA6, 0x46, 0x2D, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0x18, 0xB5, 0x40, 0x69, 0x00, 0x21, 0x00, 0x91, 0x02, 0x68, 0x83, 0x68, 0x27, 0x48, 0x01, 0x30, 0x01, 0x24, 0xA6, 0x46, 0x26, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0x19, 0x9E, 0x00, 0x00, 0xB9, 0xEC, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x80, 0x3F, 0x08, 0x00, 0xFF, 0xFF, 0x54, 0x7A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB7, 0x5D, 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0xD3, 0x8E, 0x00, 0x00, 0xF7, 0xC6, 0x00, 0x00, 0xE5, 0x90, 0x00, 0x00, 0x68, 0x64, 0x08, 0x00, 0xC0, 0x27, 0x09, 0x00, 0xA0, 0x3B , -0x08, 0x00, 0x3D, 0x5D, 0x03, 0x00, 0x19, 0xC6, 0x00, 0x00, 0xE8, 0x3A, 0x08, 0x00, 0x81, 0x5D, 0x03, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0x4B, 0x4F, 0x03, 0x00, 0x6B, 0xC0, 0x03, 0x00, 0x95, 0x1E, 0x01, 0x00, 0xDA, 0x40, 0x08, 0x00, 0xDC, 0x05, 0x00, 0x00, 0x55, 0xAA, 0x03, 0x00, 0x0D, 0x91, 0x00, 0x00, 0xD7, 0x56, 0x03, 0x00, 0x08, 0x51, 0x08, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x65, 0xB8, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x84, 0x17, 0x1B, 0x00, 0xB5, 0x86, 0x01, 0x00, 0x3D, 0x47, 0x02, 0x00, 0x73, 0x49, 0x02, 0x00, 0x5F, 0x90, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, 0xF7, 0xF6, 0x00, 0x00, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x76, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0xFF, 0xFF, 0xEA, 0x7A, 0x08, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5 , -0x68, 0x46, 0xFF, 0xF7, 0xB6, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x55, 0xFC, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x27, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xDD, 0xFA, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x68, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x3D, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xBE, 0xFD, 0xFF, 0xBD, 0x78, 0x7B, 0x08, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xF8, 0xF0, 0x43, 0xFA, 0x00, 0xBD, 0x35, 0x66, 0x08, 0x00, 0x67, 0x66, 0x08, 0x00, 0x71, 0x65, 0x08, 0x00, 0x4D, 0x66, 0x08, 0x00, 0x25, 0x64, 0x08, 0x00, 0x81, 0x66, 0x08, 0x00, 0x8D, 0x66, 0x08, 0x00, 0x99, 0x66, 0x08, 0x00, 0x87, 0x67, 0x08, 0x00, 0xA7, 0x67, 0x08, 0x00, 0xD1, 0x67, 0x08, 0x00, 0x1B, 0x68, 0x08, 0x00, 0x57, 0x68, 0x08, 0x00, 0x2D, 0x69, 0x08, 0x00, 0xB1, 0x6B, 0x08, 0x00, 0xD5, 0x6B, 0x08, 0x00, 0xF9, 0x6B , -0x08, 0x00, 0x15, 0x6C, 0x08, 0x00, 0xA1, 0x68, 0x08, 0x00, 0x59, 0x6C, 0x08, 0x00, 0xA7, 0x6D, 0x08, 0x00, 0xFF, 0x6D, 0x08, 0x00, 0x29, 0x6E, 0x08, 0x00, 0xF9, 0x6E, 0x08, 0x00, 0xD9, 0x6C, 0x08, 0x00, 0xA5, 0x6E, 0x08, 0x00, 0xCD, 0x6D, 0x08, 0x00, 0x81, 0x6F, 0x08, 0x00, 0x1D, 0x70, 0x08, 0x00, 0x31, 0x64, 0x08, 0x00, 0x39, 0x70, 0x08, 0x00, 0x3F, 0x70, 0x08, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x00, 0xB2, 0x4E, 0x01, 0x00, 0x5A, 0xC1, 0x00, 0x00, 0x96, 0x1A, 0x01, 0x00, 0x22, 0x0B, 0x02, 0x00, 0x60, 0xD0, 0x01, 0x00, 0x06, 0x1A, 0x00, 0x00, 0xB8, 0xC6, 0x01, 0x00, 0xD8, 0x42, 0x03, 0x00, 0x16, 0x42, 0x03, 0x00, 0xEE, 0xDB, 0x00, 0x00, 0x62, 0xDC, 0x00, 0x00, 0xC8, 0xE1, 0x00, 0x00, 0x8A, 0x17, 0x02, 0x00, 0x38, 0xBE, 0x00, 0x00, 0x26, 0xC6, 0x00, 0x00, 0x56, 0xC2, 0x00, 0x00, 0x62, 0x12, 0x03, 0x00, 0xE4, 0xF4, 0x01, 0x00, 0x3A, 0xEC, 0x00, 0x00, 0x5E, 0x92, 0x00, 0x00 , -0xFE, 0xE8, 0x02, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x64, 0xEC, 0x01, 0x00, 0xFE, 0x44, 0x03, 0x00, 0x1C, 0x94, 0x00, 0x00, 0xA8, 0x66, 0x03, 0x00, 0x74, 0xE9, 0x02, 0x00, 0x68, 0x1E, 0x01, 0x00, 0xBC, 0xDA, 0x00, 0x00, 0xEA, 0xE1, 0x00, 0x00, 0x24, 0xE9, 0x01, 0x00, 0x70, 0x79, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x1C, 0xF0, 0xB5, 0x88, 0xB0, 0xCA, 0x4C, 0x03, 0x20, 0x22, 0x78, 0x63, 0x78, 0xCA, 0x4E, 0x31, 0x1C, 0x01, 0x39, 0x01, 0x25, 0xAE, 0x46, 0xC7, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0xA2, 0x78, 0xE3, 0x78, 0x03, 0x20, 0x31, 0x1C, 0xAE, 0x46, 0xC3, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x03, 0x20, 0x31, 0x1C, 0x01, 0x31, 0xAE, 0x46, 0xC1, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xC1, 0x48, 0x21, 0x78, 0x01, 0x70, 0x61, 0x78, 0x41, 0x70, 0xE1, 0x78, 0xC1, 0x70, 0xA1, 0x78, 0x81, 0x70, 0xBF, 0x48, 0x04, 0x1C, 0x33, 0x3C, 0x20, 0x1C, 0x00, 0x21, 0xDC, 0x22, 0xAE, 0x46 , -0xBA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x84, 0x20, 0xA0, 0x70, 0x05, 0x27, 0xE7, 0x71, 0x0C, 0x26, 0x26, 0x73, 0x0D, 0x20, 0x00, 0x19, 0x98, 0xA1, 0x32, 0x1C, 0xAE, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20, 0x60, 0x76, 0x1A, 0x20, 0x00, 0x19, 0x97, 0xA1, 0x06, 0x91, 0x04, 0x22, 0xAE, 0x46, 0xAE, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xFF, 0xFF, 0x96, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA7, 0x77, 0x1F, 0x34, 0x95, 0xA1, 0x07, 0x91, 0x20, 0x1C, 0x3A, 0x1C, 0xAE, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x28, 0x1C, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0xC0, 0x25, 0x65, 0x74, 0xA6, 0x74, 0x09, 0x22, 0xE2, 0x74, 0xA3, 0x4C, 0x20, 0x1C, 0x8C, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9F, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x07, 0x22, 0x62, 0x72, 0x9E, 0x4C, 0x0A, 0x34, 0x20, 0x1C, 0x89, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20 , -0xE0, 0x71, 0x98, 0x4C, 0x12, 0x34, 0x20, 0x1C, 0x06, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x27, 0x71, 0x93, 0x4C, 0x17, 0x34, 0x20, 0x1C, 0x07, 0x99, 0x3A, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x8E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x01, 0x20, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0x02, 0x20, 0xE0, 0x73, 0x25, 0x74, 0x66, 0x74, 0xFF, 0xFF, 0x2C, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA5, 0x74, 0x2F, 0x27, 0xE7, 0x74, 0x10, 0x20, 0x60, 0x75, 0x80, 0x26, 0xA6, 0x75, 0x01, 0x20, 0xE0, 0x75, 0x11, 0x20, 0xA0, 0x76, 0x94, 0x20, 0xE0, 0x76, 0x24, 0x20, 0x60, 0x77, 0x0A, 0x22, 0xA2, 0x77, 0x80, 0x4C, 0x36, 0x34, 0x20, 0x1C, 0x6D, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x18, 0x22, 0xA2, 0x72, 0x7A, 0x4C, 0x41, 0x34, 0x20, 0x1C, 0x6B, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x76, 0x4B, 0xFE, 0x44, 0x18, 0x47 , -0x25, 0x76, 0x67, 0x76, 0x21, 0x20, 0xE0, 0x76, 0x26, 0x77, 0x01, 0x20, 0x60, 0x77, 0x72, 0x48, 0x61, 0x30, 0x11, 0x21, 0x01, 0x70, 0x94, 0x21, 0x41, 0x70, 0x04, 0x21, 0x01, 0x72, 0xD2, 0x21, 0x41, 0x72, 0xC5, 0x72, 0x1E, 0x21, 0x01, 0x73, 0x45, 0x73, 0x9E, 0x21, 0x81, 0x73, 0x01, 0x21, 0x01, 0x74, 0x46, 0x74, 0x81, 0x74, 0x11, 0x21, 0x41, 0x75, 0x94, 0x21, 0x81, 0x75, 0x04, 0x21, 0x01, 0x76, 0xAD, 0x20, 0x66, 0x49, 0x08, 0x60, 0x00, 0x24, 0x0F, 0x25, 0xFF, 0xFF, 0xC2, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x29, 0x06, 0x09, 0x0E, 0x00, 0x20, 0x6A, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x6B, 0x46, 0x18, 0x88, 0x40, 0x08, 0x0E, 0xD3, 0xA0, 0x00, 0x0F, 0x21, 0xCA, 0x43, 0x69, 0x46, 0x0E, 0x88, 0x16, 0x40, 0x01, 0xAF, 0x3E, 0x52, 0x49, 0x88, 0x11, 0x40, 0x68, 0x44, 0xC1, 0x80, 0x60, 0x1C, 0x04, 0x04, 0x24, 0x0C, 0x01, 0x3D, 0x0B, 0x2D, 0xE0, 0xDA, 0x60, 0x1E , -0x00, 0x04, 0x00, 0x0C, 0x1D, 0xD0, 0x86, 0x46, 0x01, 0x1C, 0x01, 0xAD, 0x01, 0x22, 0xAE, 0x88, 0x90, 0x00, 0xC7, 0x5A, 0xB7, 0x42, 0x0A, 0xDA, 0xBC, 0x46, 0x07, 0x1C, 0x6F, 0x44, 0x7F, 0x88, 0x68, 0x44, 0x06, 0x80, 0xEE, 0x88, 0x46, 0x80, 0x60, 0x46, 0xA8, 0x80, 0xEF, 0x80, 0x04, 0x35, 0x50, 0x1C, 0x02, 0x04, 0x12, 0x0C, 0x01, 0x39, 0xE9, 0xD1, 0x70, 0x46, 0x01, 0x38, 0x86, 0x46, 0xE2, 0xD1, 0x99, 0x88, 0x68, 0x46, 0xC0, 0x88, 0x40, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x42, 0x4B, 0x18, 0x80, 0x42, 0x49, 0x08, 0x1A, 0xFF, 0xFF, 0x58, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x58, 0x80, 0x02, 0x2C, 0x1E, 0xDB, 0x65, 0x1E, 0x01, 0xAA, 0x01, 0x20, 0x01, 0x1C, 0x8C, 0x00, 0x6B, 0x46, 0xE6, 0x5A, 0x93, 0x88, 0xD4, 0x88, 0xE7, 0x18, 0xB7, 0x42, 0x0C, 0xDA, 0x06, 0x24, 0x44, 0x43, 0x38, 0x4B, 0x1B, 0x19, 0x1F, 0x80, 0x1C, 0x88, 0x34, 0x1B, 0x5C, 0x80, 0x01, 0x24, 0x1C, 0x71, 0x40, 0x1C, 0x00, 0x04 , -0x00, 0x0C, 0x04, 0x32, 0x49, 0x1C, 0x09, 0x06, 0x09, 0x0E, 0x01, 0x3D, 0xE4, 0xD1, 0x00, 0x24, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x01, 0x20, 0x86, 0x46, 0x30, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x2F, 0x49, 0x22, 0x1C, 0x08, 0x68, 0x00, 0x28, 0x02, 0xD0, 0x01, 0x20, 0x90, 0x40, 0x04, 0x43, 0x04, 0x31, 0x01, 0x32, 0x20, 0x2A, 0xF5, 0xD3, 0x2A, 0x48, 0x04, 0x60, 0x08, 0xB0, 0xF0, 0xBD, 0x5F, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0xC0, 0x46, 0xC0, 0x5F, 0x75, 0x64, 0x70, 0x00, 0xC0, 0xFF, 0xFF, 0xEE, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x46, 0xC0, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0xC0, 0x46, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0xC0, 0x46, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x00, 0x64, 0x65, 0x76, 0x3D, 0x43, 0x43, 0x33, 0x30, 0x30, 0x30, 0x00, 0xC0, 0x76, 0x65 , -0x6E, 0x64, 0x6F, 0x72, 0x3D, 0x54, 0x65, 0x78, 0x61, 0x73, 0x2D, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x00, 0xC0, 0x46, 0xC0, 0x00, 0x00, 0x18, 0x00, 0xF3, 0x7E, 0x03, 0x00, 0xC6, 0x05, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0xA7, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0x48, 0x32, 0x08, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0x81, 0x03, 0x18, 0x00, 0x80, 0x7B, 0x08, 0x00, 0x84, 0xF3, 0x1A, 0x00, 0x0D, 0x49, 0x0E, 0x48, 0xFF, 0xFF, 0x84, 0x03, 0x18, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x88, 0x67, 0x0E, 0x48, 0x88, 0x64, 0x0E, 0x48, 0x48, 0x64, 0x0E, 0x48, 0xC8, 0x64, 0x0E, 0x48, 0x08, 0x65, 0x11, 0x48, 0x02, 0x1C, 0x04, 0x32, 0x0C, 0x4B, 0x13, 0x60, 0x0C, 0x4B, 0x93, 0x62, 0x0C, 0x4A , -0x8A, 0x66, 0x0D, 0x49, 0x01, 0x60, 0x0D, 0x48, 0x0E, 0x49, 0x01, 0x60, 0x0E, 0x49, 0x41, 0x60, 0xF7, 0x46, 0x1C, 0x21, 0x08, 0x00, 0x1B, 0x7B, 0x08, 0x00, 0x11, 0x7B, 0x08, 0x00, 0x07, 0x7B, 0x08, 0x00, 0x39, 0x7B, 0x08, 0x00, 0x2F, 0x7B, 0x08, 0x00, 0x25, 0x7B, 0x08, 0x00, 0xFD, 0x7A, 0x08, 0x00, 0xDF, 0x7A, 0x08, 0x00, 0x50, 0x23, 0x08, 0x00, 0xD5, 0x7A, 0x08, 0x00, 0x58, 0x26, 0x08, 0x00, 0xF3, 0x7A, 0x08, 0x00, 0xE9, 0x7A, 0x08, 0x00 }; - - -const unsigned char cRMdefaultParams[128] = { 0x03, 0x00, 0x01, 0x01, 0x14, 0x14, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x01, 0x77, 0x80, 0x1D, 0x1F, 0x22, 0x26, 0x28, 0x29, 0x1A, 0x1F, 0x22, 0x24, 0x26, 0x28, 0x16, 0x1D, 0x1E, 0x20, 0x24, 0x25, 0x1E, 0x2D, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x15, 0x15, 0x15, 0x11, 0x15, 0x15, 0x0E, 0x00}; - -// -//Service Pack version P1.13.7.15.15 - FW patches -// -const unsigned char fw_patch[5700] = { 0x00, 0x01, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x25, 0xF0, 0x95, 0xFB, 0xE0, 0x6B, 0xD0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x38, 0xFB, 0x2C, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x0A, 0xFB, 0x04, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB8, 0xF1, 0x90, 0x0F, 0xA4, 0x16, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x66, 0xE0, 0x04, 0xA8, 0x35, 0x1D, 0x21, 0xF0, 0x99, 0xFC, 0x68, 0x46, 0x23, 0xF0, 0x28, 0xFB, 0x9A, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x07, 0xD1, 0x28, 0x46, 0x05, 0xF0, 0xC3, 0xFE, 0x01, 0x46, 0x01, 0xAA, 0x00, 0x20, 0x21, 0xF0, 0x50, 0xF9, 0x28, 0x46, 0x05, 0xF0, 0xBB, 0xFE, 0x01, 0xA9, 0x21, 0xF0, 0x2A, 0xFA, 0xE9, 0x79, 0x4F, 0xEA, 0xE0, 0x00, 0x40, 0xB2, 0x11, 0xB1, 0x00, 0xF1, 0x06, 0x00, 0x40, 0xB2, 0xA8, 0x71, 0x1F, 0x38, 0x40, 0x00, 0xE8, 0x71, 0x30, 0x46 , -0x01, 0xF0, 0x0D, 0xFF, 0x10, 0xF1, 0x00, 0x09, 0x4F, 0xF0, 0x00, 0x01, 0x09, 0xD0, 0x28, 0x68, 0x40, 0x0C, 0x09, 0xD3, 0xE8, 0x68, 0xC0, 0x0B, 0x03, 0xD2, 0x48, 0x46, 0xFF, 0xF7, 0xDD, 0xFE, 0x01, 0x21, 0x28, 0x68, 0x40, 0x0C, 0x0A, 0xD2, 0x38, 0x68, 0x40, 0x1C, 0x38, 0x60, 0x20, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0x20, 0x60, 0x22, 0x68, 0x38, 0x68, 0x10, 0x43, 0x20, 0x60, 0xE8, 0x68, 0xC0, 0x0B, 0x0F, 0xD3, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0xC8, 0xF8, 0x00, 0x00, 0x20, 0x68, 0x6F, 0xF3, 0x1F, 0x40, 0x20, 0x60, 0xD8, 0xF8, 0x00, 0x20, 0x20, 0x68, 0x40, 0xEA, 0x02, 0x40, 0x20, 0x60, 0x49, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x03, 0xD1, 0x30, 0x46, 0x07, 0xF0, 0xBE, 0xF9, 0x02, 0xE0, 0x48, 0x46, 0x07, 0xF0, 0x06, 0xFA, 0x6C, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x46, 0x0E, 0xF0, 0x85, 0xFB, 0x00, 0x9E, 0x00, 0x2E, 0x96, 0xD1, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46 , -0x9C, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0xF0, 0x2A, 0xFE, 0x74, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x21, 0x21, 0xF0, 0x41, 0xFA, 0x20, 0x68, 0x18, 0x4B, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x1C, 0xF9, 0x0A, 0xE0, 0x20, 0x68, 0x00, 0x68, 0x0C, 0x21, 0x40, 0xF0, 0x20, 0x00, 0x21, 0xF0, 0x14, 0xF9, 0x10, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x20, 0xF0, 0x97, 0xF9, 0x01, 0x98, 0x5C, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x20, 0xF0, 0x71, 0xF9, 0x03, 0x98, 0x00, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x20, 0xF9, 0x1C, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x12, 0xF9, 0x54, 0x58, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xA8, 0x20, 0xF0, 0xF5, 0xF8, 0x04, 0xAB, 0x04, 0x62, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x79, 0x1F, 0xF0, 0x1B, 0xFD, 0x69, 0xE0, 0x60, 0x93, 0x00, 0x00, 0x40, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA6, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x39, 0xFB, 0x28, 0x46, 0x90, 0xA8, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x69, 0xF9, 0x1E, 0x48, 0x34, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x68, 0xFF, 0x29, 0x98, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD4, 0x21, 0xD4, 0xB2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xD0, 0x1A, 0xF0, 0x47, 0xFC, 0x20, 0x98, 0xAC, 0xC5, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0xF0 , -0xDB, 0xFA, 0x09, 0x49, 0x28, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0xF0, 0x9E, 0xFA, 0xDC, 0xD3, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x18, 0xF0, 0xAB, 0xFC, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xDF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0xF0, 0xA8, 0xFD, 0xCC, 0xEB, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x78, 0x17, 0xF0, 0x77, 0xF8, 0x38, 0x78, 0x16, 0xF0, 0xF0, 0xFF, 0xA8, 0xF7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x49, 0x09, 0x68, 0x23, 0x22, 0x41, 0x61, 0xC8, 0xF7, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x31, 0x39, 0x2E, 0x33, 0x31, 0x34, 0x5F, 0x4E, 0x65, 0x77, 0x5F, 0x43, 0x43, 0x41, 0x5F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 0xC0, 0x74, 0x56, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xF9, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x16, 0xF0, 0x79, 0xF8 , -0x12, 0xE0, 0x38, 0xFA, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x16, 0xF0, 0x03, 0xF8, 0x32, 0x20, 0x94, 0xFB, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0C, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x14, 0xF0, 0x05, 0xFF, 0x01, 0xF0, 0x10, 0x1B, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x46, 0xBF, 0x18, 0x30, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x30, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0xF0, 0xD8, 0xFC, 0x9C, 0x31, 0x01, 0x00, 0x08, 0x00 , -0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x51, 0xFC, 0xFE, 0xF7, 0xF0, 0x35, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x27, 0xFA, 0xFE, 0xF7, 0xF0, 0x3D, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA9, 0x11, 0xF0, 0x27, 0xFE, 0x20, 0x6F, 0xD0, 0x62, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xB8, 0xFB, 0x80, 0x7E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDF, 0xF8, 0x58, 0x82, 0xE0, 0x7E, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x6A, 0xFE, 0x0B, 0xF0, 0x9A, 0xF9, 0x03, 0x20, 0xA8, 0xF5, 0x88, 0x71, 0x08, 0x60, 0xF2, 0xF7, 0x16, 0xF9, 0x7A, 0x48, 0x6B, 0x49, 0x9C, 0x7F, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x51, 0x4D, 0xC4, 0x7F, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0xF1, 0x52, 0x00, 0x3A, 0x4A, 0xA8, 0x81, 0x28, 0x83, 0xE8, 0x83, 0xE8, 0x84, 0xA8, 0x85, 0x2A, 0x60, 0x39, 0x48, 0x41, 0xF2, 0x11, 0x12, 0x2A, 0x85, 0x18, 0x90, 0x19, 0x91 , -0x39, 0x49, 0x1A, 0x91, 0x39, 0x49, 0x1B, 0x91, 0x39, 0x49, 0x20, 0x46, 0xDF, 0xF8, 0xC4, 0x90, 0x1C, 0x91, 0x38, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x31, 0x4E, 0x1D, 0x91, 0x48, 0x80, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x7C, 0xFA, 0xB4, 0x80, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x12, 0x66, 0x09, 0x84, 0x6B, 0x00, 0x20, 0x94, 0x70, 0x00, 0x20, 0xB4, 0x70, 0x00, 0x20, 0xC4, 0x78, 0x00, 0x20, 0x50, 0x7A, 0x00, 0x20, 0xFE, 0xFF, 0x03, 0x00, 0xA4, 0x70, 0x00, 0x20, 0xB0, 0x70, 0x00, 0x20, 0xB8, 0x70, 0x00, 0x20, 0x60, 0x55, 0x30, 0x80, 0x3C, 0x5C, 0x00, 0x20, 0x04, 0x74, 0x00, 0x20, 0xB8, 0xE4, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x78, 0x07, 0xF0, 0x01, 0xFC, 0x20, 0x78, 0x07, 0xF0, 0x7A, 0xFB, 0x04, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF1, 0x8C, 0x0D, 0x04, 0x68, 0x0F, 0x30, 0x03, 0x94, 0xFE, 0xF7, 0xDB, 0xFA, 0x04, 0xF1, 0x14, 0x00 , -0x04, 0x90, 0x21, 0x7D, 0x00, 0x20, 0x21, 0xF0, 0x73, 0x01, 0x88, 0x29, 0x08, 0xBF, 0x01, 0x20, 0x05, 0x90, 0x03, 0x98, 0x00, 0x1D, 0x06, 0x90, 0x5D, 0x48, 0x00, 0x68, 0x01, 0x28, 0x40, 0xF0, 0xFA, 0x83, 0x5B, 0x4D, 0x5C, 0x48, 0xDF, 0xF8, 0x70, 0x91, 0x29, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0xDF, 0xF8, 0x74, 0xA1, 0x88, 0x42, 0x21, 0xD1, 0x10, 0x22, 0x00, 0x21, 0x48, 0x46, 0x4F, 0x46, 0xFB, 0xF7, 0xB7, 0xFE, 0x10, 0x22, 0x00, 0x21, 0x40, 0x46, 0xFB, 0xF7, 0xB2, 0xFE, 0x54, 0x49, 0x08, 0x68, 0x40, 0xF4, 0x80, 0x10, 0x08, 0x60, 0x01, 0x20, 0x51, 0x46, 0x08, 0x60, 0x00, 0x21, 0x29, 0x60, 0x39, 0x78, 0x46, 0x46, 0x00, 0x91, 0x31, 0x78, 0x41, 0xF2, 0x11, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x41, 0xFC, 0x51, 0x46, 0x07, 0x91, 0x08, 0x68, 0x56, 0x49, 0xDF, 0xF8, 0x5C, 0xB1, 0x01, 0x28, 0x08, 0x91, 0x56, 0x49, 0xDF, 0xF8, 0x48, 0xA1, 0x09, 0x91, 0x55, 0x49 , -0x0A, 0x91, 0x44, 0x49, 0x0B, 0x91, 0x44, 0x49, 0x0C, 0x91, 0x44, 0x49, 0x0D, 0x91, 0x44, 0x49, 0x0E, 0x91, 0x44, 0x49, 0x0F, 0x91, 0x44, 0x49, 0x10, 0x91, 0x44, 0x49, 0xCC, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x11, 0x91, 0x44, 0x49, 0x12, 0x91, 0x44, 0x49, 0x13, 0x91, 0x44, 0x49, 0x14, 0x91, 0x44, 0x49, 0x15, 0x91, 0x44, 0x49, 0x16, 0x91, 0x9F, 0x49, 0x17, 0x91, 0x9F, 0x49, 0x18, 0x91, 0x9F, 0x49, 0x19, 0x91, 0x9F, 0x49, 0x1A, 0x91, 0x9F, 0x49, 0x1B, 0x91, 0x9F, 0x49, 0x1C, 0x91, 0x9F, 0x49, 0x1D, 0x91, 0x9F, 0x49, 0x1E, 0x91, 0x9F, 0x49, 0x1F, 0x91, 0x40, 0xF0, 0x00, 0x81, 0x04, 0x98, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF9, 0x80, 0x04, 0x99, 0x09, 0x78, 0x01, 0xF0, 0x0C, 0x01, 0x08, 0x29, 0x40, 0xF0, 0xF2, 0x80, 0x06, 0x99, 0x09, 0x88, 0xA1, 0xF1, 0x3C, 0x01, 0x0E, 0xB2, 0x05, 0x99, 0x11, 0xB1, 0xA6, 0xF1, 0x02, 0x06, 0x36, 0xB2, 0xC0, 0x09, 0x4F, 0xF0 , -0x00, 0x07, 0x15, 0xD3, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x10, 0xD0, 0x17, 0x2E, 0x0E, 0xD0, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x08, 0xD0, 0x17, 0x2E, 0x06, 0xD0, 0x36, 0x1F, 0x36, 0xB2, 0x03, 0x2E, 0x14, 0xBF, 0x17, 0x2E, 0x02, 0x27, 0x02, 0xE0, 0x03, 0x27, 0x00, 0xE0, 0x01, 0x27, 0x03, 0x2E, 0x18, 0xBF, 0x17, 0x2E, 0x04, 0x9A, 0x40, 0xF0, 0xC8, 0x80, 0x0A, 0x32, 0x12, 0xF8, 0x01, 0x1B, 0x05, 0x24, 0x12, 0xF8, 0x01, 0x3B, 0x4B, 0x40, 0x64, 0x1E, 0xD9, 0xB2, 0xF9, 0xD1, 0x81, 0xEA, 0x21, 0x11, 0x03, 0x2E, 0x94, 0x4E, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x01, 0x48, 0x46, 0x35, 0xD0, 0x43, 0x46, 0xCA, 0x5C, 0x52, 0x1C, 0xCA, 0x54, 0x0C, 0x18, 0x33, 0xE0, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0xC8, 0x48, 0x30, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x88, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00 , -0x18, 0x58, 0x02, 0x00, 0x20, 0x58, 0x02, 0x00, 0x28, 0x58, 0x02, 0x00, 0x30, 0x58, 0x02, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58, 0x02, 0x00, 0xE4, 0x58, 0x02, 0x00, 0xE2, 0x58, 0x02, 0x00, 0x14, 0x58, 0x02, 0x00, 0xEF, 0x58, 0x02, 0x00, 0xE0, 0x58, 0x02, 0x00, 0xEE, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x0C, 0x18, 0x20, 0x78, 0x40, 0x1C, 0x20, 0x70, 0x20, 0x78, 0x43, 0x46, 0x03, 0xEB, 0x01, 0x08, 0x0A, 0x28, 0x76, 0xDB, 0x98, 0xF8, 0x00, 0x00, 0x0A, 0x28, 0x72, 0xDB, 0x94, 0x48, 0x00, 0x25, 0x01, 0x60, 0x04, 0x98, 0x00, 0xF1, 0x0A, 0x09, 0x40, 0x78, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x04, 0xD2, 0x80, 0x08, 0x2E, 0xBF, 0x49, 0x46, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0x06, 0x22, 0xFA, 0xF7, 0xB9, 0xFC, 0x0C, 0x98, 0x06, 0x22, 0x49, 0x46, 0xFA, 0xF7, 0xB4, 0xFC, 0x9B, 0x48, 0x9A, 0x49, 0x5C, 0x4F, 0x02, 0x00, 0xC8, 0x00 , -0x00, 0x00, 0x00, 0x78, 0x08, 0x22, 0x08, 0x60, 0x58, 0x46, 0x07, 0x60, 0x0D, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAF, 0xFD, 0x08, 0x22, 0x0E, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAA, 0xFD, 0x08, 0x22, 0x0F, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA5, 0xFD, 0x08, 0x22, 0x10, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, 0x08, 0x22, 0x11, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x9B, 0xFD, 0x08, 0x22, 0x12, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x96, 0xFD, 0x07, 0x99, 0x02, 0x20, 0x08, 0x60, 0x13, 0x99, 0x28, 0x46, 0x08, 0x80, 0x08, 0x99, 0x08, 0x70, 0x14, 0x99, 0x08, 0x70, 0x15, 0x99, 0x08, 0x60, 0x16, 0x99, 0x08, 0x70, 0x17, 0x99, 0x08, 0x60, 0x18, 0x99, 0x08, 0x60, 0x19, 0x99, 0x08, 0x60, 0x09, 0x99, 0x08, 0x80, 0x0A, 0x99, 0x08, 0x80, 0x1A, 0x99, 0x08, 0x80, 0x7D, 0x49, 0x0D, 0x60, 0x1B, 0x99, 0x08, 0x70, 0x1C, 0x99, 0x08, 0x70, 0x1D, 0x99, 0x08, 0x70, 0x1E, 0x99, 0x08, 0x80, 0x1F, 0x99, 0x08, 0x80, 0x51, 0x46, 0x08, 0x80 , -0x20, 0x78, 0x00, 0x96, 0x04, 0x22, 0x01, 0x90, 0x98, 0xF8, 0x00, 0x00, 0x41, 0xF2, 0x14, 0x13, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x07, 0xFB, 0x07, 0x98, 0xA2, 0x49, 0x00, 0x68, 0x20, 0x91, 0xA2, 0x49, 0x05, 0x28, 0x21, 0x91, 0x9E, 0x49, 0x22, 0x91, 0x40, 0xF0, 0x37, 0x82, 0x04, 0x98, 0x40, 0x78, 0x24, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x05, 0xD2, 0x80, 0x08, 0x27, 0xBF, 0x04, 0x99, 0x0A, 0x31, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0xF8, 0xF7, 0x2D, 0xFC, 0x01, 0x28, 0x04, 0x98, 0x40, 0xF0, 0x23, 0x82, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x00, 0x03, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x07, 0xBF, 0x04, 0x99, 0x10, 0x31, 0x04, 0x99, 0x0A, 0x31, 0x13, 0xE0, 0x48, 0x58, 0x02, 0x00, 0x4C, 0x58, 0x02, 0x00, 0x50, 0x58, 0x02, 0x00, 0xF0, 0x58, 0x02, 0x00, 0xF2, 0x58, 0x02, 0x00, 0xF3, 0x58, 0x02, 0x00, 0xF4, 0x58, 0x02, 0x00, 0xEA, 0x58 , -0x02, 0x00, 0xEC, 0x58, 0x02, 0x00, 0x04, 0x99, 0x18, 0x31, 0x0C, 0x98, 0xF8, 0xF7, 0x06, 0xFC, 0x04, 0x99, 0x01, 0x28, 0x40, 0xF0, 0xFC, 0x81, 0x49, 0x78, 0x01, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF6, 0x81, 0x59, 0x46, 0x09, 0x68, 0x04, 0x9A, 0x8E, 0x46, 0x51, 0x46, 0xD2, 0x8A, 0x0B, 0x88, 0x12, 0x11, 0x93, 0x42, 0x00, 0xF0, 0x37, 0x82, 0x0A, 0x80, 0x06, 0x99, 0x09, 0x88, 0x3C, 0x39, 0x0B, 0xB2, 0x71, 0x46, 0x49, 0x1E, 0x09, 0xD0, 0x49, 0x1E, 0x04, 0xD0, 0x49, 0x1E, 0x08, 0xD1, 0xA3, 0xF1, 0x10, 0x03, 0x04, 0xE0, 0xA3, 0xF1, 0x14, 0x03, 0x01, 0xE0, 0xA3, 0xF1, 0x08, 0x03, 0x1B, 0xB2, 0x05, 0x98, 0x10, 0xB1, 0xA3, 0xF1, 0x02, 0x03, 0x1B, 0xB2, 0xEC, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0xF1, 0xCE, 0x81, 0x16, 0x98, 0x40, 0xF2, 0x77, 0x51, 0x99, 0x42, 0x0B, 0x90, 0x14, 0x98, 0x05, 0x90, 0x00, 0xF0, 0xA3, 0x81, 0x08, 0x46, 0x00, 0xF1, 0x3C, 0x00, 0x98, 0x42 , -0x05, 0x9A, 0x00, 0xF0, 0x9A, 0x81, 0xDF, 0xF8, 0x48, 0x82, 0x14, 0x78, 0x0B, 0x9A, 0xBB, 0x2C, 0x12, 0x78, 0x0C, 0x92, 0x63, 0xD1, 0xDD, 0xF8, 0x68, 0xC0, 0xBC, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x18, 0xBF, 0x90, 0x42, 0x5B, 0xD1, 0x1C, 0x2B, 0x4F, 0xF0, 0x00, 0x00, 0xC0, 0xF2, 0x82, 0x81, 0x3D, 0x2B, 0x13, 0x9D, 0x80, 0xF2, 0x7E, 0x81, 0xA3, 0xF1, 0x1C, 0x01, 0x09, 0xB2, 0x29, 0x80, 0x1E, 0x9A, 0xDD, 0xF8, 0x30, 0x90, 0xB2, 0xF9, 0x00, 0x60, 0xB9, 0xF1, 0x01, 0x0F, 0x15, 0xD1, 0xDD, 0xF8, 0x24, 0x90, 0x03, 0x2E, 0x0D, 0xDA, 0xB9, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x07, 0xD0, 0x01, 0x26, 0x16, 0x80, 0x4A, 0x46, 0x0E, 0x46, 0x03, 0xE0, 0xC0, 0x46, 0x90, 0x57, 0x02, 0x00, 0x76, 0x1C, 0x16, 0x80, 0x1B, 0x9A, 0x16, 0x78, 0x1D, 0x9A, 0x16, 0x70, 0x0C, 0x9A, 0x1F, 0x9E, 0x02, 0x2A, 0x28, 0xD1, 0xB6, 0xF9, 0x00, 0x20, 0xBE, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x03, 0x2A, 0x35, 0x46, 0x0B, 0xDA, 0x0A, 0x9E , -0xB6, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x04, 0xD0, 0x01, 0x22, 0x2A, 0x80, 0x0A, 0x46, 0x35, 0x46, 0x00, 0xE0, 0xB4, 0x51, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x52, 0x1C, 0x2A, 0x80, 0x1C, 0x99, 0x0A, 0x78, 0x1D, 0x99, 0x0A, 0x70, 0x0F, 0xE0, 0xC0, 0x46, 0x58, 0x57, 0x02, 0x00, 0xA6, 0x64, 0x00, 0x20, 0x54, 0x57, 0x02, 0x00, 0x28, 0x80, 0x05, 0x99, 0x08, 0x70, 0x08, 0x9A, 0x11, 0x78, 0x41, 0xF0, 0x04, 0x01, 0x11, 0x70, 0x04, 0x46, 0x45, 0x46, 0xAC, 0xF8, 0x00, 0x00, 0x28, 0x70, 0xCC, 0x2C, 0x09, 0x9A, 0x40, 0xF0, 0x00, 0x81, 0xDD, 0xF8, 0x7C, 0xC0, 0x0A, 0x99, 0x1E, 0x9F, 0x45, 0x46, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x00, 0x90, 0x28, 0x78, 0xCD, 0xF8, 0x50, 0xC0, 0x16, 0x91, 0x0A, 0x97, 0x13, 0x92, 0x09, 0x95, 0x0C, 0x99, 0x01, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x49, 0x0F, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0x0C, 0x99, 0x02, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x46, 0x0F , -0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0xB3, 0xF5, 0x14, 0x7F, 0x40, 0xF3, 0xBA, 0x80, 0x40, 0xF2, 0x51, 0x31, 0x99, 0x42, 0x08, 0x99, 0x40, 0xF3, 0xB4, 0x80, 0x09, 0x78, 0x06, 0x29, 0x00, 0xF0, 0xB0, 0x80, 0xA3, 0xF2, 0x51, 0x21, 0x0B, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x4F, 0xEA, 0x21, 0x11, 0xCA, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x15, 0x9D, 0x21, 0xF0, 0x0F, 0x01, 0xA3, 0xEB, 0x01, 0x03, 0x1D, 0x99, 0x2E, 0x68, 0x7C, 0x52, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0xE0, 0x5F, 0xFA, 0x83, 0xF8, 0x60, 0xB1, 0x31, 0x18, 0x11, 0xF8, 0x01, 0x1C, 0x51, 0x40, 0xCB, 0xB2, 0x07, 0xE0, 0xC0, 0x46, 0x58, 0x58, 0x02, 0x00, 0x54, 0x58, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0x13, 0x46, 0x19, 0x99, 0xDD, 0xF8, 0x6C, 0xA0, 0xDD, 0xF8, 0x70, 0xB0, 0xD1, 0xF8, 0x00, 0xC0, 0x00, 0xF0, 0x0F, 0x01, 0x99, 0x42, 0x22, 0xD0, 0x0A, 0x9B, 0x86, 0x45, 0x9A, 0xF8 , -0x00, 0x10, 0xB3, 0xF9, 0x00, 0x30, 0x9B, 0xF8, 0x00, 0x50, 0x15, 0xDD, 0x37, 0x5C, 0x44, 0x1C, 0x82, 0xEA, 0x07, 0x0C, 0x04, 0xF0, 0x0F, 0x07, 0x67, 0x45, 0x0B, 0xD0, 0xA6, 0x45, 0x06, 0x44, 0x0A, 0xDD, 0x76, 0x78, 0x72, 0x40, 0x86, 0x1C, 0x06, 0xF0, 0x0F, 0x06, 0x96, 0x42, 0x03, 0xD1, 0xC0, 0x1C, 0x4D, 0xE0, 0x80, 0x1C, 0x4B, 0xE0, 0x05, 0x9E, 0x00, 0x22, 0x32, 0x70, 0x4A, 0xE0, 0x00, 0xF0, 0x1F, 0x01, 0x01, 0x22, 0x8A, 0x40, 0x17, 0x99, 0xC4, 0x10, 0x0B, 0x68, 0x24, 0xF0, 0x03, 0x01, 0x5C, 0xF8, 0x01, 0x70, 0x3A, 0x42, 0x32, 0xD1, 0x5F, 0x58, 0x3A, 0x42, 0x06, 0x44, 0x1F, 0xD0, 0x18, 0x9B, 0x37, 0x78, 0x1B, 0x68, 0xB8, 0x45, 0x04, 0xD1, 0x58, 0x58, 0x02, 0x42, 0x19, 0xD0, 0x63, 0x46, 0x15, 0xE0, 0xA1, 0x10, 0x8C, 0x00, 0x19, 0x59, 0x91, 0x43, 0x19, 0x51, 0x00, 0x90, 0x30, 0x78, 0x01, 0x90, 0x44, 0x53, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x20, 0x06, 0x21, 0x02, 0x46, 0x4D, 0xF6 , -0x80, 0x53, 0xF3, 0xF7, 0x63, 0xF9, 0x09, 0x99, 0x28, 0x68, 0x0E, 0x78, 0x36, 0x18, 0x06, 0xE0, 0xE3, 0x58, 0x02, 0x00, 0xA0, 0x10, 0x81, 0x00, 0x58, 0x58, 0x02, 0x43, 0x5A, 0x50, 0x86, 0xF8, 0x00, 0x80, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x13, 0x98, 0xB0, 0xF9, 0x00, 0x90, 0x09, 0x98, 0x00, 0x78, 0x0A, 0x9A, 0x40, 0x1C, 0x9B, 0xF8, 0x00, 0x50, 0x9A, 0xF8, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x09, 0x9A, 0xC0, 0xB2, 0x10, 0x70, 0x0C, 0x9A, 0x01, 0x2A, 0x03, 0xD1, 0x88, 0x42, 0xC8, 0xBF, 0x8A, 0xF8, 0x00, 0x00, 0x0C, 0x99, 0x02, 0x29, 0x07, 0xD1, 0xA8, 0x42, 0xC8, 0xBF, 0x8B, 0xF8, 0x00, 0x00, 0x02, 0xE0, 0x0A, 0x98, 0xB0, 0xF9, 0x00, 0x30, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x03, 0x2B, 0x04, 0xD1, 0x11, 0x98, 0x01, 0x22, 0x49, 0x46, 0x00, 0xF0, 0x72, 0xFB, 0x16, 0x98, 0xB0, 0xF9, 0x00, 0x10, 0x14, 0x98, 0x00, 0x29, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xDD, 0x03, 0x28, 0x03, 0xD1, 0x12, 0x98 , -0x02, 0x22, 0x00, 0xF0, 0x64, 0xFB, 0x05, 0x98, 0x04, 0x78, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x08, 0x98, 0xBB, 0x2C, 0x01, 0x78, 0x02, 0xD0, 0xAA, 0x2C, 0x2F, 0xD0, 0x31, 0xE0, 0x0C, 0x98, 0x01, 0x28, 0x0B, 0xD1, 0x0D, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x0C, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x0F, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x11, 0x98, 0x10, 0x60, 0x47, 0x4A, 0x15, 0x98, 0x02, 0x60, 0x0C, 0x98, 0x02, 0x28, 0x0B, 0xD1, 0x0E, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x10, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x12, 0x98, 0x10, 0x60, 0x41, 0x4A, 0x15, 0x98, 0x02, 0x60, 0xCC, 0x20, 0x0F, 0xE0, 0x08, 0x99, 0x09, 0x78, 0x0C, 0xE0, 0x02, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x0B, 0x99, 0x08, 0x70, 0x1A, 0x99, 0x0B, 0x80, 0x13, 0x99, 0x00, 0x20, 0x08, 0x80, 0x08, 0x98, 0x01, 0x78, 0xBB, 0x20, 0x05, 0x9A, 0x10, 0x70, 0x06, 0x29, 0x07, 0x99, 0x11, 0xD1, 0x06, 0x20, 0x08, 0x60, 0x20, 0x98 , -0x00, 0x25, 0x05, 0x70, 0x21, 0x98, 0x29, 0x46, 0x04, 0x22, 0xFB, 0xF7, 0x27, 0xFB, 0x01, 0x20, 0x00, 0xF0, 0x3A, 0xFA, 0x02, 0x20, 0x00, 0xF0, 0x37, 0xFA, 0x22, 0x98, 0x05, 0x60, 0x07, 0x98, 0x04, 0x99, 0x00, 0x68, 0x07, 0x28, 0x44, 0xD1, 0x09, 0x78, 0x03, 0x9C, 0x80, 0x29, 0x40, 0xD1, 0x38, 0x34, 0x21, 0x78, 0x64, 0x1C, 0x22, 0x46, 0x00, 0x29, 0x3A, 0xD1, 0x20, 0x98, 0x90, 0xF8, 0x00, 0xA0, 0x22, 0x98, 0x05, 0x90, 0xD0, 0xF8, 0x00, 0x90, 0x51, 0x46, 0x48, 0x46, 0xFD, 0xF7, 0x79, 0xF9, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x9F, 0x15, 0x78, 0x51, 0x46, 0x48, 0x46, 0x17, 0xF8, 0x08, 0x30, 0xFD, 0xF7, 0xD4, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6F, 0xF9, 0x1E, 0x46, 0x1B, 0x1D, 0xC0, 0xB2, 0x38, 0x5C, 0x00, 0x1D, 0xA8, 0x42, 0x28, 0x46, 0x07, 0xDD, 0x80, 0x18, 0x82, 0x1C, 0x10, 0x78, 0x2D, 0x18, 0xAD, 0x1C, 0xAD, 0xB2, 0xAB, 0x42, 0xF7, 0xDC, 0x04, 0xF8, 0x01, 0x6B, 0x11, 0x49, 0x32, 0x46 , -0x20, 0x46, 0x01, 0xEB, 0x48, 0x11, 0xFA, 0xF7, 0xDC, 0xF9, 0xAD, 0x1B, 0xFF, 0x20, 0x34, 0x19, 0xAD, 0x1E, 0x04, 0xF8, 0x01, 0x0B, 0x25, 0x70, 0x05, 0x98, 0x01, 0x68, 0x49, 0x1C, 0x01, 0x60, 0x07, 0x98, 0x00, 0x68, 0x07, 0x28, 0x04, 0xD0, 0x06, 0x99, 0x08, 0x68, 0x20, 0xF4, 0x80, 0x30, 0x08, 0x60, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC0, 0x46, 0x94, 0x57, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x6E, 0x48, 0x2D, 0xE9, 0xF0, 0x47, 0x6E, 0x4D, 0x82, 0x89, 0x4A, 0xF6, 0x55, 0x21, 0xAD, 0xF5, 0xFE, 0x7D, 0x91, 0x42, 0x4F, 0xF0, 0x00, 0x01, 0xAD, 0xF1, 0x38, 0x0D, 0x12, 0xD1, 0x29, 0x60, 0x68, 0x4A, 0x11, 0x70, 0x41, 0xF2, 0x10, 0x41, 0x81, 0x81, 0x4F, 0xF6, 0xFF, 0x70, 0x66, 0x49, 0x08, 0x60, 0x28, 0x68, 0x00, 0x90, 0x02, 0x22, 0x05, 0x21, 0x03, 0x20, 0x41, 0xF2, 0x34, 0x23, 0xF3, 0xF7, 0x48, 0xF8, 0x29, 0x68, 0x61, 0x4C, 0x01, 0x29, 0x20, 0x68, 0x40, 0xF0, 0xAF, 0x80 , -0x5F, 0x4D, 0x02, 0x28, 0x29, 0x68, 0x23, 0xD1, 0x9C, 0x55, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x68, 0x5F, 0x4A, 0x12, 0x5C, 0x00, 0x92, 0x01, 0x91, 0x5E, 0x49, 0x09, 0x68, 0x02, 0x91, 0x5B, 0x49, 0x0B, 0x5C, 0x03, 0x20, 0x07, 0x21, 0x04, 0x22, 0xF3, 0xF7, 0x2E, 0xF8, 0x5B, 0x49, 0x4A, 0x79, 0x59, 0x48, 0x00, 0x92, 0x02, 0x79, 0x01, 0x92, 0x40, 0x79, 0x04, 0x22, 0x02, 0x90, 0x03, 0x20, 0x0B, 0x79, 0x07, 0x21, 0xF3, 0xF7, 0x20, 0xF8, 0x03, 0x20, 0x20, 0x60, 0xEC, 0xF7, 0x1A, 0xFF, 0x20, 0x68, 0x29, 0x68, 0x04, 0x28, 0x15, 0xD1, 0x0D, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x00, 0x25, 0x8D, 0xF8, 0x14, 0x50, 0x8D, 0xF8, 0x15, 0x10, 0x28, 0x46, 0x63, 0x21, 0x00, 0xF0, 0xAA, 0xFB, 0x63, 0x21, 0x28, 0x46, 0x00, 0xF0, 0xFA, 0xFA, 0x03, 0xA9, 0x04, 0xA8, 0xE0, 0xF7, 0xCA, 0xFC, 0x05, 0x20, 0x20, 0x60, 0x46, 0x4D, 0x05, 0x28, 0x29, 0x68, 0x01, 0xF1, 0x01, 0x01, 0x29, 0x60, 0x1D, 0xD1 , -0x44, 0x4A, 0x8A, 0x42, 0x1A, 0xD1, 0x43, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0x06, 0x21, 0x41, 0x4E, 0x33, 0x46, 0x22, 0x3B, 0xF2, 0xF7, 0xEB, 0xFF, 0x3E, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x33, 0x46, 0x06, 0x21, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xE0, 0xFF, 0x00, 0x20, 0x28, 0x60, 0x20, 0x68, 0x06, 0x28, 0x47, 0xD1, 0x4F, 0xF0, 0x64, 0x56, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x07, 0x0A, 0xC4, 0xF8, 0x00, 0xA0, 0x03, 0x20, 0x48, 0xF2, 0x70, 0x53, 0x01, 0x22, 0x04, 0x21, 0xF2, 0xF7, 0xD0, 0xFF, 0xDF, 0xF8, 0xCC, 0x80, 0x31, 0x4F, 0x48, 0xF2, 0x70, 0x59, 0x01, 0x25, 0x49, 0xEA, 0x05, 0x03, 0x01, 0x22, 0x04, 0x21, 0x03, 0x20, 0xF2, 0xF7, 0xC3, 0xFF, 0x00, 0x24, 0x17, 0xF8, 0x02, 0x0F, 0x20, 0xE0, 0x69, 0x01, 0x04, 0xEB, 0x08, 0x02, 0x88, 0x18, 0xC6, 0x1C, 0x43, 0x78, 0x00, 0x93, 0x80, 0x78, 0x01, 0x90, 0x30, 0x78, 0x02, 0x90 , -0x53, 0x5C, 0x51, 0x46, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xAE, 0xFF, 0x38, 0x78, 0x01, 0x1B, 0xB1, 0xF1, 0xFF, 0x3F, 0x08, 0xD1, 0xF0, 0x78, 0x00, 0x90, 0xB3, 0x78, 0x03, 0x20, 0x02, 0x22, 0x05, 0x21, 0xF2, 0xF7, 0xA1, 0xFF, 0x38, 0x78, 0x24, 0x1D, 0xE4, 0xB2, 0xA0, 0x42, 0xDC, 0xDC, 0xAD, 0x1C, 0xED, 0xB2, 0x04, 0x2D, 0xCD, 0xDB, 0x63, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0xF1, 0xF7, 0xA3, 0xFC, 0xE1, 0xF7, 0x85, 0xFD, 0x7F, 0xB0, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46, 0x04, 0x74, 0x00, 0x20, 0x50, 0x57, 0x02, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x40, 0x00, 0x3D, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x58, 0x57, 0x02, 0x00, 0x90, 0x57, 0x02, 0x00, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00, 0x2C, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x88, 0x57, 0x02, 0x00, 0x54, 0x57, 0x02, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58 , -0x02, 0x00, 0x66, 0x55, 0xDD, 0xEE, 0xDB, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x58, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x4A, 0x4A, 0x49, 0x4D, 0x00, 0x90, 0xB2, 0xF9, 0x00, 0x20, 0x43, 0xA3, 0x29, 0x78, 0x01, 0x93, 0x43, 0xA3, 0x01, 0x28, 0x02, 0x93, 0x47, 0x4E, 0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0x91, 0x1E, 0xD0, 0x43, 0x48, 0x04, 0x78, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0xC8, 0xFF, 0x40, 0x46, 0x01, 0x78, 0x00, 0x68, 0x07, 0xF1, 0x06, 0x07, 0x07, 0xF8, 0x01, 0x1B, 0x07, 0xF8, 0x01, 0x4B, 0x4F, 0xF0, 0x00, 0x01, 0x07, 0xF8, 0x01, 0x1B, 0x20, 0xB9, 0x39, 0x70, 0x28, 0x78, 0x4E, 0x46, 0x0A, 0x21, 0x58, 0xE0, 0xDF, 0xF8, 0xE4, 0xB0, 0x0F, 0xE0, 0xD4, 0xB2, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0xAA, 0xFF, 0xFF, 0x1D, 0x00, 0x20, 0xDF, 0xF8, 0xCC, 0xB0, 0x07, 0xF8, 0x01, 0x4B, 0x07, 0xF8, 0x01, 0x0B, 0x16, 0x2C, 0xB2, 0x46, 0xAE, 0xBF, 0x14, 0x20, 0x84, 0x59 , -0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x60, 0x1E, 0xC0, 0xB2, 0x38, 0x70, 0x4E, 0x46, 0x7F, 0x1C, 0x40, 0x1C, 0xC2, 0xB2, 0x28, 0x78, 0x5B, 0x46, 0x00, 0x21, 0x32, 0x54, 0x38, 0x46, 0x00, 0xF0, 0xBC, 0xF9, 0x28, 0x78, 0x16, 0x2C, 0x31, 0x5C, 0x01, 0xF1, 0x0A, 0x01, 0x31, 0x54, 0x00, 0xF1, 0x01, 0x00, 0xC0, 0xB2, 0x28, 0x70, 0x2B, 0xDB, 0x00, 0x99, 0x0A, 0xEB, 0x40, 0x10, 0x07, 0x46, 0x01, 0x29, 0xA4, 0xF1, 0x01, 0x09, 0x09, 0xD0, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0x79, 0xFF, 0x40, 0x46, 0x00, 0x78, 0xBF, 0x1D, 0x07, 0xF8, 0x01, 0x0B, 0x04, 0xE0, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0x6F, 0xFF, 0xFF, 0x1D, 0x07, 0xF8, 0x01, 0x4B, 0x15, 0x3C, 0x15, 0x21, 0x28, 0x78, 0xE2, 0xB2, 0x5B, 0x46, 0x07, 0xF8, 0x01, 0x1B, 0x32, 0x54, 0x07, 0xF8, 0x01, 0x9B, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF9, 0x28, 0x78, 0x31, 0x5C, 0x0A, 0x31, 0x31, 0x54, 0x40, 0x1C, 0x28, 0x70, 0xBD, 0xE8, 0xFE, 0x8F, 0xC0, 0x46 , -0x54, 0x54, 0x54, 0x4B, 0x45, 0x59, 0x00, 0xC0, 0x54, 0x54, 0x54, 0x53, 0x53, 0x49, 0x44, 0x00, 0x54, 0x58, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x94, 0x57, 0x02, 0x00, 0xFF, 0xB5, 0x0C, 0x46, 0x06, 0x46, 0xF7, 0xF7, 0x4C, 0x5A, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE3, 0xFE, 0x15, 0x49, 0x15, 0x4A, 0x0D, 0x68, 0x01, 0xA9, 0x92, 0xE8, 0x8C, 0x00, 0x81, 0xE8, 0x8C, 0x00, 0xF7, 0xF7, 0xFD, 0xFE, 0x01, 0x98, 0x11, 0x49, 0x28, 0x1A, 0x03, 0x9D, 0x25, 0x60, 0x02, 0x9A, 0x80, 0x18, 0x82, 0x42, 0x30, 0x60, 0x0E, 0xD8, 0x08, 0x46, 0x00, 0x68, 0x22, 0x68, 0x82, 0x42, 0x0E, 0xD2, 0x68, 0x46, 0xE8, 0xF7, 0xB9, 0xFF, 0x9D, 0xF8, 0x00, 0x00, 0x05, 0xF1, 0x01, 0x05, 0x30, 0xB9, 0x03, 0x95, 0x03, 0xE0, 0x25, 0x68, 0x6D, 0x1C, 0x25, 0x60, 0x0C, 0x46, 0x25, 0x60, 0x00, 0x20, 0x00, 0x90 , -0xFF, 0xBD, 0x60, 0x55, 0x30, 0x80, 0x24, 0x5D, 0x00, 0x20, 0x6C, 0x5D, 0x02, 0x00, 0x70, 0xB5, 0x4D, 0x00, 0x20, 0x2D, 0x4F, 0xF0, 0x00, 0x01, 0x0C, 0x46, 0x4F, 0xEA, 0x55, 0x13, 0x09, 0xD3, 0x50, 0xF8, 0x21, 0x60, 0xB6, 0xF1, 0xFF, 0x3F, 0x04, 0xD1, 0x49, 0x1C, 0xC9, 0xB2, 0x20, 0x3D, 0x5B, 0x1E, 0xF5, 0xD1, 0x4D, 0xB1, 0x20, 0x2D, 0x09, 0xD2, 0x01, 0x23, 0xAB, 0x40, 0x5B, 0x1E, 0x50, 0xF8, 0x21, 0x00, 0x18, 0x40, 0x83, 0x42, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x04, 0x07, 0x48, 0x03, 0x78, 0x2C, 0xB9, 0x01, 0x21, 0x91, 0x40, 0xC9, 0x43, 0xC9, 0xB2, 0x0B, 0x40, 0x03, 0xE0, 0x01, 0x21, 0x91, 0x40, 0xC9, 0xB2, 0x0B, 0x43, 0x03, 0x70, 0x70, 0xBD, 0xC0, 0x46, 0xEE, 0x58, 0x02, 0x00, 0x14, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x7E, 0xB5, 0x05, 0x46, 0x95, 0xF8, 0x36, 0x20, 0x0E, 0x46, 0x0F, 0x49, 0x07, 0x2A, 0x12, 0xBF, 0x08, 0x68, 0x01, 0x20, 0x08, 0x60, 0x0D, 0x4C, 0x00, 0x92, 0x21, 0x68 , -0x41, 0xF2, 0x12, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF2, 0xF7, 0x6B, 0xFD, 0x31, 0x46, 0x28, 0x46, 0xE7, 0xF7, 0x21, 0xFC, 0x21, 0x68, 0x00, 0x22, 0x05, 0x29, 0x02, 0xD1, 0x04, 0x49, 0x08, 0x31, 0x0A, 0x60, 0x7E, 0xBD, 0xC0, 0x46, 0x50, 0x57, 0x02, 0x00, 0x4C, 0x57, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x20, 0x0E, 0x49, 0x09, 0x68, 0x49, 0x08, 0x15, 0xD2, 0x0D, 0x49, 0x09, 0x78, 0x91, 0xB1, 0x44, 0xF2, 0xE9, 0x21, 0x68, 0xB9, 0x0B, 0x48, 0x01, 0x78, 0x07, 0x48, 0x01, 0x29, 0x03, 0xD1, 0x0A, 0x49, 0x09, 0x78, 0x0E, 0x29, 0x02, 0xD0, 0x44, 0xF2, 0xDE, 0x21, 0x41, 0x60, 0x01, 0x21, 0x00, 0xE0, 0x06, 0x48, 0x01, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x97, 0x3C, 0x80, 0x10, 0x0C, 0x30, 0x80, 0xDD, 0x6A, 0x00, 0x20, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x00, 0xB5, 0xAD, 0xF1, 0x18, 0x0D, 0x4F, 0xF0, 0x09, 0x00, 0x00, 0x90, 0x4F, 0xF4 , -0x0C, 0x60, 0x03, 0x90, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0x90, 0x02, 0x90, 0x08, 0x48, 0x08, 0x49, 0x05, 0x90, 0x08, 0x68, 0x20, 0xB9, 0xDC, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0x3A, 0xFA, 0x03, 0xE0, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0xC1, 0xFC, 0x06, 0xB0, 0x00, 0xBD, 0xC0, 0x46, 0x81, 0x5C, 0x02, 0x00, 0xDC, 0x7C, 0x00, 0x20, 0x1C, 0xB5, 0x0F, 0x4C, 0x22, 0x68, 0x01, 0x2A, 0x15, 0xD1, 0x0C, 0x48, 0x00, 0x68, 0x07, 0x28, 0x14, 0xBF, 0x40, 0x20, 0x4F, 0xF4, 0x05, 0x70, 0x63, 0x21, 0xF1, 0xF7, 0x0F, 0xFA, 0x20, 0x68, 0x00, 0x90, 0x43, 0xF2, 0x33, 0x33, 0x06, 0x21, 0x40, 0x20, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xF4, 0xFC, 0x1C, 0xBD, 0xF1, 0xF7, 0x01, 0xFA, 0x1C, 0xBD, 0x4C, 0x57, 0x02, 0x00, 0x50, 0x57, 0x02, 0x00, 0x1E, 0xB5, 0x04, 0x46, 0x0A, 0x49, 0x00, 0x20, 0x0A, 0x4A, 0x08, 0x60, 0x0A, 0x49, 0x00, 0x90, 0x01, 0x90, 0x11, 0x60 , -0x09, 0x4A, 0x45, 0xF2, 0x55, 0x53, 0x02, 0x91, 0x10, 0x60, 0x07, 0x21, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xD8, 0xFC, 0x20, 0x46, 0xE7, 0xF7, 0x59, 0xFD, 0x1E, 0xBD, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x4C, 0x57, 0x02, 0x00, 0x00, 0xB5, 0x0B, 0x49, 0x00, 0x20, 0x08, 0x60, 0xE0, 0x20, 0xF7, 0xF7, 0xAA, 0xFD, 0x09, 0x49, 0x09, 0x78, 0x49, 0xB1, 0x08, 0x49, 0x0A, 0x78, 0x08, 0x49, 0x00, 0x2A, 0x06, 0xBF, 0x01, 0x22, 0x09, 0x1F, 0x44, 0xF2, 0xA4, 0x5C, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE9, 0x22, 0x0A, 0x60, 0xF7, 0xF7, 0xA1, 0xFD, 0x00, 0xBD, 0xC0, 0x46, 0xDC, 0x7C, 0x00, 0x20, 0xDD, 0x6A, 0x00, 0x20, 0xA7, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x50, 0xB9, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x06, 0xD1, 0x08, 0x48, 0x00, 0x78, 0x0E, 0x28, 0x08, 0xBF, 0x44, 0xF2, 0xCB, 0x20, 0x01, 0xD0, 0x44, 0xF2, 0xDE, 0x20, 0x04, 0x49, 0x08, 0x60, 0x01, 0x20 , -0x41, 0xF8, 0x04, 0x0C, 0x70, 0x47, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x30, 0xB5, 0x0D, 0x46, 0x84, 0x69, 0xDC, 0xF7, 0x97, 0xFB, 0x24, 0x1D, 0x01, 0x28, 0x04, 0xEB, 0x45, 0x01, 0x06, 0xD1, 0x89, 0x8E, 0x04, 0xEB, 0x85, 0x04, 0x11, 0xB9, 0x21, 0x69, 0x01, 0xB9, 0x00, 0x20, 0x30, 0xBD, 0x30, 0xB5, 0x05, 0x46, 0x5A, 0xB1, 0x03, 0xEB, 0x41, 0x03, 0x1C, 0x78, 0x59, 0x78, 0x41, 0xEA, 0x04, 0x11, 0x52, 0x1E, 0x03, 0xF1, 0x02, 0x03, 0x05, 0xF8, 0x01, 0x1B, 0xF5, 0xD1, 0x30, 0xBD, 0x00, 0xB5, 0x00, 0x20, 0xE7, 0xF7, 0xD6, 0xFE, 0x03, 0x48, 0x01, 0x68, 0x03, 0x29, 0x04, 0xBF, 0x04, 0x21, 0x01, 0x60, 0x00, 0xBD, 0xC0, 0x46, 0x4C, 0x57, 0x02, 0x00, 0x03, 0x4A, 0x12, 0x68, 0x01, 0x2A, 0x04, 0xBF, 0x02, 0x48, 0x63, 0x21, 0xF1, 0xF7, 0x76, 0xB9, 0x50, 0x57, 0x02, 0x00, 0x02, 0x20, 0x01, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/patch_prog.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/patch_prog.c deleted file mode 100644 index fd128928..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/patch_prog.c +++ /dev/null @@ -1,414 +0,0 @@ -#include -#include -#include "cc3000_common.h" -#include "nvmem.h" -#include "ccspi.h" -#include "hci.h" -#include "wlan.h" -#include "patch_prog.h" -#define BIT0 0x1 -#define BIT1 0x2 -#define BIT2 0x4 -#define BIT3 0x8 -#define BIT4 0x10 -#define BIT5 0x20 -#define BIT6 0x40 -#define BIT7 0x80 - -static unsigned char ucStatus_Dr; -static unsigned char ucStatus_FW; -static unsigned char return_status = 0xFF; - -static signed char mac_status = -1; -static unsigned char counter = 0; - -// Array to store RM parameters from EEPROM. -static unsigned char cRMParamsFromEeprom[128]; -// Array to store MAC address from EEPROM. -static unsigned char cMacFromEeprom[MAC_ADDR_LEN]; -// Smart Config Prefix -static const char aucCC3000_prefix[] = {'T', 'T', 'T'}; - -static void systick_sleep(unsigned long ms) { - extern void HAL_Delay(volatile uint32_t Delay); - HAL_Delay(ms); -} - -// 2 dim array to store address and length of new FAT -static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] = -/* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830}, -/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}}; -/* 0. NVS */ -/* 1. NVS Shadow */ -/* 2. Wireless Conf */ -/* 3. Wireless Conf Shadow */ -/* 4. BT (WLAN driver) Patches */ -/* 5. WiLink (Firmware) Patches */ -/* 6. MAC addr */ -/* 7. Frontend Vars */ -/* 8. IP config */ -/* 9. IP config Shadow */ -/* 10. Bootloader Patches */ -/* 11. Radio Module params */ -/* 12. AES128 for smart config */ -/* 13. user file */ -/* 14. user file */ -/* 15. user file */ - -//***************************************************************************** -// -//! sendDriverPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the driver patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendDriverPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - - -//***************************************************************************** -// -//! sendBootLoaderPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the boot loader patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendBootLoaderPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - -//***************************************************************************** -// -//! sendWLFWPatch -//! -//! \param pointer to the length -//! -//! \return none -//! -//! \brief The function returns a pointer to the FW patch: -//! since there is no patch yet - it returns 0 -// -//***************************************************************************** - -static char *sendWLFWPatch(unsigned long *Length) -{ - *Length = 0; - return NULL; -} - -//***************************************************************************** -// -//! CC3000_UsynchCallback -//! -//! \param Event type -//! -//! \return none -//! -//! \brief The function handles asynchronous events that come from CC3000 -//! device and operates a LED4 to have an on-board indication -// -//***************************************************************************** - -static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length) -{ - -} - -//***************************************************************************** -// -//! initDriver -//! -//! \param[in] cRequestPatch 0 to load with EEPROM patches -//! and 1 to load with no patches -//! -//! \return none -//! -//! \brief The function initializes a CC3000 device -//! and triggers it to start operation -// -//***************************************************************************** -static int initDriver(unsigned short cRequestPatch) -{ - // WLAN On API Implementation - wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, - ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin); - - // Trigger a WLAN device - wlan_start(cRequestPatch); - wlan_smart_config_set_prefix((char*)aucCC3000_prefix); - wlan_ioctl_set_connection_policy(0, 0, 0); - wlan_ioctl_del_profile(255); - - // Mask out all non-required events from CC3000 - wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE| - HCI_EVNT_WLAN_UNSOL_INIT| - HCI_EVNT_WLAN_ASYNC_PING_REPORT); - - //unsolicicted_events_timer_init(); - systick_sleep(100); - return(0); -} - - -//***************************************************************************** -// -//! fat_read_content -//! -//! \param[out] is_allocated array of is_allocated in FAT table:\n -//! an allocated entry implies the address and length of the -//! file are valid. -//! 0: not allocated; 1: allocated. -//! \param[out] is_valid array of is_valid in FAT table:\n -//! a valid entry implies the content of the file is relevant. -//! 0: not valid; 1: valid. -//! \param[out] write_protected array of write_protected in FAT table:\n -//! a write protected entry implies it is not possible to write -//! into this entry. -//! 0: not protected; 1: protected. -//! \param[out] file_address array of file address in FAT table:\n -//! this is the absolute address of the file in the EEPROM. -//! \param[out] file_length array of file length in FAT table:\n -//! this is the upper limit of the file size in the EEPROM. -//! -//! \return on succes 0, error otherwise -//! -//! \brief parse the FAT table from eeprom -// -//***************************************************************************** -static unsigned char __attribute__ ((unused)) -fat_read_content(unsigned char *is_allocated, unsigned char *is_valid, - unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length) -{ - unsigned short index; - unsigned char ucStatus; - unsigned char fatTable[48]; - unsigned char* fatTablePtr = fatTable; - - // - // Read in 6 parts to work with tiny driver - // - for (index = 0; index < 6; index++) - { - ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr); - fatTablePtr += 8; - } - - fatTablePtr = fatTable; - - for (index = 0; index <= NVMEM_RM_FILEID; index++) - { - *is_allocated++ = (*fatTablePtr) & BIT0; - *is_valid++ = ((*fatTablePtr) & BIT1) >> 1; - *write_protected++ = ((*fatTablePtr) & BIT2) >> 2; - *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7); - *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7); - - // - // Move to next file ID - // - fatTablePtr += 4; - } - - return ucStatus; -} - -//***************************************************************************** -// -//! fat_write_content -//! -//! \param[in] file_address array of file address in FAT table:\n -//! this is the absolute address of the file in the EEPROM. -//! \param[in] file_length array of file length in FAT table:\n -//! this is the upper limit of the file size in the EEPROM. -//! -//! \return on succes 0, error otherwise -//! -//! \brief parse the FAT table from eeprom -// -//***************************************************************************** -static unsigned char fat_write_content(unsigned short const *file_address, - unsigned short const *file_length) -{ - unsigned short index = 0; - unsigned char ucStatus; - unsigned char fatTable[48]; - unsigned char* fatTablePtr = fatTable; - - // - // First, write the magic number. - // - ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS"); - - for (; index <= NVMEM_RM_FILEID; index++) - { - // - // Write address low char and mark as allocated. - // - *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0; - - // - // Write address high char. - // - *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff); - - // - // Write length low char. - // - *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff); - - // - // Write length high char. - // - *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff); - } - - // - // Second, write the FAT. - // Write in two parts to work with tiny driver. - // - ucStatus = nvmem_write(16, 24, 4, fatTable); - ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]); - - // - // Third, we want to erase any user files. - // - memset(fatTable, 0, sizeof(fatTable)); - ucStatus = nvmem_write(16, 16, 52, fatTable); - - return ucStatus; -} - -void patch_prog_start() -{ - unsigned short index; - unsigned char *pRMParams; - - printf("Initializing module...\n"); - - // Init module and request to load with no patches. - // This is in order to overwrite restrictions to - // write to specific places in EEPROM. - initDriver(1); - - // Read MAC address. - mac_status = nvmem_get_mac_address(cMacFromEeprom); - - return_status = 1; - - printf("Reading RM parameters...\n"); - while ((return_status) && (counter < 3)) { - // Read RM parameters. - // Read in 16 parts to work with tiny driver. - return_status = 0; - pRMParams = cRMParamsFromEeprom; - for (index = 0; index < 16; index++) { - return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams); - pRMParams += 8; - } - counter++; - } - - // If RM file is not valid, load the default one. - if (counter == 3) { - printf("RM is not valid, loading default one...\n"); - pRMParams = (unsigned char *)cRMdefaultParams; - } else { - printf("RM is valid.\n"); - pRMParams = cRMParamsFromEeprom; - } - - return_status = 1; - - printf("Writing new FAT\n"); - while (return_status) { - // Write new FAT. - return_status = fat_write_content(aFATEntries[0], aFATEntries[1]); - } - - return_status = 1; - - printf("Writing RM parameters...\n"); - while (return_status) { - // Write RM parameters. - // Write in 4 parts to work with tiny driver. - return_status = 0; - - for (index = 0; index < 4; index++) { - return_status |= nvmem_write(NVMEM_RM_FILEID, - 32, - 32*index, - (pRMParams + 32*index)); - } - } - - return_status = 1; - - // Write back the MAC address, only if exists. - if (mac_status == 0) { - // Zero out MCAST bit if set. - cMacFromEeprom[0] &= 0xfe; - printf("Writing back MAC address..\n"); - while (return_status) { - return_status = nvmem_set_mac_address(cMacFromEeprom); - } - } - - // Update driver - ucStatus_Dr = 1; - printf("Updating driver patch...\n"); - while (ucStatus_Dr) { - // Writing driver patch to EEPRROM - PROTABLE CODE - // Note that the array itself is changing between the - // different Service Packs. - ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID, - drv_length, - wlan_drv_patch); - } - - // Update firmware - ucStatus_FW = 1; - printf("Updating firmware patch...\n"); - while (ucStatus_FW) { - // Writing FW patch to EEPRROM - PROTABLE CODE - // Note that the array itself is changing between the - // different Service Packs. - ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID, - fw_length, - fw_patch); - } - - printf("Update complete, resetting module\n"\ - "If this doesn't work, reset manually...\n"); - - wlan_stop(); - systick_sleep(500); - - // Re-Init module and request to load with patches. - initDriver(0); - - // If MAC does not exist, it is recommended - // that the user will write a valid mac address. - if (mac_status != 0) { - printf("MAC address is not valid, please write a new one\n"); - } - - // Patch update done - printf("All done, call wlan.patch_version()\n"); -} diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/security.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/security.c deleted file mode 100644 index 62b4f881..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/security.c +++ /dev/null @@ -1,530 +0,0 @@ -/***************************************************************************** -* -* security.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup security_api -//! @{ -// -//***************************************************************************** - -#include "security.h" - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -// foreward sbox -const UINT8 sbox[256] = { -//0 1 2 3 4 5 6 7 8 9 A B C D E F -0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 -0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 -0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 -0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 -0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 -0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 -0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 -0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 -0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 -0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 -0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A -0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B -0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C -0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D -0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E -0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F -// inverse sbox -const UINT8 rsbox[256] = -{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb -, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb -, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e -, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 -, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 -, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 -, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 -, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b -, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 -, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e -, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b -, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 -, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f -, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef -, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 -, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; -// round constant -const UINT8 Rcon[11] = { - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; - - -UINT8 expandedKey[176]; - -//***************************************************************************** -// -//! expandKey -//! -//! @param key AES128 key - 16 bytes -//! @param expandedKey expanded AES128 key -//! -//! @return none -//! -//! @brief expend a 16 bytes key for AES128 implementation -//! -//***************************************************************************** - -void expandKey(UINT8 *expandedKey, UINT8 *key) -{ - UINT16 ii, buf1; - for (ii=0;ii<16;ii++) - expandedKey[ii] = key[ii]; - for (ii=1;ii<11;ii++){ - buf1 = expandedKey[ii*16 - 4]; - expandedKey[ii*16 + 0] = sbox[expandedKey[ii*16 - 3]]^expandedKey[(ii-1)*16 + 0]^Rcon[ii]; - expandedKey[ii*16 + 1] = sbox[expandedKey[ii*16 - 2]]^expandedKey[(ii-1)*16 + 1]; - expandedKey[ii*16 + 2] = sbox[expandedKey[ii*16 - 1]]^expandedKey[(ii-1)*16 + 2]; - expandedKey[ii*16 + 3] = sbox[buf1 ]^expandedKey[(ii-1)*16 + 3]; - expandedKey[ii*16 + 4] = expandedKey[(ii-1)*16 + 4]^expandedKey[ii*16 + 0]; - expandedKey[ii*16 + 5] = expandedKey[(ii-1)*16 + 5]^expandedKey[ii*16 + 1]; - expandedKey[ii*16 + 6] = expandedKey[(ii-1)*16 + 6]^expandedKey[ii*16 + 2]; - expandedKey[ii*16 + 7] = expandedKey[(ii-1)*16 + 7]^expandedKey[ii*16 + 3]; - expandedKey[ii*16 + 8] = expandedKey[(ii-1)*16 + 8]^expandedKey[ii*16 + 4]; - expandedKey[ii*16 + 9] = expandedKey[(ii-1)*16 + 9]^expandedKey[ii*16 + 5]; - expandedKey[ii*16 +10] = expandedKey[(ii-1)*16 +10]^expandedKey[ii*16 + 6]; - expandedKey[ii*16 +11] = expandedKey[(ii-1)*16 +11]^expandedKey[ii*16 + 7]; - expandedKey[ii*16 +12] = expandedKey[(ii-1)*16 +12]^expandedKey[ii*16 + 8]; - expandedKey[ii*16 +13] = expandedKey[(ii-1)*16 +13]^expandedKey[ii*16 + 9]; - expandedKey[ii*16 +14] = expandedKey[(ii-1)*16 +14]^expandedKey[ii*16 +10]; - expandedKey[ii*16 +15] = expandedKey[(ii-1)*16 +15]^expandedKey[ii*16 +11]; - } - -} - -//***************************************************************************** -// -//! galois_mul2 -//! -//! @param value argument to multiply -//! -//! @return multiplied argument -//! -//! @brief multiply by 2 in the galois field -//! -//***************************************************************************** - -UINT8 galois_mul2(UINT8 value) -{ - if (value>>7) - { - value = value << 1; - return (value^0x1b); - } else - return value<<1; -} - -//***************************************************************************** -// -//! aes_encr -//! -//! @param[in] expandedKey expanded AES128 key -//! @param[in/out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief internal implementation of AES128 encryption. -//! straight forward aes encryption implementation -//! first the group of operations -//! - addRoundKey -//! - subbytes -//! - shiftrows -//! - mixcolums -//! is executed 9 times, after this addroundkey to finish the 9th -//! round, after that the 10th round without mixcolums -//! no further subfunctions to save cycles for function calls -//! no structuring with "for (....)" to save cycles. -//! -//! -//***************************************************************************** - -void aes_encr(UINT8 *state, UINT8 *expandedKey) -{ - UINT8 buf1, buf2, buf3, round; - - for (round = 0; round < 9; round ++){ - // addroundkey, sbox and shiftrows - // row 0 - state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; - state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; - state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; - state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; - // row 1 - buf1 = state[1] ^ expandedKey[(round*16) + 1]; - state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; - state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; - state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; - state[13] = sbox[buf1]; - // row 2 - buf1 = state[2] ^ expandedKey[(round*16) + 2]; - buf2 = state[6] ^ expandedKey[(round*16) + 6]; - state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; - state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; - state[10] = sbox[buf1]; - state[14] = sbox[buf2]; - // row 3 - buf1 = state[15] ^ expandedKey[(round*16) + 15]; - state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; - state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; - state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; - state[ 3] = sbox[buf1]; - - // mixcolums ////////// - // col1 - buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; - buf2 = state[0]; - buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; - buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; - buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; - buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; - // col2 - buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; - buf2 = state[4]; - buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; - buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; - buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; - buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; - // col3 - buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; - buf2 = state[8]; - buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; - buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; - buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; - buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; - // col4 - buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; - buf2 = state[12]; - buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; - buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; - buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; - buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; - - } - // 10th round without mixcols - state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])]; - state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])]; - state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])]; - state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])]; - // row 1 - buf1 = state[1] ^ expandedKey[(round*16) + 1]; - state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])]; - state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])]; - state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])]; - state[13] = sbox[buf1]; - // row 2 - buf1 = state[2] ^ expandedKey[(round*16) + 2]; - buf2 = state[6] ^ expandedKey[(round*16) + 6]; - state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])]; - state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])]; - state[10] = sbox[buf1]; - state[14] = sbox[buf2]; - // row 3 - buf1 = state[15] ^ expandedKey[(round*16) + 15]; - state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])]; - state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])]; - state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])]; - state[ 3] = sbox[buf1]; - // last addroundkey - state[ 0]^=expandedKey[160]; - state[ 1]^=expandedKey[161]; - state[ 2]^=expandedKey[162]; - state[ 3]^=expandedKey[163]; - state[ 4]^=expandedKey[164]; - state[ 5]^=expandedKey[165]; - state[ 6]^=expandedKey[166]; - state[ 7]^=expandedKey[167]; - state[ 8]^=expandedKey[168]; - state[ 9]^=expandedKey[169]; - state[10]^=expandedKey[170]; - state[11]^=expandedKey[171]; - state[12]^=expandedKey[172]; - state[13]^=expandedKey[173]; - state[14]^=expandedKey[174]; - state[15]^=expandedKey[175]; -} - -//***************************************************************************** -// -//! aes_decr -//! -//! @param[in] expandedKey expanded AES128 key -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief internal implementation of AES128 decryption. -//! straight forward aes decryption implementation -//! the order of substeps is the exact reverse of decryption -//! inverse functions: -//! - addRoundKey is its own inverse -//! - rsbox is inverse of sbox -//! - rightshift instead of leftshift -//! - invMixColumns = barreto + mixColumns -//! no further subfunctions to save cycles for function calls -//! no structuring with "for (....)" to save cycles -//! -//***************************************************************************** - -void aes_decr(UINT8 *state, UINT8 *expandedKey) -{ - UINT8 buf1, buf2, buf3; - INT8 round; - round = 9; - - // initial addroundkey - state[ 0]^=expandedKey[160]; - state[ 1]^=expandedKey[161]; - state[ 2]^=expandedKey[162]; - state[ 3]^=expandedKey[163]; - state[ 4]^=expandedKey[164]; - state[ 5]^=expandedKey[165]; - state[ 6]^=expandedKey[166]; - state[ 7]^=expandedKey[167]; - state[ 8]^=expandedKey[168]; - state[ 9]^=expandedKey[169]; - state[10]^=expandedKey[170]; - state[11]^=expandedKey[171]; - state[12]^=expandedKey[172]; - state[13]^=expandedKey[173]; - state[14]^=expandedKey[174]; - state[15]^=expandedKey[175]; - - // 10th round without mixcols - state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; - state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; - state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; - state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; - // row 1 - buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; - state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; - state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; - state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; - state[ 1] = buf1; - // row 2 - buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; - buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; - state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; - state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; - state[10] = buf1; - state[14] = buf2; - // row 3 - buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; - state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; - state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; - state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; - state[15] = buf1; - - for (round = 8; round >= 0; round--){ - // barreto - //col1 - buf1 = galois_mul2(galois_mul2(state[0]^state[2])); - buf2 = galois_mul2(galois_mul2(state[1]^state[3])); - state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2; - //col2 - buf1 = galois_mul2(galois_mul2(state[4]^state[6])); - buf2 = galois_mul2(galois_mul2(state[5]^state[7])); - state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2; - //col3 - buf1 = galois_mul2(galois_mul2(state[8]^state[10])); - buf2 = galois_mul2(galois_mul2(state[9]^state[11])); - state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2; - //col4 - buf1 = galois_mul2(galois_mul2(state[12]^state[14])); - buf2 = galois_mul2(galois_mul2(state[13]^state[15])); - state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2; - // mixcolums ////////// - // col1 - buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; - buf2 = state[0]; - buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; - buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; - buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; - buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; - // col2 - buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; - buf2 = state[4]; - buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; - buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; - buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; - buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; - // col3 - buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; - buf2 = state[8]; - buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; - buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; - buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; - buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; - // col4 - buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; - buf2 = state[12]; - buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; - buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; - buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; - buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; - - // addroundkey, rsbox and shiftrows - // row 0 - state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ]; - state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4]; - state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8]; - state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12]; - // row 1 - buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1]; - state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13]; - state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9]; - state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5]; - state[ 1] = buf1; - // row 2 - buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10]; - buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14]; - state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2]; - state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6]; - state[10] = buf1; - state[14] = buf2; - // row 3 - buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15]; - state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3]; - state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7]; - state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11]; - state[15] = buf1; - } - -} - -//***************************************************************************** -// -//! aes_encrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of plain text and cipher text -//! -//! @return none -//! -//! @brief AES128 encryption: -//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes -//! is computed. The AES implementation is in mode ECB (Electronic -//! Code Book). -//! -//! -//***************************************************************************** - -void aes_encrypt(UINT8 *state, UINT8 *key) -{ - // expand the key into 176 bytes - expandKey(expandedKey, key); - aes_encr(state, expandedKey); -} - -//***************************************************************************** -// -//! aes_decrypt -//! -//! @param[in] key AES128 key of size 16 bytes -//! @param[in\out] state 16 bytes of cipher text and plain text -//! -//! @return none -//! -//! @brief AES128 decryption: -//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes -//! is computed The AES implementation is in mode ECB -//! (Electronic Code Book). -//! -//! -//***************************************************************************** - -void aes_decrypt(UINT8 *state, UINT8 *key) -{ - expandKey(expandedKey, key); // expand the key into 176 bytes - aes_decr(state, expandedKey); -} - -//***************************************************************************** -// -//! aes_read_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief Reads AES128 key from EEPROM -//! Reads the AES128 key from fileID #12 in EEPROM -//! returns an error if the key does not exist. -//! -//! -//***************************************************************************** - -INT32 aes_read_key(UINT8 *key) -{ - INT32 returnValue; - - returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); - - return returnValue; -} - -//***************************************************************************** -// -//! aes_write_key -//! -//! @param[out] key AES128 key of size 16 bytes -//! -//! @return on success 0, error otherwise. -//! -//! @brief writes AES128 key from EEPROM -//! Writes the AES128 key to fileID #12 in EEPROM -//! -//! -//***************************************************************************** - -INT32 aes_write_key(UINT8 *key) -{ - INT32 returnValue; - - returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); - - return returnValue; -} - -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/socket.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/socket.c deleted file mode 100644 index ddd7e56e..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/socket.c +++ /dev/null @@ -1,1182 +0,0 @@ -/***************************************************************************** -* -* socket.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup socket_api -//! @{ -// -//***************************************************************************** - -#include -#include -#include "hci.h" -#include "socket.h" -#include "evnt_handler.h" -#include "netapp.h" - - - -//Enable this flag if and only if you must comply with BSD socket -//close() function -#ifdef _API_USE_BSD_CLOSE -#define close(sd) closesocket(sd) -#endif - -//Enable this flag if and only if you must comply with BSD socket read() and -//write() functions -#ifdef _API_USE_BSD_READ_WRITE -#define read(sd, buf, len, flags) recv(sd, buf, len, flags) -#define write(sd, buf, len, flags) send(sd, buf, len, flags) -#endif - -#define SOCKET_OPEN_PARAMS_LEN (12) -#define SOCKET_CLOSE_PARAMS_LEN (4) -#define SOCKET_ACCEPT_PARAMS_LEN (4) -#define SOCKET_BIND_PARAMS_LEN (20) -#define SOCKET_LISTEN_PARAMS_LEN (8) -#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9) -#define SOCKET_CONNECT_PARAMS_LEN (20) -#define SOCKET_SELECT_PARAMS_LEN (44) -#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20) -#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12) -#define SOCKET_RECV_FROM_PARAMS_LEN (12) -#define SOCKET_SENDTO_PARAMS_LEN (24) -#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12) -#define SOCKET_GET_MSS_VALUE_PARAMS_LEN (4) - -// The legnth of arguments for the SEND command: sd + buff_offset + len + flags, -// while size of each parameter is 32 bit - so the total length is 16 bytes; - -#define HCI_CMND_SEND_ARG_LENGTH (16) - - -#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000 - -#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5) - -#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) - -#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32) - - -//***************************************************************************** -// -//! HostFlowControlConsumeBuff -//! -//! @param sd socket descriptor -//! -//! @return 0 in case there are buffers available, -//! -1 in case of bad socket -//! -2 if there are no free buffers present (only when -//! SEND_NON_BLOCKING is enabled) -//! -//! @brief if SEND_NON_BLOCKING not define - block until have free buffer -//! becomes available, else return immediately with correct status -//! regarding the buffers available. -// -//***************************************************************************** -static INT16 HostFlowControlConsumeBuff(INT16 sd) -{ -#ifndef SEND_NON_BLOCKING - /* wait in busy loop */ - do - { - // In case last transmission failed then we will return the last failure - // reason here. - // Note that the buffer will not be allocated in this case - if (tSLInformation.slTransmitDataError != 0) - { - CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; - tSLInformation.slTransmitDataError = 0; - return CC3000_EXPORT(errno); - } - - if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) - return -1; - } while(0 == tSLInformation.usNumberOfFreeBuffers); - - tSLInformation.usNumberOfFreeBuffers--; - - return 0; -#else - - // In case last transmission failed then we will return the last failure - // reason here. - // Note that the buffer will not be allocated in this case - if (tSLInformation.slTransmitDataError != 0) - { - CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError; - tSLInformation.slTransmitDataError = 0; - return CC3000_EXPORT(errno); - } - if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) - return -1; - - //If there are no available buffers, return -2. It is recommended to use - // select or receive to see if there is any buffer occupied with received data - // If so, call receive() to release the buffer. - if(0 == tSLInformation.usNumberOfFreeBuffers) - { - return -2; - } - else - { - tSLInformation.usNumberOfFreeBuffers--; - return 0; - } -#endif -} - -//***************************************************************************** -// -//! socket -//! -//! @param domain selects the protocol family which will be used for -//! communication. On this version only AF_INET is supported -//! @param type specifies the communication semantics. On this version -//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported -//! @param protocol specifies a particular protocol to be used with the -//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are -//! supported. -//! -//! @return On success, socket handle that is used for consequent socket -//! operations. On error, -1 is returned. -//! -//! @brief create an endpoint for communication -//! The socket function creates a socket that is bound to a specific -//! transport service provider. This function is called by the -//! application layer to obtain a socket handle. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, domain); - args = UINT32_TO_STREAM(args, type); - args = UINT32_TO_STREAM(args, protocol); - - // Initiate a HCI command - hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret); - - // Process the event - CC3000_EXPORT(errno) = ret; - - set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); - - return(ret); -} - -//***************************************************************************** -// -//! closesocket -//! -//! @param sd socket handle. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief The socket function closes a created socket. -// -//***************************************************************************** - -INT32 CC3000_EXPORT(closesocket)(INT32 sd) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_CLOSE_SOCKET, - ptr, SOCKET_CLOSE_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret); - CC3000_EXPORT(errno) = ret; - - // since 'close' call may result in either OK (and then it closed) or error - // mark this socket as invalid - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - - return(ret); -} - -//***************************************************************************** -// -//! accept -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr the argument addr is a pointer to a sockaddr structure -//! This structure is filled in with the address of the -//! peer socket, as known to the communications layer. -//! determined. The exact format of the address returned -//! addr is by the socket's address sockaddr. -//! On this version only AF_INET is supported. -//! This argument returns in network order. -//! @param[out] addrlen the addrlen argument is a value-result argument: -//! it should initially contain the size of the structure -//! pointed to by addr. -//! -//! @return For socket in blocking mode: -//! On success, socket handle. on failure negative -//! For socket in non-blocking mode: -//! - On connection establishment, socket handle -//! - On connection pending, SOC_IN_PROGRESS (-2) -//! - On failure, SOC_ERROR (-1) -//! -//! @brief accept a connection on a socket: -//! This function is used with connection-based socket types -//! (SOCK_STREAM). It extracts the first connection request on the -//! queue of pending connections, creates a new connected socket, and -//! returns a new file descriptor referring to that socket. -//! The newly created socket is not in the listening state. -//! The original socket sd is unaffected by this call. -//! The argument sd is a socket that has been created with socket(), -//! bound to a local address with bind(), and is listening for -//! connections after a listen(). The argument addr is a pointer -//! to a sockaddr structure. This structure is filled in with the -//! address of the peer socket, as known to the communications layer. -//! The exact format of the address returned addr is determined by the -//! socket's address family. The addrlen argument is a value-result -//! argument: it should initially contain the size of the structure -//! pointed to by addr, on return it will contain the actual -//! length (in bytes) of the address returned. -//! -//! @sa socket ; bind ; listen -// -//***************************************************************************** - -INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - tBsdReturnParams tAcceptReturnArguments; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_ACCEPT, - ptr, SOCKET_ACCEPT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments); - - - // need specify return parameters!!! - memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN); - *addrlen = ASIC_ADDR_LEN; - CC3000_EXPORT(errno) = tAcceptReturnArguments.iStatus; - ret = CC3000_EXPORT(errno); - - // if succeeded, iStatus = new socket descriptor. otherwise - error number - if(M_IS_VALID_SD(ret)) - { - set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); - } - else - { - set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); - } - - return(ret); -} - -//***************************************************************************** -// -//! bind -//! -//! @param[in] sd socket descriptor (handle) -//! @param[out] addr specifies the destination address. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr. -//! -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief assign a name to a socket -//! This function gives the socket the local address addr. -//! addr is addrlen bytes long. Traditionally, this is called when a -//! socket is created with socket, it exists in a name space (address -//! family) but has no name assigned. -//! It is necessary to assign a local address before a SOCK_STREAM -//! socket may receive connections. -//! -//! @sa socket ; accept ; listen -// -//***************************************************************************** - -INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - addrlen = ASIC_ADDR_LEN; - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, addrlen); - ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_BIND, - ptr, SOCKET_BIND_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); - - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! listen -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] backlog specifies the listen queue depth. On this version -//! backlog is not supported. -//! @return On success, zero is returned. On error, -1 is returned. -//! -//! @brief listen for connections on a socket -//! The willingness to accept incoming connections and a queue -//! limit for incoming connections are specified with listen(), -//! and then the connections are accepted with accept. -//! The listen() call applies only to sockets of type SOCK_STREAM -//! The backlog parameter defines the maximum length the queue of -//! pending connections may grow to. -//! -//! @sa socket ; accept ; bind -//! -//! @note On this version, backlog is not supported -// -//***************************************************************************** - -INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, backlog); - - // Initiate a HCI command - hci_command_send(HCI_CMND_LISTEN, - ptr, SOCKET_LISTEN_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! gethostbyname -//! -//! @param[in] hostname host name -//! @param[in] usNameLen name length -//! @param[out] out_ip_addr This parameter is filled in with host IP address. -//! In case that host name is not resolved, -//! out_ip_addr is zero. -//! @return On success, positive is returned. On error, negative is returned -//! -//! @brief Get host IP by name. Obtain the IP Address of machine on network, -//! by its name. -//! -//! @note On this version, only blocking mode is supported. Also note that -//! the function requires DNS server to be configured prior to its usage. -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, - UINT32* out_ip_addr) -{ - tBsdGethostbynameParams ret; - UINT8 *ptr, *args; - - CC3000_EXPORT(errno) = EFAIL; - - if (usNameLen > HOSTNAME_MAX_LENGTH) - { - return CC3000_EXPORT(errno); - } - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, 8); - args = UINT32_TO_STREAM(args, usNameLen); - ARRAY_TO_STREAM(args, hostname, usNameLen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN - + usNameLen - 1); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret); - - CC3000_EXPORT(errno) = ret.retVal; - - (*((INT32*)out_ip_addr)) = ret.outputAddress; - - return CC3000_EXPORT(errno); - -} -#endif - -//***************************************************************************** -// -//! connect -//! -//! @param[in] sd socket descriptor (handle) -//! @param[in] addr specifies the destination addr. On this version -//! only AF_INET is supported. -//! @param[out] addrlen contains the size of the structure pointed to by addr -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief initiate a connection on a socket -//! Function connects the socket referred to by the socket descriptor -//! sd, to the address specified by addr. The addrlen argument -//! specifies the size of addr. The format of the address in addr is -//! determined by the address space of the socket. If it is of type -//! SOCK_DGRAM, this call specifies the peer with which the socket is -//! to be associated; this address is that to which datagrams are to be -//! sent, and the only address from which datagrams are to be received. -//! If the socket is of type SOCK_STREAM, this call attempts to make a -//! connection to another socket. The other socket is specified by -//! address, which is an address in the communications space of the -//! socket. Note that the function implements only blocking behavior -//! thus the caller will be waiting either for the connection -//! establishment or for the connection establishment failure. -//! -//! @sa socket -// -//***************************************************************************** - -INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - addrlen = 8; - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, addrlen); - ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_CONNECT, - ptr, SOCKET_CONNECT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); - - CC3000_EXPORT(errno) = ret; - - return((INT32)ret); -} - - -//***************************************************************************** -// -//! select -//! -//! @param[in] nfds the highest-numbered file descriptor in any of the -//! three sets, plus 1. -//! @param[out] writesds socket descriptors list for write monitoring -//! @param[out] readsds socket descriptors list for read monitoring -//! @param[out] exceptsds socket descriptors list for exception monitoring -//! @param[in] timeout is an upper bound on the amount of time elapsed -//! before select() returns. Null means infinity -//! timeout. The minimum timeout is 5 milliseconds, -//! less than 5 milliseconds will be set -//! automatically to 5 milliseconds. -//! @return On success, select() returns the number of file descriptors -//! contained in the three returned descriptor sets (that is, the -//! total number of bits that are set in readfds, writefds, -//! exceptfds) which may be zero if the timeout expires before -//! anything interesting happens. -//! On error, -1 is returned. -//! *readsds - return the sockets on which Read request will -//! return without delay with valid data. -//! *writesds - return the sockets on which Write request -//! will return without delay. -//! *exceptsds - return the sockets which closed recently. -//! -//! @brief Monitor socket activity -//! Select allow a program to monitor multiple file descriptors, -//! waiting until one or more of the file descriptors become -//! "ready" for some class of I/O operation -//! -//! @Note If the timeout value set to less than 5ms it will automatically set -//! to 5ms to prevent overload of the system -//! -//! @sa socket -// -//***************************************************************************** - -INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, -struct cc3000_timeval *timeout) -{ - UINT8 *ptr, *args; - tBsdSelectRecvParams tParams; - UINT32 is_blocking; - - if( timeout == NULL) - { - is_blocking = 1; /* blocking , infinity timeout */ - } - else - { - is_blocking = 0; /* no blocking, timeout */ - } - - // Fill in HCI packet structure - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, nfds); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, is_blocking); - args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0)); - args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0)); - args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0)); - - if (timeout) - { - if ( 0 == timeout->tv_sec && timeout->tv_usec < - SELECT_TIMEOUT_MIN_MICRO_SECONDS) - { - timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS; - } - args = UINT32_TO_STREAM(args, timeout->tv_sec); - args = UINT32_TO_STREAM(args, timeout->tv_usec); - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams); - - // Update actually read FD - if (tParams.iStatus >= 0) - { - if (readsds) - { - memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd)); - } - - if (writesds) - { - memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); - } - - if (exceptsds) - { - memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); - } - - return(tParams.iStatus); - - } - else - { - CC3000_EXPORT(errno) = tParams.iStatus; - return(-1); - } -} - -//***************************************************************************** -// -//! setsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[in] optval specifies a value for the option -//! @param[in] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa getsockopt -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval, - socklen_t optlen) -{ - INT32 ret; - UINT8 *ptr, *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, level); - args = UINT32_TO_STREAM(args, optname); - args = UINT32_TO_STREAM(args, 0x00000008); - args = UINT32_TO_STREAM(args, optlen); - ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen); - - // Initiate a HCI command - hci_command_send(HCI_CMND_SETSOCKOPT, - ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret); - - if (ret >= 0) - { - return (0); - } - else - { - CC3000_EXPORT(errno) = ret; - return ret; - } -} -#endif - -//***************************************************************************** -// -//! getsockopt -//! -//! @param[in] sd socket handle -//! @param[in] level defines the protocol level for this option -//! @param[in] optname defines the option name to Interrogate -//! @param[out] optval specifies a value for the option -//! @param[out] optlen specifies the length of the option value -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief set socket options -//! This function manipulate the options associated with a socket. -//! Options may exist at multiple protocol levels; they are always -//! present at the uppermost socket level. -//! When manipulating socket options the level at which the option -//! resides and the name of the option must be specified. -//! To manipulate options at the socket level, level is specified as -//! SOL_SOCKET. To manipulate options at any other level the protocol -//! number of the appropriate protocol controlling the option is -//! supplied. For example, to indicate that an option is to be -//! interpreted by the TCP protocol, level should be set to the -//! protocol number of TCP; -//! The parameters optval and optlen are used to access optval - -//! use for setsockopt(). For getsockopt() they identify a buffer -//! in which the value for the requested option(s) are to -//! be returned. For getsockopt(), optlen is a value-result -//! parameter, initially containing the size of the buffer -//! pointed to by option_value, and modified on return to -//! indicate the actual size of the value returned. If no option -//! value is to be supplied or returned, option_value may be NULL. -//! -//! @Note On this version the following two socket options are enabled: -//! The only protocol level supported in this version -//! is SOL_SOCKET (level). -//! 1. SOCKOPT_RECV_TIMEOUT (optname) -//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout -//! in milliseconds. -//! In that case optval should be pointer to UINT32. -//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on -//! or off. -//! In that case optval should be SOCK_ON or SOCK_OFF (optval). -//! -//! @sa setsockopt -// -//***************************************************************************** - -INT16 CC3000_EXPORT(getsockopt) (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen) -{ - UINT8 *ptr, *args; - tBsdGetSockOptReturnParams tRetParams; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, level); - args = UINT32_TO_STREAM(args, optname); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETSOCKOPT, - ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams); - - if (((INT8)tRetParams.iStatus) >= 0) - { - *optlen = 4; - memcpy(optval, tRetParams.ucOptValue, 4); - return (0); - } - else - { - CC3000_EXPORT(errno) = tRetParams.iStatus; - return CC3000_EXPORT(errno); - } -} - -//***************************************************************************** -// -//! simple_link_recv -//! -//! @param sd socket handle -//! @param buf read buffer -//! @param len buffer length -//! @param flags indicates blocking or non-blocking operation -//! @param from pointer to an address structure indicating source address -//! @param fromlen source address structure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief Read data from socket -//! Return the length of the message on successful completion. -//! If a message is too long to fit in the supplied buffer, -//! excess bytes may be discarded depending on the type of -//! socket the message is received from -// -//***************************************************************************** -static INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen, INT32 opcode) -{ - UINT8 *ptr, *args; - tBsdReadReturnParams tSocketReadEvent; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, len); - args = UINT32_TO_STREAM(args, flags); - - // Generate the read command, and wait for the - hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(opcode, &tSocketReadEvent); - - // In case the number of bytes is more then zero - read data - if (tSocketReadEvent.iNumberOfBytes > 0) - { - // Wait for the data in a synchronous way. Here we assume that the bug is - // big enough to store also parameters of receive from too.... - SimpleLinkWaitData(buf, (UINT8 *)from, (UINT8 *)fromlen); - } - - CC3000_EXPORT(errno) = tSocketReadEvent.iNumberOfBytes; - - return(tSocketReadEvent.iNumberOfBytes); -} - -//***************************************************************************** -// -//! recv -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief function receives a message from a connection-mode socket -//! -//! @sa recvfrom -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags) -{ - return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); -} - -//***************************************************************************** -// -//! recvfrom -//! -//! @param[in] sd socket handle -//! @param[out] buf Points to the buffer where the message should be stored -//! @param[in] len Specifies the length in bytes of the buffer pointed to -//! by the buffer argument. -//! @param[in] flags Specifies the type of message reception. -//! On this version, this parameter is not supported. -//! @param[in] from pointer to an address structure indicating the source -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param[in] fromlen source address tructure size -//! -//! @return Return the number of bytes received, or -1 if an error -//! occurred -//! -//! @brief read data from socket -//! function receives a message from a connection-mode or -//! connectionless-mode socket. Note that raw sockets are not -//! supported. -//! -//! @sa recv -//! -//! @Note On this version, only blocking mode is supported. -// -//***************************************************************************** -INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from, - socklen_t *fromlen) -{ - return(simple_link_recv(sd, buf, len, flags, from, fromlen, - HCI_CMND_RECVFROM)); -} - -//***************************************************************************** -// -//! simple_link_send -//! -//! @param sd socket handle -//! @param buf write buffer -//! @param len buffer length -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating destination -//! address -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an error -//! occurred, or -2 in case there are no free buffers available -//! (only when SEND_NON_BLOCKING is enabled) -//! -//! @brief This function is used to transmit a message to another -//! socket -// -//***************************************************************************** -static INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags, - const sockaddr *to, INT32 tolen, INT32 opcode) -{ - UINT8 uArgSize=0, addrlen; - UINT8 *ptr, *pDataPtr=0, *args; - UINT32 addr_offset=0; - INT16 res; - tBsdReadReturnParams tSocketSendEvent; - - // Check the bsd_arguments - if (0 != (res = HostFlowControlConsumeBuff(sd))) - { - return res; - } - - //Update the number of sent packets - tSLInformation.NumberOfSentPackets++; - - // Allocate a buffer and construct a packet and send it over spi - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_DATA); - - // Update the offset of data and parameters according to the command - switch(opcode) - { - case HCI_CMND_SENDTO: - { - addr_offset = len + sizeof(len) + sizeof(len); - addrlen = 8; - uArgSize = SOCKET_SENDTO_PARAMS_LEN; - pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN; - break; - } - - case HCI_CMND_SEND: - { - tolen = 0; - to = NULL; - uArgSize = HCI_CMND_SEND_ARG_LENGTH; - pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH; - break; - } - - default: - { - break; - } - } - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd)); - args = UINT32_TO_STREAM(args, len); - args = UINT32_TO_STREAM(args, flags); - - if (opcode == HCI_CMND_SENDTO) - { - args = UINT32_TO_STREAM(args, addr_offset); - args = UINT32_TO_STREAM(args, addrlen); - } - - // Copy the data received from user into the TX Buffer - ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len); - - // In case we are using SendTo, copy the to parameters - if (opcode == HCI_CMND_SENDTO) - { - ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen); - } - - // Initiate a HCI command - hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen); - - if (opcode == HCI_CMND_SENDTO) - SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent); - else - SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent); - - return (len); -} - - -//***************************************************************************** -// -//! send -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa sendto -// -//***************************************************************************** - -INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags) -{ - return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); -} - -//***************************************************************************** -// -//! sendto -//! -//! @param sd socket handle -//! @param buf Points to a buffer containing the message to be sent -//! @param len message size in bytes -//! @param flags On this version, this parameter is not supported -//! @param to pointer to an address structure indicating the destination -//! address: sockaddr. On this version only AF_INET is -//! supported. -//! @param tolen destination address structure size -//! -//! @return Return the number of bytes transmitted, or -1 if an -//! error occurred -//! -//! @brief Write data to TCP socket -//! This function is used to transmit a message to another -//! socket. -//! -//! @Note On this version, only blocking mode is supported. -//! -//! @sa send -// -//***************************************************************************** - -INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to, - socklen_t tolen) -{ - return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); -} - -//***************************************************************************** -// -//! mdnsAdvertiser -//! -//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature -//! @param[in] deviceServiceName Service name as part of the published -//! canonical domain name -//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars -//! -//! -//! @return On success, zero is returned, return SOC_ERROR if socket was not -//! opened successfully, or if an error occurred. -//! -//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself. -// -//***************************************************************************** - -INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength) -{ - INT8 ret; - UINT8 *pTxBuffer, *pArgs; - - if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) - { - return EFAIL; - } - - pTxBuffer = tSLInformation.pucTxCommandBuffer; - pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - - // Fill in HCI packet structure - pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); - pArgs = UINT32_TO_STREAM(pArgs, 8); - pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); - ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); - - // Initiate a HCI command - hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret); - - return ret; - -} - - -//***************************************************************************** -// -//! getmssvalue -//! -//! @param[in] sd socket descriptor -//! -//! @return On success, returns the MSS value of a TCP connection -//! -//! @brief Returns the MSS value of a TCP connection according to the socket descriptor -// -//***************************************************************************** -UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd) -{ - UINT8 *ptr, *args; - UINT16 ret; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, sd); - - // Initiate a HCI command - hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN); - - // Since we are in blocking state - wait for event complete - SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret); - - return ret; -} diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/wlan.c b/MicroPython_BUILD/components/micropython/drivers/cc3000/src/wlan.c deleted file mode 100644 index 63859377..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3000/src/wlan.c +++ /dev/null @@ -1,1252 +0,0 @@ -/***************************************************************************** -* -* wlan.c - CC3000 Host Driver Implementation. -* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*****************************************************************************/ - -//***************************************************************************** -// -//! \addtogroup wlan_api -//! @{ -// -//***************************************************************************** - -#include -#include "wlan.h" -#include "hci.h" -#include "ccspi.h" -#include "socket.h" -#include "nvmem.h" -#include "security.h" -#include "evnt_handler.h" - - -volatile sSimplLinkInformation tSLInformation; - -#define SMART_CONFIG_PROFILE_SIZE 67 // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length) - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -UINT8 key[AES128_KEY_SIZE]; -UINT8 profileArray[SMART_CONFIG_PROFILE_SIZE]; -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -/* patches type */ -#define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01 -#define PATCHES_HOST_TYPE_WLAN_FW 0x02 -#define PATCHES_HOST_TYPE_BOOTLOADER 0x03 - -#define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16) -#define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3) -#define ETH_ALEN (6) -#define MAXIMAL_SSID_LENGTH (32) - -#define SL_PATCHES_REQUEST_DEFAULT (0) -#define SL_PATCHES_REQUEST_FORCE_HOST (1) -#define SL_PATCHES_REQUEST_FORCE_NONE (2) - - -#define WLAN_SEC_UNSEC (0) -#define WLAN_SEC_WEP (1) -#define WLAN_SEC_WPA (2) -#define WLAN_SEC_WPA2 (3) - - -#define WLAN_SL_INIT_START_PARAMS_LEN (1) -#define WLAN_PATCH_PARAMS_LENGTH (8) -#define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12) -#define WLAN_DEL_PROFILE_PARAMS_LEN (4) -#define WLAN_SET_MASK_PARAMS_LEN (4) -#define WLAN_SET_SCAN_PARAMS_LEN (100) -#define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4) -#define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24) -#define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36) -#define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44) -#define WLAN_CONNECT_PARAM_LEN (29) -#define WLAN_SMART_CONFIG_START_PARAMS_LEN (4) - - - - -//***************************************************************************** -// -//! SimpleLink_Init_Start -//! -//! @param usPatchesAvailableAtHost flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Send HCI_CMND_SIMPLE_LINK_START to CC3000 -// -//***************************************************************************** -static void SimpleLink_Init_Start(UINT16 usPatchesAvailableAtHost) -{ - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_NONE : SL_PATCHES_REQUEST_DEFAULT)); - - // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000 - hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN); - - SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0); -} - - - -//***************************************************************************** -// -//! wlan_init -//! -//! @param sWlanCB Asynchronous events callback. -//! 0 no event call back. -//! -call back parameters: -//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event, -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event, -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done, -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report, -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR -//! HCI_EVNT_WLAN_KEEPALIVE keepalive. -//! 2) data: pointer to extra data that received by the event -//! (NULL no data). -//! 3) length: data length. -//! -Events with extra data: -//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask, -//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes -//! for DNS server. -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent, -//! 4 bytes Packets received, 4 bytes Min round time, -//! 4 bytes Max round time and 4 bytes for Avg round time. -//! -//! @param sFWPatches 0 no patch or pointer to FW patches -//! @param sDriverPatches 0 no patch or pointer to driver patches -//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches -//! @param sReadWlanInterruptPin init callback. the callback read wlan -//! interrupt status. -//! @param sWlanInterruptEnable init callback. the callback enable wlan -//! interrupt. -//! @param sWlanInterruptDisable init callback. the callback disable wlan -//! interrupt. -//! @param sWriteWlanPin init callback. the callback write value -//! to device pin. -//! -//! @return none -//! -//! @sa wlan_set_event_mask , wlan_start , wlan_stop -//! -//! @brief Initialize wlan driver -//! -//! @warning This function must be called before ANY other wlan driver function -// -//***************************************************************************** - -void wlan_init( tWlanCB sWlanCB, - tFWPatches sFWPatches, - tDriverPatches sDriverPatches, - tBootLoaderPatches sBootLoaderPatches, - tWlanReadInteruptPin sReadWlanInterruptPin, - tWlanInterruptEnable sWlanInterruptEnable, - tWlanInterruptDisable sWlanInterruptDisable, - tWriteWlanPin sWriteWlanPin) -{ - - tSLInformation.sFWPatches = sFWPatches; - tSLInformation.sDriverPatches = sDriverPatches; - tSLInformation.sBootLoaderPatches = sBootLoaderPatches; - - // init io callback - tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin; - tSLInformation.WlanInterruptEnable = sWlanInterruptEnable; - tSLInformation.WlanInterruptDisable = sWlanInterruptDisable; - tSLInformation.WriteWlanPin = sWriteWlanPin; - - //init asynchronous events callback - tSLInformation.sWlanCB= sWlanCB; - - // By default TX Complete events are routed to host too - tSLInformation.InformHostOnTxComplete = 1; -} - -//***************************************************************************** -// -//! SpiReceiveHandler -//! -//! @param pvBuffer - pointer to the received data buffer -//! The function triggers Received event/data processing -//! -//! @param Pointer to the received data -//! @return none -//! -//! @brief The function triggers Received event/data processing. It is -//! called from the SPI library to receive the data -// -//***************************************************************************** -void SpiReceiveHandler(void *pvBuffer) -{ - tSLInformation.usEventOrDataReceived = 1; - tSLInformation.pucReceivedData = (UINT8 *)pvBuffer; - - hci_unsolicited_event_handler(); -} - - -//***************************************************************************** -// -//! wlan_start -//! -//! @param usPatchesAvailableAtHost - flag to indicate if patches available -//! from host or from EEPROM. Due to the -//! fact the patches are burn to the EEPROM -//! using the patch programmer utility, the -//! patches will be available from the EEPROM -//! and not from the host. -//! -//! @return none -//! -//! @brief Start WLAN device. This function asserts the enable pin of -//! the device (WLAN_EN), starting the HW initialization process. -//! The function blocked until device Initialization is completed. -//! Function also configure patches (FW, driver or bootloader) -//! and calls appropriate device callbacks. -//! -//! @Note Prior calling the function wlan_init shall be called. -//! @Warning This function must be called after wlan_init and before any -//! other wlan API -//! @sa wlan_init , wlan_stop -//! -// -//***************************************************************************** -#define TIMEOUT (500000) - -int wlan_start(UINT16 usPatchesAvailableAtHost) -{ - - UINT32 ulSpiIRQState; - UINT32 wlan_timeout; - - tSLInformation.NumberOfSentPackets = 0; - tSLInformation.NumberOfReleasedPackets = 0; - tSLInformation.usRxEventOpcode = 0; - tSLInformation.usNumberOfFreeBuffers = 0; - tSLInformation.usSlBufferLength = 0; - tSLInformation.usBufferSize = 0; - tSLInformation.usRxDataPending = 0; - tSLInformation.slTransmitDataError = 0; - tSLInformation.usEventOrDataReceived = 0; - tSLInformation.pucReceivedData = 0; - - // Allocate the memory for the RX/TX data transactions - tSLInformation.pucTxCommandBuffer = (UINT8 *)wlan_tx_buffer; - - // init spi - SpiOpen(SpiReceiveHandler); - - // Check the IRQ line - ulSpiIRQState = tSLInformation.ReadWlanInterruptPin(); - - // Chip enable: toggle WLAN EN line - tSLInformation.WriteWlanPin( WLAN_ENABLE ); - - wlan_timeout = TIMEOUT; - if (ulSpiIRQState) { - // wait till the IRQ line goes low - while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) - { - } - } - else - { - // wait till the IRQ line goes high and than low - while(tSLInformation.ReadWlanInterruptPin() == 0 && --wlan_timeout) - { - } - - if (wlan_timeout == 0) { - return -1; - } - - wlan_timeout = TIMEOUT; - while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout) - { - } - } - - if (wlan_timeout ==0) { - return -1; - } - - SimpleLink_Init_Start(usPatchesAvailableAtHost); - - // Read Buffer's size and finish - hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0); - SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0); - - return 0; -} - - -//***************************************************************************** -// -//! wlan_stop -//! -//! @param none -//! -//! @return none -//! -//! @brief Stop WLAN device by putting it into reset state. -//! -//! @sa wlan_start -// -//***************************************************************************** - -void wlan_stop(void) -{ - // Chip disable - tSLInformation.WriteWlanPin( WLAN_DISABLE ); - - // Wait till IRQ line goes high... - while(tSLInformation.ReadWlanInterruptPin() == 0) - { - } - - // Free the used by WLAN Driver memory - if (tSLInformation.pucTxCommandBuffer) - { - tSLInformation.pucTxCommandBuffer = 0; - } - - SpiClose(); -} - - -//***************************************************************************** -// -//! wlan_connect -//! -//! @param sec_type security options: -//! WLAN_SEC_UNSEC, -//! WLAN_SEC_WEP (ASCII support only), -//! WLAN_SEC_WPA or WLAN_SEC_WPA2 -//! @param ssid up to 32 bytes and is ASCII SSID of the AP -//! @param ssid_len length of the SSID -//! @param bssid 6 bytes specified the AP bssid -//! @param key up to 32 bytes specified the AP security key -//! @param key_len key length -//! -//! @return On success, zero is returned. On error, negative is returned. -//! Note that even though a zero is returned on success to trigger -//! connection operation, it does not mean that CCC3000 is already -//! connected. An asynchronous "Connected" event is generated when -//! actual association process finishes and CC3000 is connected to -//! the AP. If DHCP is set, An asynchronous "DHCP" event is -//! generated when DHCP process is finish. -//! -//! -//! @brief Connect to AP -//! @warning Please Note that when connection to AP configured with security -//! type WEP, please confirm that the key is set as ASCII and not -//! as HEX. -//! @sa wlan_disconnect -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len, - UINT8 *bssid, UINT8 *key, INT32 key_len) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in command buffer - args = UINT32_TO_STREAM(args, 0x0000001c); - args = UINT32_TO_STREAM(args, ssid_len); - args = UINT32_TO_STREAM(args, ulSecType); - args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); - args = UINT32_TO_STREAM(args, key_len); - args = UINT16_TO_STREAM(args, 0); - - // padding shall be zeroed - if(bssid) - { - ARRAY_TO_STREAM(args, bssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - - ARRAY_TO_STREAM(args, ssid, ssid_len); - - if(key_len && key) - { - ARRAY_TO_STREAM(args, key, key_len); - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + - ssid_len + key_len - 1); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} -#else -INT32 wlan_connect(CHAR *ssid, INT32 ssid_len) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in command buffer - args = UINT32_TO_STREAM(args, 0x0000001c); - args = UINT32_TO_STREAM(args, ssid_len); - args = UINT32_TO_STREAM(args, 0); - args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); - args = UINT32_TO_STREAM(args, 0); - args = UINT16_TO_STREAM(args, 0); - - // padding shall be zeroed - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - ARRAY_TO_STREAM(args, ssid, ssid_len); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + - ssid_len - 1); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} -#endif - -//***************************************************************************** -// -//! wlan_disconnect -//! -//! @return 0 disconnected done, other CC3000 already disconnected -//! -//! @brief Disconnect connection from AP. -//! -//! @sa wlan_connect -// -//***************************************************************************** - -INT32 wlan_disconnect() -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret); - CC3000_EXPORT(errno) = ret; - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_set_connection_policy -//! -//! @param should_connect_to_open_ap enable(1), disable(0) connect to any -//! available AP. This parameter corresponds to the configuration of -//! item # 3 in the brief description. -//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries -//! to connect to the last connected AP. This parameter corresponds -//! to the configuration of item # 1 in the brief description. -//! @param auto_start enable(1), disable(0) auto connect -//! after reset and periodically reconnect if needed. This -//! configuration configures option 2 in the above description. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief When auto is enabled, the device tries to connect according -//! the following policy: -//! 1) If fast connect is enabled and last connection is valid, -//! the device will try to connect to it without the scanning -//! procedure (fast). The last connection will be marked as -//! invalid, due to adding/removing profile. -//! 2) If profile exists, the device will try to connect it -//! (Up to seven profiles). -//! 3) If fast and profiles are not found, and open mode is -//! enabled, the device will try to connect to any AP. -//! * Note that the policy settings are stored in the CC3000 NVMEM. -//! -//! @sa wlan_add_profile , wlan_ioctl_del_profile -// -//***************************************************************************** - -INT32 wlan_ioctl_set_connection_policy(UINT32 should_connect_to_open_ap, - UINT32 ulShouldUseFastConnect, - UINT32 ulUseProfiles) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, should_connect_to_open_ap); - args = UINT32_TO_STREAM(args, ulShouldUseFastConnect); - args = UINT32_TO_STREAM(args, ulUseProfiles); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, - ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_add_profile -//! -//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2 -//! @param ucSsid ssid SSID up to 32 bytes -//! @param ulSsidLen ssid length -//! @param ucBssid bssid 6 bytes -//! @param ulPriority ulPriority profile priority. Lowest priority:0. -//! Important Note: Smartconfig process (in unencrypted mode) -//! stores the profile internally with priority 1, so changing -//! priorities when adding new profiles should be done with extra care -//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security -//! @param ulGroupCipher_TxKeyIndex key index -//! @param ulKeyMgmt KEY management -//! @param ucPf_OrKey security key -//! @param ulPassPhraseLen security key length for WPA\WPA2 -//! -//! @return On success, index (1-7) of the stored profile is returned. -//! On error, -1 is returned. -//! -//! @brief When auto start is enabled, the device connects to -//! station from the profiles table. Up to 7 profiles are supported. -//! If several profiles configured the device choose the highest -//! priority profile, within each priority group, device will choose -//! profile based on security policy, signal strength, etc -//! parameters. All the profiles are stored in CC3000 NVMEM. -//! -//! @sa wlan_ioctl_del_profile -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_add_profile(UINT32 ulSecType, - UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_TxKeyLen, - UINT32 ulGroupCipher_TxKeyIndex, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen) -{ - UINT16 arg_len=0; - INT32 ret; - UINT8 *ptr; - INT32 i = 0; - UINT8 *args; - UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0}; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - args = UINT32_TO_STREAM(args, ulSecType); - - // Setup arguments in accordance with the security type - switch (ulSecType) - { - //OPEN - case WLAN_SEC_UNSEC: - { - args = UINT32_TO_STREAM(args, 0x00000014); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - - arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen; - } - break; - - //WEP - case WLAN_SEC_WEP: - { - args = UINT32_TO_STREAM(args, 0x00000020); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen); - args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); - args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - - for(i = 0; i < 4; i++) - { - UINT8 *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen]; - - ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen); - } - - arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen + - ulPairwiseCipher_Or_TxKeyLen * 4; - - } - break; - - //WPA - //WPA2 - case WLAN_SEC_WPA: - case WLAN_SEC_WPA2: - { - args = UINT32_TO_STREAM(args, 0x00000028); - args = UINT32_TO_STREAM(args, ulSsidLen); - args = UINT16_TO_STREAM(args, 0); - if(ucBssid) - { - ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN); - } - else - { - ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); - } - args = UINT32_TO_STREAM(args, ulPriority); - args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen); - args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex); - args = UINT32_TO_STREAM(args, ulKeyMgmt); - args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen); - args = UINT32_TO_STREAM(args, ulPassPhraseLen); - ARRAY_TO_STREAM(args, ucSsid, ulSsidLen); - ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen); - - arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen; - } - - break; - } - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, - ptr, arg_len); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); - - return(ret); -} -#else -INT32 wlan_add_profile(UINT32 ulSecType, - UINT8* ucSsid, - UINT32 ulSsidLen, - UINT8 *ucBssid, - UINT32 ulPriority, - UINT32 ulPairwiseCipher_Or_TxKeyLen, - UINT32 ulGroupCipher_TxKeyIndex, - UINT32 ulKeyMgmt, - UINT8* ucPf_OrKey, - UINT32 ulPassPhraseLen) -{ - return -1; -} -#endif - -//***************************************************************************** -// -//! wlan_ioctl_del_profile -//! -//! @param index number of profile to delete -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Delete WLAN profile -//! -//! @Note In order to delete all stored profile, set index to 255. -//! -//! @sa wlan_add_profile -// -//***************************************************************************** - -INT32 wlan_ioctl_del_profile(UINT32 ulIndex) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulIndex); - ret = EFAIL; - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, - ptr, WLAN_DEL_PROFILE_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_get_scan_results -//! -//! @param[in] scan_timeout parameter not supported -//! @param[out] ucResults scan results (_wlan_full_scan_results_args_t) -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Gets entry from scan result table. -//! The scan results are returned one by one, and each entry -//! represents a single AP found in the area. The following is a -//! format of the scan result: -//! - 4 Bytes: number of networks found -//! - 4 Bytes: The status of the scan: 0 - aged results, -//! 1 - results valid, 2 - no results -//! - 42 bytes: Result entry, where the bytes are arranged as follows: -//! -//! - 1 bit isValid - is result valid or not -//! - 7 bits rssi - RSSI value; -//! - 2 bits: securityMode - security mode of the AP: -//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 -//! - 6 bits: SSID name length -//! - 2 bytes: the time at which the entry has entered into -//! scans result table -//! - 32 bytes: SSID name -//! - 6 bytes: BSSID -//! -//! @Note scan_timeout, is not supported on this version. -//! -//! @sa wlan_ioctl_set_scan_params -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout, - UINT8 *ucResults) -{ - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, ulScanTimeout); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, - ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults); - - return(0); -} -#endif - -//***************************************************************************** -// -//! wlan_ioctl_set_scan_params -//! -//! @param uiEnable - start/stop application scan: -//! 1 = start scan with default interval value of 10 min. -//! in order to set a different scan interval value apply the value -//! in milliseconds. minimum 1 second. 0=stop). Wlan reset -//! (wlan_stop() wlan_start()) is needed when changing scan interval -//! value. Saved: No -//! @param uiMinDwellTime minimum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 20) -//! @param uiMaxDwellTime maximum dwell time value to be used for each -//! channel, in milliseconds. Saved: yes -//! Recommended Value: 100 (Default: 30) -//! @param uiNumOfProbeRequests max probe request between dwell time. -//! Saved: yes. Recommended Value: 5 (Default:2) -//! @param uiChannelMask bitwise, up to 13 channels (0x1fff). -//! Saved: yes. Default: 0x7ff -//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80) -//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0) -//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205) -//! @param aiIntervalList pointer to array with 16 entries (16 channels) -//! each entry (UINT32) holds timeout between periodic scan -//! (connection scan) - in millisecond. Saved: yes. Default 2000ms. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief start and stop scan procedure. Set scan parameters. -//! -//! @Note uiDefaultTxPower, is not supported on this version. -//! -//! @sa wlan_ioctl_get_scan_results -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime, - UINT32 uiMaxDwellTime, - UINT32 uiNumOfProbeRequests, - UINT32 uiChannelMask,INT32 iRSSIThreshold, - UINT32 uiSNRThreshold, - UINT32 uiDefaultTxPower, - UINT32 *aiIntervalList) -{ - UINT32 uiRes; - UINT8 *ptr; - UINT8 *args; - - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - // Fill in temporary command buffer - args = UINT32_TO_STREAM(args, 36); - args = UINT32_TO_STREAM(args, uiEnable); - args = UINT32_TO_STREAM(args, uiMinDwellTime); - args = UINT32_TO_STREAM(args, uiMaxDwellTime); - args = UINT32_TO_STREAM(args, uiNumOfProbeRequests); - args = UINT32_TO_STREAM(args, uiChannelMask); - args = UINT32_TO_STREAM(args, iRSSIThreshold); - args = UINT32_TO_STREAM(args, uiSNRThreshold); - args = UINT32_TO_STREAM(args, uiDefaultTxPower); - ARRAY_TO_STREAM(args, aiIntervalList, sizeof(UINT32) * - SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE); - - // Initiate a HCI command - hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, - ptr, WLAN_SET_SCAN_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes); - - return(uiRes); -} -#endif - -//***************************************************************************** -// -//! wlan_set_event_mask -//! -//! @param mask mask option: -//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event -//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event -//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done -//! HCI_EVNT_WLAN_UNSOL_INIT init done -//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report -//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report -//! HCI_EVNT_WLAN_KEEPALIVE keepalive -//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission -//! Saved: no. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Mask event according to bit mask. In case that event is -//! masked (1), the device will not send the masked event to host. -// -//***************************************************************************** - -INT32 wlan_set_event_mask(UINT32 ulMask) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - - if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE) - { - tSLInformation.InformHostOnTxComplete = 0; - - // Since an event is a virtual event - i.e. it is not coming from CC3000 - // there is no need to send anything to the device if it was an only event - if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE) - { - return 0; - } - - ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE; - ulMask |= HCI_EVNT_WLAN_UNSOL_BASE; - } - else - { - tSLInformation.InformHostOnTxComplete = 1; - } - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, ulMask); - - // Initiate a HCI command - hci_command_send(HCI_CMND_EVENT_MASK, - ptr, WLAN_SET_MASK_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_ioctl_statusget -//! -//! @param none -//! -//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING, -//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED -//! -//! @brief get wlan status: disconnected, scanning, connecting or connected -// -//***************************************************************************** - -#ifndef CC3000_TINY_DRIVER -INT32 wlan_ioctl_statusget(void) -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET, - ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret); - - return(ret); -} -#endif - -//***************************************************************************** -// -//! wlan_smart_config_start -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Start to acquire device profile. The device acquire its own -//! profile, if profile message is found. The acquired AP information -//! is stored in CC3000 EEPROM only in case AES128 encryption is used. -//! In case AES128 encryption is not used, a profile is created by -//! CC3000 internally. -//! -//! @Note An asynchronous event - Smart Config Done will be generated as soon -//! as the process finishes successfully. -//! -//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop -// -//***************************************************************************** - -INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (UINT8 *)(ptr + HEADERS_SIZE_CMD); - - // Fill in HCI packet structure - args = UINT32_TO_STREAM(args, algoEncryptedFlag); - ret = EFAIL; - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr, - WLAN_SMART_CONFIG_START_PARAMS_LEN); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_stop -//! -//! @param algoEncryptedFlag indicates whether the information is encrypted -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Stop the acquire profile procedure -//! -//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix -// -//***************************************************************************** - -INT32 wlan_smart_config_stop(void) -{ - INT32 ret; - UINT8 *ptr; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_set_prefix -//! -//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config. -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief Configure station ssid prefix. The prefix is used internally -//! in CC3000. It should always be TTT. -//! -//! @Note The prefix is stored in CC3000 NVMEM -//! -//! @sa wlan_smart_config_start , wlan_smart_config_stop -// -//***************************************************************************** - -INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix) -{ - INT32 ret; - UINT8 *ptr; - UINT8 *args; - - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); - - if (cNewPrefix == NULL) - return ret; - else // with the new Smart Config, prefix must be TTT - { - *cNewPrefix = 'T'; - *(cNewPrefix + 1) = 'T'; - *(cNewPrefix + 2) = 'T'; - } - - ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH); - - hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr, - SL_SIMPLE_CONFIG_PREFIX_LENGTH); - - // Wait for command complete event - SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret); - - return(ret); -} - -//***************************************************************************** -// -//! wlan_smart_config_process -//! -//! @param none -//! -//! @return On success, zero is returned. On error, -1 is returned -//! -//! @brief process the acquired data and store it as a profile. The acquired -//! AP information is stored in CC3000 EEPROM encrypted. -//! The encrypted data is decrypted and stored as a profile. -//! behavior is as defined by connection policy. -// -//***************************************************************************** - - -#ifndef CC3000_UNENCRYPTED_SMART_CONFIG -INT32 wlan_smart_config_process() -{ - INT32 returnValue; - UINT32 ssidLen, keyLen; - UINT8 *decKeyPtr; - UINT8 *ssidPtr; - - // read the key from EEPROM - fileID 12 - returnValue = aes_read_key(key); - - if (returnValue != 0) - return returnValue; - - // read the received data from fileID #13 and parse it according to the followings: - // 1) SSID LEN - not encrypted - // 2) SSID - not encrypted - // 3) KEY LEN - not encrypted. always 32 bytes long - // 4) Security type - not encrypted - // 5) KEY - encrypted together with true key length as the first byte in KEY - // to elaborate, there are two corner cases: - // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length - // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31 - returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray); - - if (returnValue != 0) - return returnValue; - - ssidPtr = &profileArray[1]; - - ssidLen = profileArray[0]; - - decKeyPtr = &profileArray[profileArray[0] + 3]; - - aes_decrypt(decKeyPtr, key); - if (profileArray[profileArray[0] + 1] > 16) - aes_decrypt((UINT8 *)(decKeyPtr + 16), key); - - if (*(UINT8 *)(decKeyPtr +31) != 0) - { - if (*decKeyPtr == 31) - { - keyLen = 31; - decKeyPtr++; - } - else - { - keyLen = 32; - } - } - else - { - keyLen = *decKeyPtr; - decKeyPtr++; - } - - // add a profile - switch (profileArray[profileArray[0] + 2]) - { - case WLAN_SEC_UNSEC://None - { - returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type - ssidPtr, // SSID - ssidLen, // SSID length - NULL, // BSSID - 1, // Priority - 0, 0, 0, 0, 0); - - break; - } - - case WLAN_SEC_WEP://WEP - { - returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type - ssidPtr, // SSID - ssidLen, // SSID length - NULL, // BSSID - 1, // Priority - keyLen, // KEY length - 0, // KEY index - 0, - decKeyPtr, // KEY - 0); - - break; - } - - case WLAN_SEC_WPA://WPA - case WLAN_SEC_WPA2://WPA2 - { - returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type - ssidPtr, - ssidLen, - NULL, // BSSID - 1, // Priority - 0x18, // PairwiseCipher - 0x1e, // GroupCipher - 2, // KEY management - decKeyPtr, // KEY - keyLen); // KEY length - - break; - } - } - - return returnValue; -} -#endif //CC3000_UNENCRYPTED_SMART_CONFIG - -//***************************************************************************** -// -// Close the Doxygen group. -//! @} -// -//***************************************************************************** diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/device.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/device.h deleted file mode 100644 index 169736da..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/device.h +++ /dev/null @@ -1,656 +0,0 @@ -/* - * device.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef __DEVICE_H__ -#define __DEVICE_H__ - - - -#ifdef __cplusplus -extern "C" { -#endif - - - -/*! - - \addtogroup device - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - - -/* SL internal Error codes */ - -/* Receive this error in case there are no resources to issue the command - If possible, increase the number of MAX_CUNCURENT_ACTIONS (result in memory increase) - If not, try again later */ -#define SL_POOL_IS_EMPTY (-2000) - -/* Receive this error in case a given length for RX buffer was too small. - Receive payload was bigger than the given buffer size. Therefore, payload is cut according to receive size - Recommend to increase buffer size */ -#define SL_ESMALLBUF (-2001) - -/* Receive this error in case zero length is supplied to a "get" API - Recommend to supply length according to requested information (view options defines for help) */ -#define SL_EZEROLEN (-2002) - -/* User supplied invalid parameter */ -#define SL_INVALPARAM (-2003) - - -/* Failed to open interface */ -#define SL_BAD_INTERFACE (-2004) - -/* End of SL internal Error codes */ - - - -/*****************************************************************************/ -/* Errors returned from the general error async event */ -/*****************************************************************************/ - -/* Send types */ -typedef enum -{ - SL_ERR_SENDER_HEALTH_MON, - SL_ERR_SENDER_CLI_UART, - SL_ERR_SENDER_SUPPLICANT, - SL_ERR_SENDER_NETWORK_STACK, - SL_ERR_SENDER_WLAN_DRV_IF, - SL_ERR_SENDER_WILINK, - SL_ERR_SENDER_INIT_APP, - SL_ERR_SENDER_NETX, - SL_ERR_SENDER_HOST_APD, - SL_ERR_SENDER_MDNS, - SL_ERR_SENDER_HTTP_SERVER, - SL_ERR_SENDER_DHCP_SERVER, - SL_ERR_SENDER_DHCP_CLIENT, - SL_ERR_DISPATCHER, - SL_ERR_NUM_SENDER_LAST=0xFF -}SlErrorSender_e; - - -/* Error codes */ -#define SL_ERROR_STATIC_ADDR_SUBNET_ERROR (-60) /* network stack error*/ -#define SL_ERROR_ILLEGAL_CHANNEL (-61) /* supplicant error */ -#define SL_ERROR_SUPPLICANT_ERROR (-72) /* init error code */ -#define SL_ERROR_HOSTAPD_INIT_FAIL (-73) /* init error code */ -#define SL_ERROR_HOSTAPD_INIT_IF_FAIL (-74) /* init error code */ -#define SL_ERROR_WLAN_DRV_INIT_FAIL (-75) /* init error code */ -#define SL_ERROR_WLAN_DRV_START_FAIL (-76) /* wlan start error */ -#define SL_ERROR_FS_FILE_TABLE_LOAD_FAILED (-77) /* init file system failed */ -#define SL_ERROR_PREFERRED_NETWORKS_FILE_LOAD_FAILED (-78) /* init file system failed */ -#define SL_ERROR_HOSTAPD_BSSID_VALIDATION_ERROR (-79) /* Ap configurations BSSID error */ -#define SL_ERROR_HOSTAPD_FAILED_TO_SETUP_INTERFACE (-80) /* Ap configurations interface error */ -#define SL_ERROR_MDNS_ENABLE_FAIL (-81) /* mDNS enable failed */ -#define SL_ERROR_HTTP_SERVER_ENABLE_FAILED (-82) /* HTTP server enable failed */ -#define SL_ERROR_DHCP_SERVER_ENABLE_FAILED (-83) /* DHCP server enable failed */ -#define SL_ERROR_PREFERRED_NETWORK_LIST_FULL (-93) /* supplicant error */ -#define SL_ERROR_PREFERRED_NETWORKS_FILE_WRITE_FAILED (-94) /* supplicant error */ -#define SL_ERROR_DHCP_CLIENT_RENEW_FAILED (-100) /* DHCP client error */ -/* WLAN Connection management status */ -#define SL_ERROR_CON_MGMT_STATUS_UNSPECIFIED (-102) -#define SL_ERROR_CON_MGMT_STATUS_AUTH_REJECT (-103) -#define SL_ERROR_CON_MGMT_STATUS_ASSOC_REJECT (-104) -#define SL_ERROR_CON_MGMT_STATUS_SECURITY_FAILURE (-105) -#define SL_ERROR_CON_MGMT_STATUS_AP_DEAUTHENTICATE (-106) -#define SL_ERROR_CON_MGMT_STATUS_AP_DISASSOCIATE (-107) -#define SL_ERROR_CON_MGMT_STATUS_ROAMING_TRIGGER (-108) -#define SL_ERROR_CON_MGMT_STATUS_DISCONNECT_DURING_CONNECT (-109) -#define SL_ERROR_CON_MGMT_STATUS_SG_RESELECT (-110) -#define SL_ERROR_CON_MGMT_STATUS_ROC_FAILURE (-111) -#define SL_ERROR_CON_MGMT_STATUS_MIC_FAILURE (-112) -/* end of WLAN connection management error statuses */ -#define SL_ERROR_WAKELOCK_ERROR_PREFIX (-115) /* Wake lock expired */ -#define SL_ERROR_LENGTH_ERROR_PREFIX (-116) /* Uart header length error */ -#define SL_ERROR_MDNS_CREATE_FAIL (-121) /* mDNS create failed */ -#define SL_ERROR_GENERAL_ERROR (-127) - - - -#define SL_DEVICE_GENERAL_CONFIGURATION (1) -#define SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME (11) -#define SL_DEVICE_GENERAL_VERSION (12) -#define SL_DEVICE_STATUS (2) - -/* - Declare the different event group classifications - The SimpleLink device send asynchronous events. Each event has a group - classification according to its nature. -*/ -/* SL_EVENT_CLASS_WLAN connection user events */ -#define SL_WLAN_CONNECT_EVENT (1) -#define SL_WLAN_DISCONNECT_EVENT (2) -/* WLAN Smart Config user events */ -#define SL_WLAN_SMART_CONFIG_COMPLETE_EVENT (3) -#define SL_WLAN_SMART_CONFIG_STOP_EVENT (4) -/* WLAN AP user events */ -#define SL_WLAN_STA_CONNECTED_EVENT (5) -#define SL_WLAN_STA_DISCONNECTED_EVENT (6) -/* WLAN P2P user events */ -#define SL_WLAN_P2P_DEV_FOUND_EVENT (7) -#define SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT (8) -#define SL_WLAN_CONNECTION_FAILED_EVENT (9) -/* SL_EVENT_CLASS_DEVICE user events */ -#define SL_DEVICE_FATAL_ERROR_EVENT (1) -#define SL_DEVICE_ABORT_ERROR_EVENT (2) - -/* SL_EVENT_CLASS_BSD user events */ -#define SL_SOCKET_TX_FAILED_EVENT (1) -#define SL_SOCKET_ASYNC_EVENT (2) -/* SL_EVENT_CLASS_NETAPP user events */ -#define SL_NETAPP_IPV4_IPACQUIRED_EVENT (1) -#define SL_NETAPP_IPV6_IPACQUIRED_EVENT (2) -#define SL_NETAPP_IP_LEASED_EVENT (3) -#define SL_NETAPP_IP_RELEASED_EVENT (4) - -/* Server Events */ -#define SL_NETAPP_HTTPGETTOKENVALUE_EVENT (1) -#define SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT (2) - - -/* - Declare the different event group classifications for sl_DevGet - for getting status indications - */ - -/* Events list to mask/unmask*/ -#define SL_EVENT_CLASS_GLOBAL (0) -#define SL_EVENT_CLASS_DEVICE (1) -#define SL_EVENT_CLASS_WLAN (2) -#define SL_EVENT_CLASS_BSD (3) -#define SL_EVENT_CLASS_NETAPP (4) -#define SL_EVENT_CLASS_NETCFG (5) -#define SL_EVENT_CLASS_FS (6) - - -/****************** DEVICE CLASS status ****************/ -#define EVENT_DROPPED_DEVICE_ASYNC_GENERAL_ERROR (0x00000001L) -#define STATUS_DEVICE_SMART_CONFIG_ACTIVE (0x80000000L) - -/****************** WLAN CLASS status ****************/ -#define EVENT_DROPPED_WLAN_WLANASYNCONNECTEDRESPONSE (0x00000001L) -#define EVENT_DROPPED_WLAN_WLANASYNCDISCONNECTEDRESPONSE (0x00000002L) -#define EVENT_DROPPED_WLAN_STA_CONNECTED (0x00000004L) -#define EVENT_DROPPED_WLAN_STA_DISCONNECTED (0x00000008L) -#define STATUS_WLAN_STA_CONNECTED (0x80000000L) - -/****************** NETAPP CLASS status ****************/ -#define EVENT_DROPPED_NETAPP_IPACQUIRED (0x00000001L) -#define EVENT_DROPPED_NETAPP_IPACQUIRED_V6 (0x00000002L) -#define EVENT_DROPPED_NETAPP_IP_LEASED (0x00000004L) -#define EVENT_DROPPED_NETAPP_IP_RELEASED (0x00000008L) - -/****************** BSD CLASS status ****************/ -#define EVENT_DROPPED_SOCKET_TXFAILEDASYNCRESPONSE (0x00000001L) - -/****************** FS CLASS ****************/ - - - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -#define ROLE_UNKNOWN_ERR (-1) - -#ifdef SL_IF_TYPE_UART -typedef struct -{ - _u32 BaudRate; - _u8 FlowControlEnable; - _u8 CommPort; -} SlUartIfParams_t; -#endif - -typedef struct -{ - _u32 ChipId; - _u32 FwVersion[4]; - _u8 PhyVersion[4]; -}_SlPartialVersion; - -typedef struct -{ - _SlPartialVersion ChipFwAndPhyVersion; - _u32 NwpVersion[4]; - _u16 RomVersion; - _u16 Padding; -}SlVersionFull; - - -typedef struct -{ - _u32 AbortType; - _u32 AbortData; -}sl_DeviceReportAbort; - - -typedef struct -{ - _i8 status; - SlErrorSender_e sender; -}sl_DeviceReport; - -typedef union -{ - sl_DeviceReport deviceEvent; - sl_DeviceReportAbort deviceReport; -} _SlDeviceEventData_u; - -typedef struct -{ - _u32 Event; - _SlDeviceEventData_u EventData; -} SlDeviceEvent_t; - -typedef struct -{ - /* time */ - _u32 sl_tm_sec; - _u32 sl_tm_min; - _u32 sl_tm_hour; - /* date */ - _u32 sl_tm_day; /* 1-31 */ - _u32 sl_tm_mon; /* 1-12 */ - _u32 sl_tm_year; /* YYYY 4 digits */ - _u32 sl_tm_week_day; /* not required */ - _u32 sl_tm_year_day; /* not required */ - _u32 reserved[3]; -}SlDateTime_t; - - -/******************************************************************************/ -/* Type declarations */ -/******************************************************************************/ -typedef void (*P_INIT_CALLBACK)(_u32 Status); - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - \brief Start the SimpleLink device - - This function initialize the communication interface, set the enable pin - of the device, and call to the init complete callback. - - \param[in] pIfHdl Opened Interface Object. In case the interface - must be opened outside the SimpleLink Driver, the - user might give the handler to be used in \n - any access of the communication interface with the - device (UART/SPI). \n - The SimpleLink driver will open an interface port - only if this parameter is null! \n - \param[in] pDevName The name of the device to open. Could be used when - the pIfHdl is null, to transfer information to the - open interface function \n - This pointer could be used to pass additional information to - sl_IfOpen in case it is required (e.g. UART com port name) - \param[in] pInitCallBack Pointer to function that would be called - on completion of the initialization process.\n - If this parameter is NULL the function is - blocked until the device initialization - is completed, otherwise the function returns - immediately. - - \return Returns the current active role (STA/AP/P2P) or an error code: - - ROLE_STA, ROLE_AP, ROLE_P2P in case of success, - otherwise in failure one of the following is return: - - ROLE_STA_ERR (Failure to load MAC/PHY in STA role) - - ROLE_AP_ERR (Failure to load MAC/PHY in AP role) - - ROLE_P2P_ERR (Failure to load MAC/PHY in P2P role) - - - \sa sl_Stop - - \note belongs to \ref basic_api - - \warning This function must be called before any other SimpleLink API is used, or after sl_Stop is called for reinit the device - \par Example: - \code - An example for open interface without callback routine. The interface name and handler are - handled by the sl_IfOpen routine: - - if( sl_Start(NULL, NULL, NULL) < 0 ) - { - LOG("Error opening interface to device\n"); - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_Start) -_i16 sl_Start(const void* pIfHdl, _i8* pDevName, const P_INIT_CALLBACK pInitCallBack); -#endif - -/*! - \brief Stop the SimpleLink device - - This function clears the enable pin of the device, closes the communication \n - interface and invokes the stop complete callback - - \param[in] timeout Stop timeout in msec. Should be used to give the device time to finish \n - any transmission/reception that is not completed when the function was called. \n - Additional options: - - 0 Enter to hibernate immediately \n - - 0xFFFF Host waits for device's response before \n - hibernating, without timeout protection \n - - 0 < Timeout[msec] < 0xFFFF Host waits for device's response before \n - hibernating, with a defined timeout protection \n - This timeout defines the max time to wait. The NWP \n - response can be sent earlier than this timeout. - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_Start - - \note This API will shutdown the device and invoke the "i/f close" function regardless \n - if it was opened implicitly or explicitly. \n - It is up to the platform interface library to properly handle interface close \n - routine \n - belongs to \ref basic_api \n - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Stop) -_i16 sl_Stop(const _u16 timeout); -#endif - - -/*! - \brief Internal function for setting device configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] DeviceSetId configuration id - \param[in] Option configurations option - \param[in] ConfigLen configurations len - \param[in] pValues configurations values - - \sa - \note - \warning - \par Examples: - \code - Setting device time and date example: - - SlDateTime_t dateTime= {0}; - dateTime.sl_tm_day = (_u32)23; // Day of month (DD format) range 1-31 - dateTime.sl_tm_mon = (_u32)6; // Month (MM format) in the range of 1-12 - dateTime.sl_tm_year = (_u32)2014; // Year (YYYY format) - dateTime.sl_tm_hour = (_u32)17; // Hours in the range of 0-23 - dateTime.sl_tm_min = (_u32)55; // Minutes in the range of 0-59 - dateTime.sl_tm_sec = (_u32)22; // Seconds in the range of 0-59 - sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, - SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, - sizeof(SlDateTime_t), - (_u8 *)(&dateTime)); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_DevSet) -_i32 sl_DevSet(const _u8 DeviceSetId ,const _u8 Option,const _u8 ConfigLen,const _u8 *pValues); -#endif - -/*! - \brief Internal function for getting device configurations - \return On success, zero is returned. On error, -1 is - returned - \param[in] DeviceGetId configuration id - example SL_DEVICE_STATUS - \param[out] pOption Get configurations option, example for get status options - - SL_EVENT_CLASS_GLOBAL - - SL_EVENT_CLASS_DEVICE - - SL_EVENT_CLASS_WLAN - - SL_EVENT_CLASS_BSD - - SL_EVENT_CLASS_NETAPP - - SL_EVENT_CLASS_NETCFG - - SL_EVENT_CLASS_FS - \param[out] pConfigLen The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device.\n - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return SL_ESMALLBUF - \param[out] pValues Get configurations values - \sa - \note - \warning - \par Examples: - \code - Example for getting WLAN class status: - _u32 statusWlan; - _u8 pConfigOpt; - _u8 pConfigLen; - pConfigOpt = SL_EVENT_CLASS_WLAN; - pConfigLen = sizeof(_u32); - sl_DevGet(SL_DEVICE_STATUS,&pConfigOpt,&pConfigLen,(_u8 *)(&statusWlan)); - Example for getting version: - SlVersionFull ver; - pConfigLen = sizeof(ver); - pConfigOpt = SL_DEVICE_GENERAL_VERSION; - sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION,&pConfigOpt,&pConfigLen,(_u8 *)(&ver)); - printf("CHIP %d\nMAC 31.%d.%d.%d.%d\nPHY %d.%d.%d.%d\nNWP %d.%d.%d.%d\nROM %d\nHOST %d.%d.%d.%d\n", - ver.ChipFwAndPhyVersion.ChipId, - ver.ChipFwAndPhyVersion.FwVersion[0],ver.ChipFwAndPhyVersion.FwVersion[1], - ver.ChipFwAndPhyVersion.FwVersion[2],ver.ChipFwAndPhyVersion.FwVersion[3], - ver.ChipFwAndPhyVersion.PhyVersion[0],ver.ChipFwAndPhyVersion.PhyVersion[1], - ver.ChipFwAndPhyVersion.PhyVersion[2],ver.ChipFwAndPhyVersion.PhyVersion[3], - ver.NwpVersion[0],ver.NwpVersion[1],ver.NwpVersion[2],ver.NwpVersion[3], - ver.RomVersion, - SL_MAJOR_VERSION_NUM,SL_MINOR_VERSION_NUM,SL_VERSION_NUM,SL_SUB_VERSION_NUM); - - \endcode - \code - Getting Device time and date example: - - SlDateTime_t dateTime = {0}; - _i8 configLen = sizeof(SlDateTime_t); - _i8 configOpt = SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME; - sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION,&configOpt, &configLen,(_u8 *)(&dateTime)); - - printf("Day %d,Mon %d,Year %d,Hour %,Min %d,Sec %d\n",dateTime.sl_tm_day,dateTime.sl_tm_mon,dateTime.sl_tm_year - dateTime.sl_tm_hour,dateTime.sl_tm_min,dateTime.sl_tm_sec); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_DevGet) -_i32 sl_DevGet(const _u8 DeviceGetId,_u8 *pOption,_u8 *pConfigLen, _u8 *pValues); -#endif - - -/*! - \brief Set asynchronous event mask - - Mask asynchronous events from the device. Masked events do not - generate asynchronous messages from the device. - By default - all events are active - - \param[in] EventClass The classification groups that the - mask is referred to. Need to be one of - the following: - - SL_EVENT_CLASS_GLOBAL - - SL_EVENT_CLASS_DEVICE - - SL_EVENT_CLASS_WLAN - - SL_EVENT_CLASS_BSD - - SL_EVENT_CLASS_NETAPP - - SL_EVENT_CLASS_NETCFG - - SL_EVENT_CLASS_FS - - - \param[in] Mask Event Mask bitmap. Valid mask are (per group): - - SL_EVENT_CLASS_WLAN user events - - SL_WLAN_CONNECT_EVENT - - SL_WLAN_DISCONNECT_EVENT - - SL_EVENT_CLASS_DEVICE user events - - SL_DEVICE_FATAL_ERROR_EVENT - - SL_EVENT_CLASS_BSD user events - - SL_SOCKET_TX_FAILED_EVENT - - SL_SOCKET_ASYNC_EVENT - - SL_EVENT_CLASS_NETAPP user events - - SL_NETAPP_IPV4_IPACQUIRED_EVENT - - SL_NETAPP_IPV6_IPACQUIRED_EVENT - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_EventMaskGet - - \note belongs to \ref ext_api - - \warning - \par Example: - \code - - An example of masking connection/disconnection async events from WLAN class: - sl_EventMaskSet(SL_EVENT_CLASS_WLAN, (SL_WLAN_CONNECT_EVENT | SL_WLAN_DISCONNECT_EVENT) ); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_EventMaskSet) -_i16 sl_EventMaskSet(const _u8 EventClass ,const _u32 Mask); -#endif - -/*! - \brief Get current event mask of the device - - return the events bit mask from the device. In case that event is - masked, the device is not sending this event. - - \param[in] EventClass The classification groups that the - mask is referred to. Need to be one of - the following: - - SL_EVENT_CLASS_GLOBAL - - SL_EVENT_CLASS_DEVICE - - SL_EVENT_CLASS_WLAN - - SL_EVENT_CLASS_BSD - - SL_EVENT_CLASS_NETAPP - - SL_EVENT_CLASS_NETCFG - - SL_EVENT_CLASS_FS - - \param[out] pMask Pointer to Mask bitmap where the - value should be stored. Bitmasks are the same as in \ref sl_EventMaskSet - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_EventMaskSet - - \note belongs to \ref ext_api - - \warning - \par Example: - \code - - An example of getting an event mask for WLAN class - _u32 maskWlan; - sl_StatusGet(SL_EVENT_CLASS_WLAN,&maskWlan); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_EventMaskGet) -_i16 sl_EventMaskGet(const _u8 EventClass,_u32 *pMask); -#endif - - -/*! - \brief the simple link task entry - - \Param - This function must be called from the main loop or from dedicated thread in - the following cases: - - Non-Os Platform - should be called from the mail loop - - Multi Threaded Platform when the user does not implement the external spawn functions - - should be called from dedicated thread allocated to the simplelink driver. - In this mode the function never return. - - \return None - - \sa sl_Stop - - \note belongs to \ref basic_api - - \warning This function must be called from a thread that is start running before - any call to other simple link API -*/ -#if _SL_INCLUDE_FUNC(sl_Task) -void sl_Task(void); -#endif - - -/*! - \brief Setting the internal uart mode - - \param[in] pUartParams Pointer to the uart configuration parameter set: - baudrate - up to 711 Kbps - flow control - enable/disable - comm port - the comm port number - - \return On success zero is returned, otherwise - Failed. - - \sa sl_Stop - - \note belongs to \ref basic_api - - \warning This function must consider the host uart capability -*/ -#ifdef SL_IF_TYPE_UART -#if _SL_INCLUDE_FUNC(sl_UartSetMode) -_i16 sl_UartSetMode(const SlUartIfParams_t* pUartParams); -#endif -#endif - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __DEVICE_H__ */ - - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/driver.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/driver.h deleted file mode 100644 index 4ef484df..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/driver.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * driver.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __DRIVER_INT_H__ -#define __DRIVER_INT_H__ - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#ifndef CPU_FREQ_IN_MHZ - #define CPU_FREQ_IN_MHZ (200) -#endif -#define USEC_DELAY (50) - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -typedef struct -{ - _SlOpcode_t Opcode; - _SlArgSize_t TxDescLen; - _SlArgSize_t RxDescLen; -}_SlCmdCtrl_t; - -typedef struct -{ - _u16 TxPayloadLen; - _i16 RxPayloadLen; - _i16 ActualRxPayloadLen; - _u8 *pTxPayload; - _u8 *pRxPayload; -}_SlCmdExt_t; - - -typedef struct _SlArgsData_t -{ - _u8 *pArgs; - _u8 *pData; -} _SlArgsData_t; - - -typedef struct _SlPoolObj_t -{ - _SlSyncObj_t SyncObj; - _u8 *pRespArgs; - _u8 ActionID; - _u8 AdditionalData; /* use for socketID and one bit which indicate supprt IPV6 or not (1=support, 0 otherwise) */ - _u8 NextIndex; - -} _SlPoolObj_t; - - -typedef enum -{ - SOCKET_0, - SOCKET_1, - SOCKET_2, - SOCKET_3, - SOCKET_4, - SOCKET_5, - SOCKET_6, - SOCKET_7, - MAX_SOCKET_ENUM_IDX, -#ifndef SL_TINY_EXT - ACCEPT_ID = MAX_SOCKET_ENUM_IDX, - CONNECT_ID, -#else - CONNECT_ID = MAX_SOCKET_ENUM_IDX, -#endif -#ifndef SL_TINY_EXT - SELECT_ID, -#endif - GETHOSYBYNAME_ID, -#ifndef SL_TINY_EXT - GETHOSYBYSERVICE_ID, - PING_ID, -#endif - START_STOP_ID, - RECV_ID -}_SlActionID_e; - -typedef struct _SlActionLookup_t -{ - _u8 ActionID; - _u16 ActionAsyncOpcode; - _SlSpawnEntryFunc_t AsyncEventHandler; - -} _SlActionLookup_t; - - -typedef struct -{ - _u8 TxPoolCnt; - _SlLockObj_t TxLockObj; - _SlSyncObj_t TxSyncObj; -}_SlFlowContCB_t; - -typedef enum -{ - RECV_RESP_CLASS, - CMD_RESP_CLASS, - ASYNC_EVT_CLASS, - DUMMY_MSG_CLASS -}_SlRxMsgClass_e; - -typedef struct -{ - _u8 *pAsyncBuf; /* place to write pointer to buffer with CmdResp's Header + Arguments */ - _u8 ActionIndex; - _SlSpawnEntryFunc_t AsyncEvtHandler; /* place to write pointer to AsyncEvent handler (calc-ed by Opcode) */ - _SlRxMsgClass_e RxMsgClass; /* type of Rx message */ -} AsyncExt_t; - -typedef _u8 _SlSd_t; - -typedef struct -{ - _SlCmdCtrl_t *pCmdCtrl; - _u8 *pTxRxDescBuff; - _SlCmdExt_t *pCmdExt; - AsyncExt_t AsyncExt; -}_SlFunctionParams_t; - - -typedef struct -{ - _SlFd_t FD; - _SlLockObj_t GlobalLockObj; - _SlCommandHeader_t TempProtocolHeader; - P_INIT_CALLBACK pInitCallback; - - _SlPoolObj_t ObjPool[MAX_CONCURRENT_ACTIONS]; - _u8 FreePoolIdx; - _u8 PendingPoolIdx; - _u8 ActivePoolIdx; - _u32 ActiveActionsBitmap; - _SlLockObj_t ProtectionLockObj; - - _SlSyncObj_t CmdSyncObj; - _u8 IsCmdRespWaited; - _SlFlowContCB_t FlowContCB; - _u8 TxSeqNum; - _u8 RxDoneCnt; - _u8 SocketNonBlocking; - _u8 SocketTXFailure; - /* for stack reduction the parameters are globals */ - _SlFunctionParams_t FunctionParams; - - _u8 ActionIndex; -}_SlDriverCb_t; - -extern _volatile _u8 RxIrqCnt; - -extern _SlDriverCb_t* g_pCB; -extern P_SL_DEV_PING_CALLBACK pPingCallBackFunc; - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ -extern void _SlDrvDriverCBInit(void); -extern void _SlDrvDriverCBDeinit(void); -extern void _SlDrvRxIrqHandler(void *pValue); -extern _SlReturnVal_t _SlDrvCmdOp(_SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern _SlReturnVal_t _SlDrvCmdSend(_SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern _SlReturnVal_t _SlDrvDataReadOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern _SlReturnVal_t _SlDrvDataWriteOp(_SlSd_t Sd, _SlCmdCtrl_t *pCmdCtrl , void* pTxRxDescBuff , _SlCmdExt_t* pCmdExt); -extern void _sl_HandleAsync_InitComplete(void *pVoidBuf); -extern void _sl_HandleAsync_Connect(void *pVoidBuf); - - -#ifndef SL_TINY_EXT -extern _i16 _SlDrvBasicCmd(_SlOpcode_t Opcode); -extern void _sl_HandleAsync_Accept(void *pVoidBuf); -extern void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf); -extern void _sl_HandleAsync_Select(void *pVoidBuf); -#endif - - -extern void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf); -extern void _sl_HandleAsync_DnsGetHostByAddr(void *pVoidBuf); -extern void _sl_HandleAsync_PingResponse(void *pVoidBuf); -extern void _SlDrvNetAppEventHandler(void* pArgs); -extern void _SlDrvDeviceEventHandler(void* pArgs); -extern void _sl_HandleAsync_Stop(void *pVoidBuf); -extern _u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID); -extern void _SlDrvReleasePoolObj(_u8 pObj); -extern _u16 _SlDrvAlignSize(_u16 msgLen); -extern _u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID); - - -extern void _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj); -extern void _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj); -extern void _SlDrvObjLock(_SlLockObj_t *pLockObj, _SlTime_t Timeout); -extern void _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj); -extern void _SlDrvProtectionObjLockWaitForever(); -extern void _SlDrvObjUnLock(_SlLockObj_t *pLockObj); -extern void _SlDrvProtectionObjUnLock(); - -extern void _SlDrvMemZero(void* Addr, _u16 size); -extern void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt); - - - -#define _SL_PROTOCOL_ALIGN_SIZE(msgLen) (((msgLen)+3) & (~3)) -#define _SL_IS_PROTOCOL_ALIGNED_SIZE(msgLen) (!((msgLen) & 3)) - - -#define _SL_PROTOCOL_CALC_LEN(pCmdCtrl,pCmdExt) ((pCmdExt) ? \ - (_SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen) + _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen)) : \ - (_SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen))) -#endif /* __DRIVER_INT_H__ */ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/flowcont.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/flowcont.h deleted file mode 100644 index 3dcc130d..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/flowcont.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * flowcont.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __FLOWCONT_H__ -#define __FLOWCONT_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define FLOW_CONT_MIN 1 - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ -extern void _SlDrvFlowContInit(void); -extern void _SlDrvFlowContDeinit(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __FLOWCONT_H__ */ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/fs.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/fs.h deleted file mode 100644 index 078feaff..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/fs.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * fs.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ - -#include "simplelink.h" - -#ifndef __FS_H__ -#define __FS_H__ - - - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - - \addtogroup FileSystem - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/* FS error codes */ -#define SL_FS_OK (0) -#define SL_FS_ERR_EMPTY_SFLASH (-67) -#define SL_FS_ERR_FILE_IS_NOT_SECURE_AND_SIGN (-66) -#define SL_FS_ERASING_FLASH (-65) -#define SL_FS_FILE_HAS_NOT_BEEN_CLOSE_CORRECTLY (-64) -#define SL_FS_WRONG_SIGNATURE (-63) -#define SL_FS_WRONG_SIGNATURE_OR_CERTIFIC_NAME_LENGTH (-62) -#define SL_FS_NOT_16_ALIGNED (-61) -#define SL_FS_CERT_CHAIN_ERROR (-60) -#define SL_FS_FILE_NAME_EXIST (-59) -#define SL_FS_SECURITY_BUF_ALREADY_ALLOC (-58) -#define SL_FS_SECURE_FILE_MUST_BE_COMMIT (-57) -#define SL_FS_ERR_INCORRECT_OFFSET_ALIGNMENT (-56) -#define SL_FS_ERR_FAILED_READ_NVMEM_HEADER (-55) -#define SL_FS_WRONG_FILE_NAME (-54) -#define SL_FS_FILE_SYSTEM_IS_LOCKED (-53) -#define SL_FS_SECURITY_ALLERT (-52) -#define SL_FS_FILE_UNVALID_FILE_SIZE (-51) -#define SL_FS_ERR_TOKEN_IS_NOT_VALID (-50) -#define SL_FS_NO_DEVICE_IS_LOADED (-49) -#define SL_FS_DATA_ADDRESS_SHOUD_BE_IN_DATA_RAM (-48) -#define SL_FS_DATA_IS_NOT_ALIGNED (-47) -#define SL_FS_ERR_OVERLAP_DETECTION_THRESHHOLD (-46) -#define SL_FS_FILE_HAS_RESERVED_NV_INDEX (-45) -#define SL_FS_ERR_MAX_FS_FILES_IS_LARGER (-44) -#define SL_FS_ERR_MAX_FS_FILES_IS_SMALLER (-43) -#define SL_FS_FILE_MAX_SIZE_EXCEEDED (-42) -#define SL_FS_INVALID_BUFFER_FOR_READ (-41) -#define SL_FS_INVALID_BUFFER_FOR_WRITE (-40) -#define SL_FS_ERR_FILE_IMAGE_IS_CORRUPTED (-39) -#define SL_FS_ERR_SIZE_OF_FILE_EXT_EXCEEDED (-38) -#define SL_FS_WARNING_FILE_NAME_NOT_KEPT (-37) -#define SL_FS_ERR_DEVICE_IS_NOT_FORMATTED (-36) -#define SL_FS_ERR_FAILED_WRITE_NVMEM_HEADER (-35) -#define SL_FS_ERR_NO_AVAILABLE_NV_INDEX (-34) -#define SL_FS_ERR_FAILED_TO_ALLOCATE_MEM (-33) -#define SL_FS_ERR_FAILED_TO_READ_INTEGRITY_HEADER_2 (-32) -#define SL_FS_ERR_FAILED_TO_READ_INTEGRITY_HEADER_1 (-31) -#define SL_FS_ERR_NO_AVAILABLE_BLOCKS (-30) -#define SL_FS_ERR_FILE_MAX_SIZE_BIGGER_THAN_EXISTING_FILE (-29) -#define SL_FS_ERR_FILE_EXISTS_ON_DIFFERENT_DEVICE_ID (-28) -#define SL_FS_ERR_INVALID_ACCESS_TYPE (-27) -#define SL_FS_ERR_FILE_ALREADY_EXISTS (-26) -#define SL_FS_ERR_PROGRAM (-25) -#define SL_FS_ERR_NO_ENTRIES_AVAILABLE (-24) -#define SL_FS_ERR_FILE_ACCESS_IS_DIFFERENT (-23) -#define SL_FS_ERR_BAD_FILE_MODE (-22) -#define SL_FS_ERR_FAILED_READ_NVFILE (-21) -#define SL_FS_ERR_FAILED_INIT_STORAGE (-20) -#define SL_FS_ERR_CONTINUE_WRITE_MUST_BE_MOD_4 (-19) -#define SL_FS_ERR_FAILED_LOAD_FILE (-18) -#define SL_FS_ERR_INVALID_HANDLE (-17) -#define SL_FS_ERR_FAILED_TO_WRITE (-16) -#define SL_FS_ERR_OFFSET_OUT_OF_RANGE (-15) -#define SL_FS_ERR_ALLOC (-14) -#define SL_FS_ERR_READ_DATA_LENGTH (-13) -#define SL_FS_ERR_INVALID_FILE_ID (-12) -#define SL_FS_ERR_FILE_NOT_EXISTS (-11) -#define SL_FS_ERR_EMPTY_ERROR (-10) -#define SL_FS_ERR_INVALID_ARGS (-9) -#define SL_FS_ERR_FAILED_TO_CREATE_FILE (-8) -#define SL_FS_ERR_FS_ALREADY_LOADED (-7) -#define SL_FS_ERR_UNKNOWN (-6) -#define SL_FS_ERR_FAILED_TO_CREATE_LOCK_OBJ (-5) -#define SL_FS_ERR_DEVICE_NOT_LOADED (-4) -#define SL_FS_ERR_INVALID_MAGIC_NUM (-3) -#define SL_FS_ERR_FAILED_TO_READ (-2) -#define SL_FS_ERR_NOT_SUPPORTED (-1) -/* end of error codes */ - -#define _FS_MODE_ACCESS_RESERVED_OFFSET (24) -#define _FS_MODE_ACCESS_RESERVED_MASK (0xFF) -#define _FS_MODE_ACCESS_FLAGS_OFFSET (16) -#define _FS_MODE_ACCESS_FLAGS_MASK (0xFF) -#define _FS_MODE_ACCESS_OFFSET (12) -#define _FS_MODE_ACCESS_MASK (0xF) -#define _FS_MODE_OPEN_SIZE_GRAN_OFFSET (8) -#define _FS_MODE_OPEN_SIZE_GRAN_MASK (0xF) -#define _FS_MODE_OPEN_SIZE_OFFSET (0) -#define _FS_MODE_OPEN_SIZE_MASK (0xFF) -#define MAX_MODE_SIZE (0xFF) -#define _FS_MODE(Access, SizeGran, Size,Flags) (_u32)(((_u32)((Access) & _FS_MODE_ACCESS_MASK)<<_FS_MODE_ACCESS_OFFSET) | \ - ((_u32)((SizeGran) & _FS_MODE_OPEN_SIZE_GRAN_MASK)<<_FS_MODE_OPEN_SIZE_GRAN_OFFSET) | \ - ((_u32)((Size) & _FS_MODE_OPEN_SIZE_MASK)<<_FS_MODE_OPEN_SIZE_OFFSET) | \ - ((_u32)((Flags) & _FS_MODE_ACCESS_FLAGS_MASK)<<_FS_MODE_ACCESS_FLAGS_OFFSET)) - - -/* sl_FsOpen options */ -/* Open for Read */ -#define FS_MODE_OPEN_READ _FS_MODE(_FS_MODE_OPEN_READ,0,0,0) -/* Open for Write (in case file exist) */ -#define FS_MODE_OPEN_WRITE _FS_MODE(_FS_MODE_OPEN_WRITE,0,0,0) -/* Open for Creating a new file */ -#define FS_MODE_OPEN_CREATE(maxSizeInBytes,accessModeFlags) _sl_GetCreateFsMode(maxSizeInBytes,accessModeFlags) - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ -typedef struct -{ - _u16 flags; - _u32 FileLen; - _u32 AllocatedLen; - _u32 Token[4]; -}SlFsFileInfo_t; - -typedef enum -{ - _FS_MODE_OPEN_READ = 0, - _FS_MODE_OPEN_WRITE, - _FS_MODE_OPEN_CREATE, - _FS_MODE_OPEN_WRITE_CREATE_IF_NOT_EXIST -}SlFsFileOpenAccessType_e; - -typedef enum -{ - _FS_FILE_OPEN_FLAG_COMMIT = 0x1, /* MIRROR - for fail safe */ - _FS_FILE_OPEN_FLAG_SECURE = 0x2, /* SECURE */ - _FS_FILE_OPEN_FLAG_NO_SIGNATURE_TEST = 0x4, /* Relevant to secure file only */ - _FS_FILE_OPEN_FLAG_STATIC = 0x8, /* Relevant to secure file only */ - _FS_FILE_OPEN_FLAG_VENDOR = 0x10, /* Relevant to secure file only */ - _FS_FILE_PUBLIC_WRITE= 0x20, /* Relevant to secure file only, the file can be opened for write without Token */ - _FS_FILE_PUBLIC_READ = 0x40 /* Relevant to secure file only, the file can be opened for read without Token */ -}SlFileOpenFlags_e; - -typedef enum -{ - _FS_MODE_SIZE_GRAN_256B = 0, /* MAX_SIZE = 64K */ - _FS_MODE_SIZE_GRAN_1KB, /* MAX_SIZE = 256K */ - _FS_MODE_SIZE_GRAN_4KB, /* MAX_SZIE = 1M */ - _FS_MODE_SIZE_GRAN_16KB, /* MAX_SIZE = 4M */ - _FS_MODE_SIZE_GRAN_64KB, /* MAX_SIZE = 16M */ - _FS_MAX_MODE_SIZE_GRAN -}_SlFsFileOpenMaxSizeGran_e; - -/*****************************************************************************/ -/* Internal Function prototypes */ -/*****************************************************************************/ -_u32 _sl_GetCreateFsMode(_u32 maxSizeInBytes,_u32 accessFlags); - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - \brief open file for read or write from/to storage device - - \param[in] pFileName File Name buffer pointer - \param[in] AccessModeAndMaxSize Options: As described below - \param[in] pToken Reserved for future use. Use NULL for this field - \param[out] pFileHandle Pointing on the file and used for read and write commands to the file - - AccessModeAndMaxSize possible input \n - FS_MODE_OPEN_READ - Read a file \n - FS_MODE_OPEN_WRITE - Open for write for an existing file \n - FS_MODE_OPEN_CREATE(maxSizeInBytes,accessModeFlags) - Open for creating a new file. Max file size is defined in bytes. \n - For optimal FS size, use max size in 4K-512 bytes steps (e.g. 3584,7680,117760) \n - Several access modes bits can be combined together from SlFileOpenFlags_e enum - - \return On success, zero is returned. On error, an error code is returned - - \sa sl_FsRead sl_FsWrite sl_FsClose - \note belongs to \ref basic_api - \warning - \par Example: - \code - char* DeviceFileName = "MyFile.txt"; - unsigned long MaxSize = 63 * 1024; //62.5K is max file size - long DeviceFileHandle = -1; - long RetVal; //negative retval is an error - unsigned long Offset = 0; - unsigned char InputBuffer[100]; - - // Create a file and write data. The file in this example is secured, without signature and with a fail safe commit - RetVal = sl_FsOpen((unsigned char *)DeviceFileName, - FS_MODE_OPEN_CREATE(MaxSize , _FS_FILE_OPEN_FLAG_NO_SIGNATURE_TEST | _FS_FILE_OPEN_FLAG_COMMIT ), - NULL, &DeviceFileHandle); - - Offset = 0; - //Preferred in secure file that the Offset and the length will be aligned to 16 bytes. - RetVal = sl_FsWrite( DeviceFileHandle, Offset, (unsigned char *)"HelloWorld", strlen("HelloWorld")); - - RetVal = sl_FsClose(DeviceFileHandle, NULL, NULL , 0); - - // open the same file for read, using the Token we got from the creation procedure above - RetVal = sl_FsOpen((unsigned char *)DeviceFileName, - FS_MODE_OPEN_READ, - NULL, &DeviceFileHandle); - - Offset = 0; - RetVal = sl_FsRead( DeviceFileHandle, Offset, (unsigned char *)InputBuffer, strlen("HelloWorld")); - - RetVal = sl_FsClose(DeviceFileHandle, NULL, NULL , 0); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsOpen) -_i32 sl_FsOpen(const _u8 *pFileName,const _u32 AccessModeAndMaxSize,_u32 *pToken,_i32 *pFileHandle); -#endif - -/*! - \brief close file in storage device - - \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) - \param[in] pCeritificateFileName Reserved for future use. Use NULL. - \param[in] pSignature Reserved for future use. Use NULL. - \param[in] SignatureLen Reserved for future use. Use 0. - - - \return On success, zero is returned. On error, an error code is returned - - \sa sl_FsRead sl_FsWrite sl_FsOpen - \note Call the fs_Close with signature = 'A' signature len = 1 for activating an abort action - \warning - \par Example: - \code - sl_FsClose(FileHandle,0,0,0); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsClose) -_i16 sl_FsClose(const _i32 FileHdl,const _u8* pCeritificateFileName,const _u8* pSignature,const _u32 SignatureLen); -#endif - -/*! - \brief Read block of data from a file in storage device - - \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) - \param[in] Offset Offset to specific read block - \param[out] pData Pointer for the received data - \param[in] Len Length of the received data - - \return On success, returns the number of read bytes. On error, negative number is returned - - \sa sl_FsClose sl_FsWrite sl_FsOpen - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsRead(FileHandle, 0, &readBuff[0], readSize); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsRead) -_i32 sl_FsRead(const _i32 FileHdl,_u32 Offset ,_u8* pData,_u32 Len); -#endif - -/*! - \brief write block of data to a file in storage device - - \param[in] FileHdl Pointer to the file (assigned from sl_FsOpen) - \param[in] Offset Offset to specific block to be written - \param[in] pData Pointer the transmitted data to the storage device - \param[in] Len Length of the transmitted data - - \return On success, returns the number of written bytes. On error, an error code is returned - - \sa - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsWrite(FileHandle, 0, &buff[0], readSize); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsWrite) -_i32 sl_FsWrite(const _i32 FileHdl,_u32 Offset,_u8* pData,_u32 Len); -#endif - -/*! - \brief get info on a file - - \param[in] pFileName File name - \param[in] Token Reserved for future use. Use 0 - \param[out] pFsFileInfo Returns the File's Information: flags,file size, allocated size and Tokens - - \return On success, zero is returned. On error, an error code is returned - - \sa sl_FsOpen - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsGetInfo("FileName.html",0,&FsFileInfo); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsGetInfo) -_i16 sl_FsGetInfo(const _u8 *pFileName,const _u32 Token,SlFsFileInfo_t* pFsFileInfo); -#endif - -/*! - \brief Delete specific file from a storage or all files from a storage (format) - - \param[in] pFileName File Name - \param[in] Token Reserved for future use. Use 0 - \return On success, zero is returned. On error, an error code is returned - - \sa - \note belongs to \ref basic_api - \warning - \par Example: - \code - Status = sl_FsDel("FileName.html",0); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_FsDel) -_i16 sl_FsDel(const _u8 *pFileName,const _u32 Token); -#endif -/*! - - Close the Doxygen group. - @} - - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __FS_H__ */ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/netapp.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/netapp.h deleted file mode 100644 index a968e7d0..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/netapp.h +++ /dev/null @@ -1,884 +0,0 @@ -/* - * netapp.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ - -#include "simplelink.h" - -#ifndef __NETAPP_H__ -#define __NETAPP_H__ - - - - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - - \addtogroup netapp - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/*ERROR code*/ -#define SL_ERROR_NETAPP_RX_BUFFER_LENGTH_ERROR (-230) - -/* Http Server interface */ -#define MAX_INPUT_STRING (64) /* because of WPA */ - -#define MAX_AUTH_NAME_LEN (20) -#define MAX_AUTH_PASSWORD_LEN (20) -#define MAX_AUTH_REALM_LEN (20) - -#define MAX_DEVICE_URN_LEN (15+1) -#define MAX_DOMAIN_NAME_LEN (24+1) - -#define MAX_ACTION_LEN (30) -/* Important: in case the max len is changed, make sure the struct sl_NetAppHttpServerSendToken_t in protocol.h is padded correctly! */ -#define MAX_TOKEN_NAME_LEN (20) -#define MAX_TOKEN_VALUE_LEN MAX_INPUT_STRING - -#define NETAPP_MAX_SERVICE_TEXT_SIZE (256) -#define NETAPP_MAX_SERVICE_NAME_SIZE (60) -#define NETAPP_MAX_SERVICE_HOST_NAME_SIZE (64) - - -/* Server Responses */ -#define SL_NETAPP_RESPONSE_NONE (0) -#define SL_NETAPP_HTTPSETTOKENVALUE (1) - -#define SL_NETAPP_FAMILY_MASK (0x80) - -/* mDNS types */ -#define SL_NET_APP_MASK_IPP_TYPE_OF_SERVICE (0x00000001) -#define SL_NET_APP_MASK_DEVICE_INFO_TYPE_OF_SERVICE (0x00000002) -#define SL_NET_APP_MASK_HTTP_TYPE_OF_SERVICE (0x00000004) -#define SL_NET_APP_MASK_HTTPS_TYPE_OF_SERVICE (0x00000008) -#define SL_NET_APP_MASK_WORKSATION_TYPE_OF_SERVICE (0x00000010) -#define SL_NET_APP_MASK_GUID_TYPE_OF_SERVICE (0x00000020) -#define SL_NET_APP_MASK_H323_TYPE_OF_SERVICE (0x00000040) -#define SL_NET_APP_MASK_NTP_TYPE_OF_SERVICE (0x00000080) -#define SL_NET_APP_MASK_OBJECITVE_TYPE_OF_SERVICE (0x00000100) -#define SL_NET_APP_MASK_RDP_TYPE_OF_SERVICE (0x00000200) -#define SL_NET_APP_MASK_REMOTE_TYPE_OF_SERVICE (0x00000400) -#define SL_NET_APP_MASK_RTSP_TYPE_OF_SERVICE (0x00000800) -#define SL_NET_APP_MASK_SIP_TYPE_OF_SERVICE (0x00001000) -#define SL_NET_APP_MASK_SMB_TYPE_OF_SERVICE (0x00002000) -#define SL_NET_APP_MASK_SOAP_TYPE_OF_SERVICE (0x00004000) -#define SL_NET_APP_MASK_SSH_TYPE_OF_SERVICE (0x00008000) -#define SL_NET_APP_MASK_TELNET_TYPE_OF_SERVICE (0x00010000) -#define SL_NET_APP_MASK_TFTP_TYPE_OF_SERVICE (0x00020000) -#define SL_NET_APP_MASK_XMPP_CLIENT_TYPE_OF_SERVICE (0x00040000) -#define SL_NET_APP_MASK_RAOP_TYPE_OF_SERVICE (0x00080000) -#define SL_NET_APP_MASK_ALL_TYPE_OF_SERVICE (0xFFFFFFFF) - -/********************************************************************************************************/ -/* sl_NetAppDnsGetHostByName error codes */ - -#define SL_NET_APP_DNS_QUERY_NO_RESPONSE (-159) /* DNS query failed, no response */ -#define SL_NET_APP_DNS_NO_SERVER (-161) /* No DNS server was specified */ -#define SL_NET_APP_DNS_PARAM_ERROR (-162) /* mDNS parameters error */ -#define SL_NET_APP_DNS_QUERY_FAILED (-163) /* DNS query failed; no DNS server sent an 'answer' */ -#define SL_NET_APP_DNS_INTERNAL_1 (-164) -#define SL_NET_APP_DNS_INTERNAL_2 (-165) -#define SL_NET_APP_DNS_MALFORMED_PACKET (-166) /* Improperly formed or corrupted DNS packet received */ -#define SL_NET_APP_DNS_INTERNAL_3 (-167) -#define SL_NET_APP_DNS_INTERNAL_4 (-168) -#define SL_NET_APP_DNS_INTERNAL_5 (-169) -#define SL_NET_APP_DNS_INTERNAL_6 (-170) -#define SL_NET_APP_DNS_INTERNAL_7 (-171) -#define SL_NET_APP_DNS_INTERNAL_8 (-172) -#define SL_NET_APP_DNS_INTERNAL_9 (-173) -#define SL_NET_APP_DNS_MISMATCHED_RESPONSE (-174) /* Server response type does not match the query request*/ -#define SL_NET_APP_DNS_INTERNAL_10 (-175) -#define SL_NET_APP_DNS_INTERNAL_11 (-176) -#define SL_NET_APP_DNS_NO_ANSWER (-177) /* No response for one-shot query */ -#define SL_NET_APP_DNS_NO_KNOWN_ANSWER (-178) /* No known answer for query */ -#define SL_NET_APP_DNS_NAME_MISMATCH (-179) /* Illegal service name according to the RFC */ -#define SL_NET_APP_DNS_NOT_STARTED (-180) /* mDNS is not running */ -#define SL_NET_APP_DNS_HOST_NAME_ERROR (-181) /* Host name error. Host name format is not allowed according to RFC 1033,1034,1035, 6763 */ -#define SL_NET_APP_DNS_NO_MORE_ENTRIES (-182) /* No more entries be found. */ - -#define SL_NET_APP_DNS_MAX_SERVICES_ERROR (-200) /* Maximum advertise services are already configured */ -#define SL_NET_APP_DNS_IDENTICAL_SERVICES_ERROR (-201) /* Trying to register a service that is already exists */ -#define SL_NET_APP_DNS_NOT_EXISTED_SERVICE_ERROR (-203) /* Trying to delete service that does not existed */ -#define SL_NET_APP_DNS_ERROR_SERVICE_NAME_ERROR (-204) /* Illegal service name according to the RFC */ -#define SL_NET_APP_DNS_RX_PACKET_ALLOCATION_ERROR (-205) /* Retry request */ -#define SL_NET_APP_DNS_BUFFER_SIZE_ERROR (-206) /* List size buffer is bigger than internally allowed in the NWP */ -#define SL_NET_APP_DNS_NET_APP_SET_ERROR (-207) /* Illegal length of one of the mDNS Set functions */ -#define SL_NET_APP_DNS_GET_SERVICE_LIST_FLAG_ERROR (-208) -#define SL_NET_APP_DNS_NO_CONFIGURATION_ERROR (-209) - -/* Set Dev name error codes (NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN) */ -#define SL_ERROR_DEVICE_NAME_LEN_ERR (-117) -#define SL_ERROR_DEVICE_NAME_INVALID (-118) -/* Set domain name error codes (NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME) */ -#define SL_ERROR_DOMAIN_NAME_LEN_ERR (-119) -#define SL_ERROR_DOMAIN_NAME_INVALID (-120) - -/********************************************************************************************************/ - -/* NetApp application IDs */ -#define SL_NET_APP_HTTP_SERVER_ID (1) -#define SL_NET_APP_DHCP_SERVER_ID (2) -#define SL_NET_APP_MDNS_ID (4) -#define SL_NET_APP_DNS_SERVER_ID (8) -#define SL_NET_APP_DEVICE_CONFIG_ID (16) -/* NetApp application set/get options */ -#define NETAPP_SET_DHCP_SRV_BASIC_OPT (0) -/* HTTP server set/get options */ -#define NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER (0) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK (1) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_NAME (2) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD (3) -#define NETAPP_SET_GET_HTTP_OPT_AUTH_REALM (4) -#define NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS (5) - -#define NETAPP_SET_GET_MDNS_CONT_QUERY_OPT (1) -#define NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT (2) -#define NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT (3) - -/* DNS server set/get options */ -#define NETAPP_SET_GET_DNS_OPT_DOMAIN_NAME (0) - -/* Device Config set/get options */ -#define NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN (0) -#define NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME (1) - - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -typedef struct -{ - _u32 PacketsSent; - _u32 PacketsReceived; - _u16 MinRoundTime; - _u16 MaxRoundTime; - _u16 AvgRoundTime; - _u32 TestTime; -}SlPingReport_t; - -typedef struct -{ - _u32 PingIntervalTime; /* delay between pings, in milliseconds */ - _u16 PingSize; /* ping packet size in bytes */ - _u16 PingRequestTimeout; /* timeout time for every ping in milliseconds */ - _u32 TotalNumberOfAttempts; /* max number of ping requests. 0 - forever */ - _u32 Flags; /* flag - 0 report only when finished, 1 - return response for every ping, 2 - stop after 1 successful ping. */ - _u32 Ip; /* IPv4 address or IPv6 first 4 bytes */ - _u32 Ip1OrPaadding; - _u32 Ip2OrPaadding; - _u32 Ip3OrPaadding; -}SlPingStartCommand_t; - -typedef struct _slHttpServerString_t -{ - _u8 len; - _u8 *data; -} slHttpServerString_t; - -typedef struct _slHttpServerData_t -{ - _u8 value_len; - _u8 name_len; - _u8 *token_value; - _u8 *token_name; -} slHttpServerData_t; - -typedef struct _slHttpServerPostData_t -{ - slHttpServerString_t action; - slHttpServerString_t token_name; - slHttpServerString_t token_value; -}slHttpServerPostData_t; - -typedef union -{ - slHttpServerString_t httpTokenName; /* SL_NETAPP_HTTPGETTOKENVALUE */ - slHttpServerPostData_t httpPostData; /* SL_NETAPP_HTTPPOSTTOKENVALUE */ -} SlHttpServerEventData_u; - -typedef union -{ - slHttpServerString_t token_value; -} SlHttpServerResponsedata_u; - -typedef struct -{ - _u32 Event; - SlHttpServerEventData_u EventData; -}SlHttpServerEvent_t; - -typedef struct -{ - _u32 Response; - SlHttpServerResponsedata_u ResponseData; -}SlHttpServerResponse_t; - - -typedef struct -{ - _u32 lease_time; - _u32 ipv4_addr_start; - _u32 ipv4_addr_last; -}SlNetAppDhcpServerBasicOpt_t; - -/*mDNS parameters*/ -typedef enum -{ - SL_NET_APP_FULL_SERVICE_WITH_TEXT_IPV4_TYPE = 1, - SL_NET_APP_FULL_SERVICE_IPV4_TYPE, - SL_NET_APP_SHORT_SERVICE_IPV4_TYPE - -} SlNetAppGetServiceListType_e; - -typedef struct -{ - _u32 service_ipv4; - _u16 service_port; - _u16 Reserved; -}SlNetAppGetShortServiceIpv4List_t; - -typedef struct -{ - _u32 service_ipv4; - _u16 service_port; - _u16 Reserved; - _u8 service_name[NETAPP_MAX_SERVICE_NAME_SIZE]; - _u8 service_host[NETAPP_MAX_SERVICE_HOST_NAME_SIZE]; -}SlNetAppGetFullServiceIpv4List_t; - -typedef struct -{ - _u32 service_ipv4; - _u16 service_port; - _u16 Reserved; - _u8 service_name[NETAPP_MAX_SERVICE_NAME_SIZE]; - _u8 service_host[NETAPP_MAX_SERVICE_HOST_NAME_SIZE]; - _u8 service_text[NETAPP_MAX_SERVICE_TEXT_SIZE]; -}SlNetAppGetFullServiceWithTextIpv4List_t; - -typedef struct -{ - /*The below parameters are used to configure the advertise times and interval - For example: - If: - Period is set to T - Repetitions are set to P - Telescopic factor is K=2 - The transmission shall be: - advertise P times - wait T - advertise P times - wait 4 * T - advertise P time - wait 16 * T ... (till max time reached / configuration changed / query issued) - */ - _u32 t; /* Number of ticks for the initial period. Default is 100 ticks for 1 second. */ - _u32 p; /* Number of repetitions. Default value is 1 */ - _u32 k; /* Telescopic factor. Default value is 2. */ - _u32 RetransInterval;/* Announcing retransmission interval */ - _u32 Maxinterval; /* Announcing max period interval */ - _u32 max_time; /* Announcing max time */ -}SlNetAppServiceAdvertiseTimingParameters_t; - -/*****************************************************************************/ -/* Types declarations */ -/*****************************************************************************/ -typedef void (*P_SL_DEV_PING_CALLBACK)(SlPingReport_t*); - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - - -/*! - \brief Starts a network application - - Gets and starts network application for the current WLAN mode - - \param[in] AppBitMap application bitmap, could be one or combination of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - \return On error, negative number is returned - - \sa Stop one or more the above started applications using sl_NetAppStop - \note This command activates the application for the current WLAN mode (AP or STA) - \warning - \par Example: - \code - For example: Starting internal HTTP server + DHCP server: - sl_NetAppStart(SL_NET_APP_HTTP_SERVER_ID | SL_NET_APP_DHCP_SERVER_ID) - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppStart) -_i16 sl_NetAppStart(const _u32 AppBitMap); -#endif -/*! - \brief Stops a network application - - Gets and stops network application for the current WLAN mode - - \param[in] AppBitMap application id, could be one of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - \return On error, negative number is returned - - \sa - \note This command disables the application for the current active WLAN mode (AP or STA) - \warning - \par Example: - \code - - For example: Stopping internal HTTP server: - sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppStop) -_i16 sl_NetAppStop(const _u32 AppBitMap); -#endif - -/*! - \brief Get host IP by name - - Obtain the IP Address of machine on network, by machine name. - - \param[in] hostname host name - \param[in] usNameLen name length - \param[out] out_ip_addr This parameter is filled in with - host IP address. In case that host name is not - resolved, out_ip_addr is zero. - \param[in] family protocol family - - \return On success, 0 is returned. - On error, negative is returned - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - Possible DNS error codes: - - SL_NET_APP_DNS_QUERY_NO_RESPONSE - - SL_NET_APP_DNS_NO_SERVER - - SL_NET_APP_DNS_QUERY_FAILED - - SL_NET_APP_DNS_MALFORMED_PACKET - - SL_NET_APP_DNS_MISMATCHED_RESPONSE - - \sa - \note Only one sl_NetAppDnsGetHostByName can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - \warning - In case an IP address in a string format is set as input, without any prefix (e.g. "1.2.3.4") the device will not - try to access the DNS and it will return the input address on the 'out_ip_addr' field - \par Example: - \code - _u32 DestinationIP; - sl_NetAppDnsGetHostByName("www.google.com", strlen("www.google.com"), &DestinationIP,SL_AF_INET); - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(80); - Addr.sin_addr.s_addr = sl_Htonl(DestinationIP); - AddrSize = sizeof(SlSockAddrIn_t); - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByName) -_i16 sl_NetAppDnsGetHostByName(_i8 * hostname,const _u16 usNameLen, _u32* out_ip_addr,const _u8 family ); -#endif - -/*! - \brief Return service attributes like IP address, port and text according to service name - \par - The user sets a service name Full/Part (see example below), and should get: - - IP of service - - The port of service - - The text of service - - Hence it can make a connection to the specific service and use it. - It is similar to get host by name method. - It is done by a single shot query with PTR type on the service name. - The command that is sent is from constant parameters and variables parameters. - - \param[in] pService Service name can be full or partial. \n - Example for full service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local \n - . - Example for partial service name: - 1. _ipp._tcp.local - 2. _ftp._tcp.local - - \param[in] ServiceLen The length of the service name (in_pService). - \param[in] Family IPv4 or IPv6 (SL_AF_INET , SL_AF_INET6). - \param[out] pAddr Contains the IP address of the service. - \param[out] pPort Contains the port of the service. - \param[out] pTextLen Has 2 options. One as Input field and the other one as output: - - Input: \n - Contains the max length of the text that the user wants to get.\n - It means that if the text len of service is bigger that its value than - the text is cut to inout_TextLen value. - - Output: \n - Contain the length of the text that is returned. Can be full text or part of the text (see above). - - \param[out] pOut_pText Contains the text of the service full or partial - - \return On success, zero is returned - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - In case No service is found error SL_NET_APP_DNS_NO_ANSWER will be returned - - \note The returns attributes belongs to the first service found. - There may be other services with the same service name that will response to the query. - The results of these responses are saved in the peer cache of the Device and should be read by another API. - - Only one sl_NetAppDnsGetHostByService can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - - \warning Text length can be 120 bytes only -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByService) -_i32 sl_NetAppDnsGetHostByService(_i8 *pServiceName, /* string containing all (or only part): name + subtype + service */ - const _u8 ServiceLen, - const _u8 Family, /* 4-IPv4 , 16-IPv6 */ - _u32 pAddr[], - _u32 *pPort, - _u16 *pTextLen, /* in: max len , out: actual len */ - _i8 *pText - ); - -#endif - -/*! - \brief Get service List - Insert into out pBuffer a list of peer's services that are the NWP. - The list is in a form of service struct. The user should chose the type - of the service struct like: - - Full service parameters with text. - - Full service parameters. - - Short service parameters (port and IP only) especially for tiny hosts. - - The different types of struct are made to give the - Possibility to save memory in the host - - - The user also chose how many max services to get and start point index - NWP peer cache. - For example: - 1. Get max of 3 full services from index 0.Up to 3 full services - from index 0 are inserted into pBuffer (services that are in indexes 0,1,2). - 2. Get max of 4 full services from index 3.Up to 4 full services - from index 3 are inserted into pBuffer (services that are in indexes 3,4,5,6). - 3. Get max of 2 int services from index 6.Up to 2 int services - from index 6 are inserted into pBuffer (services that are in indexes 6,7). - - See below - command parameters. - - \param[in] indexOffset - The start index in the peer cache that from it the first service is returned. - \param[in] MaxServiceCount - The Max services that can be returned if existed or if not exceed the max index - in the peer cache - \param[in] Flags - an ENUM number that means which service struct to use (means which types of service to fill) - - use SlNetAppGetFullServiceWithTextIpv4List_t - - use SlNetAppGetFullServiceIpv4List_t - - use SlNetAppGetShortServiceIpv4List_t - - \param[out] Buffer - The Services are inserted into this buffer. In the struct form according to the bit that is set in the Flags - input parameter. - - \return ServiceFoundCount - The number of the services that were inserted into the buffer. zero means no service is found - negative number means an error - \sa sl_NetAppMDNSRegisterService - \note - \warning - if the out pBuffer size is bigger than an RX packet(1480), than - an error is returned because there - is no place in the RX packet. - The size is a multiply of MaxServiceCount and size of service struct(that is set - according to flag value). -*/ - -#if _SL_INCLUDE_FUNC(sl_NetAppGetServiceList) -_i16 sl_NetAppGetServiceList(const _u8 IndexOffest, - const _u8 MaxServiceCount, - const _u8 Flags, - _i8 *pBuffer, - const _u32 RxBufferLength - ); - -#endif - -/*! - \brief Unregister mDNS service - This function deletes the mDNS service from the mDNS package and the database. - - The mDNS service that is to be unregistered is a service that the application no longer wishes to provide. \n - The service name should be the full service name according to RFC - of the DNS-SD - meaning the value in name field in the SRV answer. - - Examples for service names: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - \param[in] pServiceName Full service name. \n - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - \param[in] ServiceLen The length of the service. - \return On success, zero is returned - \sa sl_NetAppMDNSRegisterService - \note - \warning - The size of the service length should be smaller than 255. -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSUnRegisterService) -_i16 sl_NetAppMDNSUnRegisterService(const _i8 *pServiceName,const _u8 ServiceNameLen); -#endif - -/*! - \brief Register a new mDNS service - \par - This function registers a new mDNS service to the mDNS package and the DB. - - This registered service is a service offered by the application. - The service name should be full service name according to RFC - of the DNS-SD - meaning the value in name field in the SRV answer. - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - If the option is_unique is set, mDNS probes the service name to make sure - it is unique before starting to announce the service on the network. - Instance is the instance portion of the service name. - - \param[in] ServiceLen The length of the service. - \param[in] TextLen The length of the service should be smaller than 64. - \param[in] port The port on this target host port. - \param[in] TTL The TTL of the service - \param[in] Options bitwise parameters: \n - - bit 0 - service is unique (means that the service needs to be unique) - - bit 31 - for internal use if the service should be added or deleted (set means ADD). - - bit 1-30 for future. - - \param[in] pServiceName The service name. - Example for service name: \n - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - \param[in] pText The description of the service. - should be as mentioned in the RFC - (according to type of the service IPP,FTP...) - - \return On success, zero is returned - Possible error codes: - - Maximum advertise services are already configured. - Delete another existed service that is registered and then register again the new service - - Trying to register a service that is already exists - - Trying to delete service that does not existed - - Illegal service name according to the RFC - - Retry request - - Illegal length of one of the mDNS Set functions - - mDNS is not operational as the device has no IP.Connect the device to an AP to get an IP address. - - mDNS parameters error - - mDNS internal cache error - - mDNS internal error - - Adding a service is not allowed as it is already exist (duplicate service) - - mDNS is not running - - Host name error. Host name format is not allowed according to RFC 1033,1034,1035, 6763 - - List size buffer is bigger than internally allowed in the NWP (API get service list), - change the APIs parameters to decrease the size of the list - - - \sa sl_NetAppMDNSUnRegisterService - - \warning 1) Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. \n - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH.\n - If it is - An error is returned. \n - 2) According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterService) -_i16 sl_NetAppMDNSRegisterService( const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - _u32 Options); -#endif - -/*! - \brief send ICMP ECHO_REQUEST to network hosts - - Ping uses the ICMP protocol's mandatory ECHO_REQUEST - - \param[in] pPingParams Pointer to the ping request structure: \n - - if flags parameter is set to 0, ping will report back once all requested pings are done (as defined by TotalNumberOfAttempts). \n - - if flags parameter is set to 1, ping will report back after every ping, for TotalNumberOfAttempts. - - if flags parameter is set to 2, ping will stop after the first successful ping, and report back for the successful ping, as well as any preceding failed ones. - For stopping an ongoing ping activity, set parameters IP address to 0 - - \param[in] family SL_AF_INET or SL_AF_INET6 - \param[out] pReport Ping pReport - \param[out] pCallback Callback function upon completion. - If callback is NULL, the API is blocked until data arrives - - - \return On success, zero is returned. On error, -1 is returned - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_NetAppPingReport - \note Only one sl_NetAppPingStart can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - \warning - \par Example: - \code - - An example of sending 20 ping requests and reporting results to a callback routine when - all requests are sent: - - // callback routine - void pingRes(SlPingReport_t* pReport) - { - // handle ping results - } - - // ping activation - void PingTest() - { - SlPingReport_t report; - SlPingStartCommand_t pingCommand; - - pingCommand.Ip = SL_IPV4_VAL(10,1,1,200); // destination IP address is 10.1.1.200 - pingCommand.PingSize = 150; // size of ping, in bytes - pingCommand.PingIntervalTime = 100; // delay between pings, in milliseconds - pingCommand.PingRequestTimeout = 1000; // timeout for every ping in milliseconds - pingCommand.TotalNumberOfAttempts = 20; // max number of ping requests. 0 - forever - pingCommand.Flags = 0; // report only when finished - - sl_NetAppPingStart( &pingCommand, SL_AF_INET, &report, pingRes ) ; - } - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppPingStart) -_i16 sl_NetAppPingStart(const SlPingStartCommand_t* pPingParams,const _u8 family,SlPingReport_t *pReport,const P_SL_DEV_PING_CALLBACK pPingCallback); -#endif - -/*! - \brief Internal function for setting network application configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] AppId Application id, could be one of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - SL_NET_APP_DEVICE_CONFIG_ID - - \param[in] SetOptions set option, could be one of the following: \n - - SL_NET_APP_DHCP_SERVER_ID - - NETAPP_SET_DHCP_SRV_BASIC_OPT - - SL_NET_APP_HTTP_SERVER_ID - - NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER - - NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK - - NETAPP_SET_GET_HTTP_OPT_AUTH_NAME - - NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD - - NETAPP_SET_GET_HTTP_OPT_AUTH_REALM - - NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS - - SL_NET_APP_MDNS_ID - - NETAPP_SET_GET_MDNS_CONT_QUERY_OPT - - NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT - - NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT - - SL_NET_APP_DEVICE_CONFIG_ID - - NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN - - NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME - - - \param[in] OptionLen option structure length - - \param[in] pOptionValues pointer to the option structure - \sa - \note - \warning - \par - \code - Set DHCP Server (AP mode) parameters example: - - SlNetAppDhcpServerBasicOpt_t dhcpParams; - _u8 outLen = sizeof(SlNetAppDhcpServerBasicOpt_t); - dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address - dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,10); // first IP Address for allocation. IP Address should be set as Hex number - i.e. 0A0B0C01 for (10.11.12.1) - dhcpParams.ipv4_addr_last = SL_IPV4_VAL(192,168,1,16); // last IP Address for allocation. IP Address should be set as Hex number - i.e. 0A0B0C01 for (10.11.12.1) - sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID); // Stop DHCP server before settings - sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, outLen, (_u8* )&dhcpParams); // set parameters - sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID); // Start DHCP server with new settings - \endcode - \code - Set Device URN name example: - - Device name, maximum length of 33 characters - Device name affects URN name, own SSID name in AP mode, and WPS file "device name" in WPS I.E (STA-WPS / P2P) - In case no device URN name set, the default name is "mysimplelink" - Allowed characters in device name are: 'a - z' , 'A - Z' , '0-9' and '-' - - _u8 *my_device = "MY-SIMPLELINK-DEV"; - sl_NetAppSet (SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, strlen(my_device), (_u8 *) my_device); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppSet) -_i32 sl_NetAppSet(const _u8 AppId ,const _u8 Option,const _u8 OptionLen,const _u8 *pOptionValue); -#endif - -/*! - \brief Internal function for getting network applications configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] AppId Application id, could be one of the following: \n - - SL_NET_APP_HTTP_SERVER_ID - - SL_NET_APP_DHCP_SERVER_ID - - SL_NET_APP_MDNS_ID - - SL_NET_APP_DEVICE_CONFIG_ID - - \param[in] SetOptions set option, could be one of the following: \n - - SL_NET_APP_DHCP_SERVER_ID - - NETAPP_SET_DHCP_SRV_BASIC_OPT - - SL_NET_APP_HTTP_SERVER_ID - - NETAPP_SET_GET_HTTP_OPT_PORT_NUMBER - - NETAPP_SET_GET_HTTP_OPT_AUTH_CHECK - - NETAPP_SET_GET_HTTP_OPT_AUTH_NAME - - NETAPP_SET_GET_HTTP_OPT_AUTH_PASSWORD - - NETAPP_SET_GET_HTTP_OPT_AUTH_REALM - - NETAPP_SET_GET_HTTP_OPT_ROM_PAGES_ACCESS - - SL_NET_APP_MDNS_ID - - NETAPP_SET_GET_MDNS_CONT_QUERY_OPT - - NETAPP_SET_GET_MDNS_QEVETN_MASK_OPT - - NETAPP_SET_GET_MDNS_TIMING_PARAMS_OPT - - SL_NET_APP_DEVICE_CONFIG_ID - - NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN - - NETAPP_SET_GET_DEV_CONF_OPT_DOMAIN_NAME - - - \param[in] OptionLen The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device. - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return ESMALLBUF - - \param[out] pValues pointer to the option structure which will be filled with the response from the device - - \sa - \note - \warning - \par - \code - Get DHCP Server parameters example: - - SlNetAppDhcpServerBasicOpt_t dhcpParams; - _u8 outLen = sizeof(SlNetAppDhcpServerBasicOpt_t); - sl_NetAppGet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT, &outLen, (_u8* )&dhcpParams); - - printf("DHCP Start IP %d.%d.%d.%d End IP %d.%d.%d.%d Lease time seconds %d\n", - SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,3),SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,2), - SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,1),SL_IPV4_BYTE(dhcpParams.ipv4_addr_start,0), - SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,3),SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,2), - SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,1),SL_IPV4_BYTE(dhcpParams.ipv4_addr_last,0), - dhcpParams.lease_time); - \endcode - \code - Get Device URN name example: - Maximum length of 33 characters of device name. - Device name affects URN name, own SSID name in AP mode, and WPS file "device name" in WPS I.E (STA-WPS / P2P) - in case no device URN name set, the default name is "mysimplelink" - - _u8 my_device_name[35]; - sl_NetAppGet (SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, strlen(my_device_name), (_u8 *)my_device_name); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_NetAppGet) -_i32 sl_NetAppGet(const _u8 AppId,const _u8 Option,_u8 *pOptionLen, _u8 *pOptionValue); -#endif - - - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __NETAPP_H__ */ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/netcfg.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/netcfg.h deleted file mode 100644 index cc8cfbca..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/netcfg.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * netcfg.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - - -#ifndef __NETCFG_H__ -#define __NETCFG_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - - - -/*! - - \addtogroup netcfg - @{ - -*/ - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define SL_MAC_ADDR_LEN (6) -#define SL_IPV4_VAL(add_3,add_2,add_1,add_0) ((((_u32)add_3 << 24) & 0xFF000000) | (((_u32)add_2 << 16) & 0xFF0000) | (((_u32)add_1 << 8) & 0xFF00) | ((_u32)add_0 & 0xFF) ) -#define SL_IPV4_BYTE(val,index) ( (val >> (index*8)) & 0xFF ) - -#define IPCONFIG_MODE_DISABLE_IPV4 (0) -#define IPCONFIG_MODE_ENABLE_IPV4 (1) - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ -typedef enum -{ - SL_MAC_ADDRESS_SET = 1, - SL_MAC_ADDRESS_GET = 2, - SL_IPV4_STA_P2P_CL_GET_INFO = 3, - SL_IPV4_STA_P2P_CL_DHCP_ENABLE = 4, - SL_IPV4_STA_P2P_CL_STATIC_ENABLE = 5, - SL_IPV4_AP_P2P_GO_GET_INFO = 6, - SL_IPV4_AP_P2P_GO_STATIC_ENABLE = 7, - SL_SET_HOST_RX_AGGR = 8, - MAX_SETTINGS = 0xFF -}Sl_NetCfg_e; - - -typedef struct -{ - _u32 ipV4; - _u32 ipV4Mask; - _u32 ipV4Gateway; - _u32 ipV4DnsServer; -}SlNetCfgIpV4Args_t; - - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - \brief Internal function for setting network configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] ConfigId configuration id - \param[in] ConfigOpt configurations option - \param[in] ConfigLen configurations len - \param[in] pValues configurations values - - \sa - \note - \warning - - \par Examples: - \code - SL_MAC_ADDRESS_SET: - - Setting MAC address to the Device. - The new MAC address will override the default MAC address and it be saved in the FileSystem. - Requires restarting the device for updating this setting. - - _u8 MAC_Address[6]; - MAC_Address[0] = 0x8; - MAC_Address[1] = 0x0; - MAC_Address[2] = 0x28; - MAC_Address[3] = 0x22; - MAC_Address[4] = 0x69; - MAC_Address[5] = 0x31; - sl_NetCfgSet(SL_MAC_ADDRESS_SET,1,SL_MAC_ADDR_LEN,(_u8 *)newMacAddress); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - \code - SL_IPV4_STA_P2P_CL_STATIC_ENABLE: - - Setting a static IP address to the device working in STA mode or P2P client. - The IP address will be stored in the FileSystem. - In order to disable the static IP and get the address assigned from DHCP one should use SL_STA_P2P_CL_IPV4_DHCP_SET - - SlNetCfgIpV4Args_t ipV4; - ipV4.ipV4 = (_u32)SL_IPV4_VAL(10,1,1,201); // _u32 IP address - ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this STA/P2P - ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(10,1,1,1); // _u32 Default gateway address - ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(8,16,32,64); // _u32 DNS server address - - sl_NetCfgSet(SL_IPV4_STA_P2P_CL_STATIC_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,sizeof(SlNetCfgIpV4Args_t),(_u8 *)&ipV4); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - \code - SL_IPV4_STA_P2P_CL_DHCP_ENABLE: - - Setting IP address by DHCP to FileSystem using WLAN sta mode or P2P client. - This should be done once if using Serial Flash. - This is the system's default mode for acquiring an IP address after WLAN connection. - _u8 val = 1; - sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,1,&val); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - \code - SL_IPV4_AP_P2P_GO_STATIC_ENABLE: - - Setting a static IP address to the device working in AP mode or P2P go. - The IP address will be stored in the FileSystem. Requires restart. - - SlNetCfgIpV4Args_t ipV4; - ipV4.ipV4 = (_u32)SL_IPV4_VAL(10,1,1,201); // _u32 IP address - ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP/P2P - ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(10,1,1,1); // _u32 Default gateway address - ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(8,16,32,64); // _u32 DNS server address - - sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE,IPCONFIG_MODE_ENABLE_IPV4,sizeof(SlNetCfgIpV4Args_t),(_u8 *)&ipV4); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - - -*/ -#if _SL_INCLUDE_FUNC(sl_NetCfgSet) -_i32 sl_NetCfgSet(const _u8 ConfigId,const _u8 ConfigOpt,const _u8 ConfigLen,const _u8 *pValues); -#endif - - -/*! - \brief Internal function for getting network configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] ConfigId configuration id - - \param[out] pConfigOpt Get configurations option - - \param[out] pConfigLen The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device.\n - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return ESMALLBUF - - \param[out] pValues - get configurations values - - \sa - \note - \warning - \par Examples: - \code - SL_MAC_ADDRESS_GET: - - Get the device MAC address. - The returned MAC address is taken from FileSystem first. If the MAC address was not set by SL_MAC_ADDRESS_SET, the default MAC address - is retrieved from HW. - - _u8 macAddressVal[SL_MAC_ADDR_LEN]; - _u8 macAddressLen = SL_MAC_ADDR_LEN; - sl_NetCfgGet(SL_MAC_ADDRESS_GET,NULL,&macAddressLen,(_u8 *)macAddressVal); - - \endcode - - \code - SL_IPV4_STA_P2P_CL_GET_INFO: - - Get IP address from WLAN station or P2P client. A DHCP flag is returned to indicate if the IP address is static or from DHCP. - - _u8 len = sizeof(SlNetCfgIpV4Args_t); - _u8 dhcpIsOn = 0; - SlNetCfgIpV4Args_t ipV4 = {0}; - sl_NetCfgGet(SL_IPV4_STA_P2P_CL_GET_INFO,&dhcpIsOn,&len,(_u8 *)&ipV4); - - printf("DHCP is %s IP %d.%d.%d.%d MASK %d.%d.%d.%d GW %d.%d.%d.%d DNS %d.%d.%d.%d\n", - (dhcpIsOn > 0) ? "ON" : "OFF", - SL_IPV4_BYTE(ipV4.ipV4,3),SL_IPV4_BYTE(ipV4.ipV4,2),SL_IPV4_BYTE(ipV4.ipV4,1),SL_IPV4_BYTE(ipV4.ipV4,0), - SL_IPV4_BYTE(ipV4.ipV4Mask,3),SL_IPV4_BYTE(ipV4.ipV4Mask,2),SL_IPV4_BYTE(ipV4.ipV4Mask,1),SL_IPV4_BYTE(ipV4.ipV4Mask,0), - SL_IPV4_BYTE(ipV4.ipV4Gateway,3),SL_IPV4_BYTE(ipV4.ipV4Gateway,2),SL_IPV4_BYTE(ipV4.ipV4Gateway,1),SL_IPV4_BYTE(ipV4.ipV4Gateway,0), - SL_IPV4_BYTE(ipV4.ipV4DnsServer,3),SL_IPV4_BYTE(ipV4.ipV4DnsServer,2),SL_IPV4_BYTE(ipV4.ipV4DnsServer,1),SL_IPV4_BYTE(ipV4.ipV4DnsServer,0)); - - \endcode - - \code - SL_IPV4_AP_P2P_GO_GET_INFO: - - Get static IP address for AP or P2P go. - - _u8 len = sizeof(SlNetCfgIpV4Args_t); - _u8 dhcpIsOn = 0; // this flag is meaningless on AP/P2P go. - SlNetCfgIpV4Args_t ipV4 = {0}; - sl_NetCfgGet(SL_IPV4_AP_P2P_GO_GET_INFO,&dhcpIsOn,&len,(_u8 *)&ipV4); - - printf("IP %d.%d.%d.%d MASK %d.%d.%d.%d GW %d.%d.%d.%d DNS %d.%d.%d.%d\n", - SL_IPV4_BYTE(ipV4.ipV4,3),SL_IPV4_BYTE(ipV4.ipV4,2),SL_IPV4_BYTE(ipV4.ipV4,1),SL_IPV4_BYTE(ipV4.ipV4,0), - SL_IPV4_BYTE(ipV4.ipV4Mask,3),SL_IPV4_BYTE(ipV4.ipV4Mask,2),SL_IPV4_BYTE(ipV4.ipV4Mask,1),SL_IPV4_BYTE(ipV4.ipV4Mask,0), - SL_IPV4_BYTE(ipV4.ipV4Gateway,3),SL_IPV4_BYTE(ipV4.ipV4Gateway,2),SL_IPV4_BYTE(ipV4.ipV4Gateway,1),SL_IPV4_BYTE(ipV4.ipV4Gateway,0), - SL_IPV4_BYTE(ipV4.ipV4DnsServer,3),SL_IPV4_BYTE(ipV4.ipV4DnsServer,2),SL_IPV4_BYTE(ipV4.ipV4DnsServer,1),SL_IPV4_BYTE(ipV4.ipV4DnsServer,0)); - - \endcode - - -*/ -#if _SL_INCLUDE_FUNC(sl_NetCfgGet) -_i32 sl_NetCfgGet(const _u8 ConfigId ,_u8 *pConfigOpt, _u8 *pConfigLen, _u8 *pValues); -#endif - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __NETCFG_H__ */ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/nonos.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/nonos.h deleted file mode 100644 index 568c0ff2..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/nonos.h +++ /dev/null @@ -1,325 +0,0 @@ -/* - * nonos.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __NONOS_H__ -#define __NONOS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef SL_PLATFORM_MULTI_THREADED - -/* This function call the user defined function, if defined, from the sync wait loop */ -/* The use case of this function is to allow nonos system to call a user function to put the device into sleep */ -/* The wake up should be activated after getting an interrupt from the device to Host */ -/* The user function must return without blocking to prevent a delay on the event handling */ -/* -#define _SlSyncWaitLoopCallback UserSleepFunction -*/ - - - -#define NONOS_WAIT_FOREVER 0xFF -#define NONOS_NO_WAIT 0x00 - -#define NONOS_RET_OK (0) -#define NONOS_RET_ERR (0xFF) -#define OSI_OK NONOS_RET_OK - -#define __NON_OS_SYNC_OBJ_CLEAR_VALUE 0x11 -#define __NON_OS_SYNC_OBJ_SIGNAL_VALUE 0x22 -#define __NON_OS_LOCK_OBJ_UNLOCK_VALUE 0x33 -#define __NON_OS_LOCK_OBJ_LOCK_VALUE 0x44 - -/*! - \brief type definition for the return values of this adaptation layer -*/ -typedef _i8 _SlNonOsRetVal_t; - -/*! - \brief type definition for a time value -*/ -typedef _u8 _SlNonOsTime_t; - -/*! - \brief type definition for a sync object container - - Sync object is object used to synchronize between two threads or thread and interrupt handler. - One thread is waiting on the object and the other thread send a signal, which then - release the waiting thread. - The signal must be able to be sent from interrupt context. - This object is generally implemented by binary semaphore or events. -*/ -typedef _u8 _SlNonOsSemObj_t; - - -#define _SlTime_t _SlNonOsTime_t - -#define _SlSyncObj_t _SlNonOsSemObj_t - -#define _SlLockObj_t _SlNonOsSemObj_t - -#define SL_OS_WAIT_FOREVER NONOS_WAIT_FOREVER - -#define SL_OS_RET_CODE_OK NONOS_RET_OK - -#define SL_OS_NO_WAIT NONOS_NO_WAIT - - - - - -/*! - \brief This function creates a sync object - - The sync object is used for synchronization between different thread or ISR and - a thread. - - \param pSyncObj - pointer to the sync object control block - - \return upon successful creation the function return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjCreate(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) - -/*! - \brief This function deletes a sync object - - \param pSyncObj - pointer to the sync object control block - - \return upon successful deletion the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjDelete(pSyncObj) _SlNonOsSemSet(pSyncObj,0) - -/*! - \brief This function generates a sync signal for the object. - - All suspended threads waiting on this sync object are resumed - - \param pSyncObj - pointer to the sync object control block - - \return upon successful signaling the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note the function could be called from ISR context - \warning -*/ -#define _SlNonOsSyncObjSignal(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) - -/*! - \brief This function waits for a sync signal of the specific sync object - - \param pSyncObj - pointer to the sync object control block - \param Timeout - numeric value specifies the maximum number of mSec to - stay suspended while waiting for the sync signal - Currently, the simple link driver uses only two values: - - NONOS_WAIT_FOREVER - - NONOS_NO_WAIT - - \return upon successful reception of the signal within the timeout window return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjWait(pSyncObj , Timeout) _SlNonOsSemGet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE,__NON_OS_SYNC_OBJ_CLEAR_VALUE,Timeout) - -/*! - \brief This function clears a sync object - - \param pSyncObj - pointer to the sync object control block - - \return upon successful clearing the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsSyncObjClear(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) - -/*! - \brief This function creates a locking object. - - The locking object is used for protecting a shared resources between different - threads. - - \param pLockObj - pointer to the locking object control block - - \return upon successful creation the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjCreate(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - -/*! - \brief This function deletes a locking object. - - \param pLockObj - pointer to the locking object control block - - \return upon successful deletion the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjDelete(pLockObj) _SlNonOsSemSet(pLockObj,0) - -/*! - \brief This function locks a locking object. - - All other threads that call this function before this thread calls - the _SlNonOsLockObjUnlock would be suspended - - \param pLockObj - pointer to the locking object control block - \param Timeout - numeric value specifies the maximum number of mSec to - stay suspended while waiting for the locking object - Currently, the simple link driver uses only two values: - - NONOS_WAIT_FOREVER - - NONOS_NO_WAIT - - - \return upon successful reception of the locking object the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjLock(pLockObj , Timeout) _SlNonOsSemGet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE,__NON_OS_LOCK_OBJ_LOCK_VALUE,Timeout) - -/*! - \brief This function unlock a locking object. - - \param pLockObj - pointer to the locking object control block - - \return upon successful unlocking the function should return 0 - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -#define _SlNonOsLockObjUnlock(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - - -/*! - \brief This function call the pEntry callback from a different context - - \param pEntry - pointer to the entry callback function - - \param pValue - pointer to any type of memory structure that would be - passed to pEntry callback from the execution thread. - - \param flags - execution flags - reserved for future usage - - \return upon successful registration of the spawn the function return 0 - (the function is not blocked till the end of the execution of the function - and could be returned before the execution is actually completed) - Otherwise, a negative value indicating the error code shall be returned - \note - \warning -*/ -_SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); - - -/*! - \brief This function must be called from the main loop in non-os paltforms - - \param None - - \return 0 - No more activities - 1 - Activity still in progress - \note - \warning -*/ -_SlNonOsRetVal_t _SlNonOsMainLoopTask(void); - -extern _SlNonOsRetVal_t _SlNonOsSemGet(_SlNonOsSemObj_t* pSyncObj, _SlNonOsSemObj_t WaitValue, _SlNonOsSemObj_t SetValue, _SlNonOsTime_t Timeout); -extern _SlNonOsRetVal_t _SlNonOsSemSet(_SlNonOsSemObj_t* pSemObj , _SlNonOsSemObj_t Value); -extern _SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); - -#if (defined(_SlSyncWaitLoopCallback)) -extern void _SlSyncWaitLoopCallback(void); -#endif - - -/***************************************************************************** - - Overwrite SimpleLink driver OS adaptation functions - - - *****************************************************************************/ - -#undef sl_SyncObjCreate -#define sl_SyncObjCreate(pSyncObj,pName) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_CLEAR_VALUE) - -#undef sl_SyncObjDelete -#define sl_SyncObjDelete(pSyncObj) _SlNonOsSemSet(pSyncObj,0) - -#undef sl_SyncObjSignal -#define sl_SyncObjSignal(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) - -#undef sl_SyncObjSignalFromIRQ -#define sl_SyncObjSignalFromIRQ(pSyncObj) _SlNonOsSemSet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE) - -#undef sl_SyncObjWait -#define sl_SyncObjWait(pSyncObj,Timeout) _SlNonOsSemGet(pSyncObj,__NON_OS_SYNC_OBJ_SIGNAL_VALUE,__NON_OS_SYNC_OBJ_CLEAR_VALUE,Timeout) - -#undef sl_LockObjCreate -#define sl_LockObjCreate(pLockObj,pName) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - -#undef sl_LockObjDelete -#define sl_LockObjDelete(pLockObj) _SlNonOsSemSet(pLockObj,0) - -#undef sl_LockObjLock -#define sl_LockObjLock(pLockObj,Timeout) _SlNonOsSemGet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE,__NON_OS_LOCK_OBJ_LOCK_VALUE,Timeout) - -#undef sl_LockObjUnlock -#define sl_LockObjUnlock(pLockObj) _SlNonOsSemSet(pLockObj,__NON_OS_LOCK_OBJ_UNLOCK_VALUE) - -#undef sl_Spawn -#define sl_Spawn(pEntry,pValue,flags) _SlNonOsSpawn(pEntry,pValue,flags) - -#undef _SlTaskEntry -#define _SlTaskEntry _SlNonOsMainLoopTask - -#endif /* !SL_PLATFORM_MULTI_THREADED */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/objInclusion.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/objInclusion.h deleted file mode 100644 index cfe875e7..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/objInclusion.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * objInclusion.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#include - -#ifndef OBJINCLUSION_H_ -#define OBJINCLUSION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/****************************************************************************** - - For future use - -*******************************************************************************/ - -#define __inln /* if inline functions requiered: #define __inln inline */ - -#define SL_DEVICE /* Device silo is currently always mandatory */ - - - -/****************************************************************************** - - Qualifiers for package customizations - -*******************************************************************************/ - -#if defined (SL_DEVICE) -#define __dev 1 -#else -#define __dev 0 -#endif - -#if defined (SL_DEVICE) && defined (SL_INC_EXT_API) -#define __dev__ext 1 -#else -#define __dev__ext 0 -#endif - - -#if (!defined (SL_PLATFORM_MULTI_THREADED)) || (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) -#define __int__spwn 1 -#else -#define __int__spwn 0 -#endif - -#if defined (SL_INC_NET_APP_PKG) -#define __nap 1 -#else -#define __nap 0 -#endif - -#if defined (SL_INC_NET_APP_PKG) && defined (SL_INC_SOCK_CLIENT_SIDE_API) -#define __nap__clt 1 -#else -#define __nap__clt 0 -#endif - -#if defined (SL_INC_NET_APP_PKG) && defined (SL_INC_EXT_API) -#define __nap__ext 1 -#else -#define __nap__ext 0 -#endif - -#if defined (SL_INC_NET_CFG_PKG) -#define __ncg 1 -#else -#define __ncg 0 -#endif - -#if defined (SL_INC_NET_CFG_PKG) && defined (SL_INC_EXT_API) -#define __ncg__ext 1 -#else -#define __ncg__ext 0 -#endif - -#if defined (SL_INC_NVMEM_PKG) -#define __nvm 1 -#else -#define __nvm 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) -#define __sck 1 -#else -#define __sck 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_EXT_API) -#define __sck__ext 1 -#else -#define __sck__ext 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_SERVER_SIDE_API) -#define __sck__srv 1 -#else -#define __sck__srv 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_CLIENT_SIDE_API) -#define __sck__clt 1 -#else -#define __sck__clt 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_RECV_API) -#define __sck__rcv 1 -#else -#define __sck__rcv 0 -#endif - -#if defined (SL_INC_SOCKET_PKG) && defined (SL_INC_SOCK_SEND_API) -#define __sck__snd 1 -#else -#define __sck__snd 0 -#endif - -#if defined (SL_INC_WLAN_PKG) -#define __wln 1 -#else -#define __wln 0 -#endif - -#if defined (SL_INC_WLAN_PKG) && defined (SL_INC_EXT_API) -#define __wln__ext 1 -#else -#define __wln__ext 0 -#endif - -/* The return 1 is the function need to be included in the output */ -#define _SL_INCLUDE_FUNC(Name) (_SL_INC_##Name) - -/* Driver */ -#define _SL_INC_sl_NetAppStart __nap__ext -#define _SL_INC_sl_NetAppStop __nap__ext - -#define _SL_INC_sl_NetAppDnsGetHostByName __nap__clt - - -#define _SL_INC_sl_NetAppDnsGetHostByService __nap__ext -#define _SL_INC_sl_NetAppMDNSRegisterService __nap__ext -#define _SL_INC_sl_NetAppMDNSUnRegisterService __nap__ext -#define _SL_INC_sl_NetAppMDNSRegisterUnregisterService __nap__ext -#define _SL_INC_sl_NetAppGetServiceList __nap__ext - - -#define _SL_INC_sl_DnsGetHostByAddr __nap__ext -#define _SL_INC_sl_NetAppPingStart __nap__ext -#define _SL_INC_sl_NetAppPingReport __nap__ext -#define _SL_INC_sl_NetAppSet __nap__ext -#define _SL_INC_sl_NetAppGet __nap__ext - - -/* FS */ -#define _SL_INC_sl_FsOpen __nvm - -#define _SL_INC_sl_FsClose __nvm - -#define _SL_INC_sl_FsRead __nvm - -#define _SL_INC_sl_FsWrite __nvm - -#define _SL_INC_sl_FsGetInfo __nvm - -#define _SL_INC_sl_FsDel __nvm - -/* netcfg */ -#define _SL_INC_sl_MacAdrrSet __ncg - -#define _SL_INC_sl_MacAdrrGet __ncg - -#define _SL_INC_sl_NetCfgGet __ncg - -#define _SL_INC_sl_NetCfgSet __ncg - - -/* socket */ -#define _SL_INC_sl_Socket __sck - -#define _SL_INC_sl_Close __sck - -#define _SL_INC_sl_Accept __sck__srv - -#define _SL_INC_sl_Bind __sck - -#define _SL_INC_sl_Listen __sck__srv - -#define _SL_INC_sl_Connect __sck__clt - -#define _SL_INC_sl_Select __sck - -#define _SL_INC_sl_SetSockOpt __sck - -#define _SL_INC_sl_GetSockOpt __sck__ext - -#define _SL_INC_sl_Recv __sck__rcv - -#define _SL_INC_sl_RecvFrom __sck__rcv - -#define _SL_INC_sl_Write __sck__snd - -#define _SL_INC_sl_Send __sck__snd - -#define _SL_INC_sl_SendTo __sck__snd - -#define _SL_INC_sl_Htonl __sck - -#define _SL_INC_sl_Htons __sck - -/* wlan */ -#define _SL_INC_sl_WlanConnect __wln__ext - -#define _SL_INC_sl_WlanDisconnect __wln__ext - -#define _SL_INC_sl_WlanProfileAdd __wln__ext - -#define _SL_INC_sl_WlanProfileGet __wln__ext - -#define _SL_INC_sl_WlanProfileDel __wln__ext - -#define _SL_INC_sl_WlanPolicySet __wln__ext - -#define _SL_INC_sl_WlanPolicyGet __wln__ext - -#define _SL_INC_sl_WlanGetNetworkList __wln__ext - -#define _SL_INC_sl_WlanRxFilterAdd __wln__ext - -#define _SL_INC_sl_WlanRxFilterSet __wln__ext - -#define _SL_INC_sl_WlanRxFilterGet __wln__ext - -#define _SL_INC_sl_SmartConfigStart __wln - -#define _SL_INC_sl_SmartConfigOptSet __wln__ext - - -#define _SL_INC_sl_WlanSmartConfigStart __wln - -#define _SL_INC_sl_WlanSmartConfigStop __wln - -#define _SL_INC_sl_WlanSetMode __wln - -#define _SL_INC_sl_WlanSet __wln - -#define _SL_INC_sl_WlanGet __wln - -#define _SL_INC_sl_SmartConfigOptSet __wln__ext - -#define _SL_INC_sl_SmartConfigOptGet __wln__ext - -#define _SL_INC_sl_WlanRxStatStart __wln__ext - -#define _SL_INC_sl_WlanRxStatStop __wln__ext - -#define _SL_INC_sl_WlanRxStatGet __wln__ext - - -/* device */ -#define _SL_INC_sl_Task __int__spwn - -#define _SL_INC_sl_Start __dev - -#define _SL_INC_sl_Stop __dev - -#define _SL_INC_sl_StatusGet __dev - -#ifdef SL_IF_TYPE_UART -#define _SL_INC_sl_UartSetMode __dev__ext -#endif - -#define _SL_INC_sl_EventMaskGet __dev__ext - -#define _SL_INC_sl_EventMaskSet __dev__ext - -#define _SL_INC_sl_DevGet __dev__ext - -#define _SL_INC_sl_DevSet __dev__ext - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /*OBJINCLUSION_H_ */ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/protocol.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/protocol.h deleted file mode 100644 index 8a1299a6..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/protocol.h +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * protocol.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*******************************************************************************\ -* -* FILE NAME: protocol.h -* -* DESCRIPTION: Constant and data structure definitions and function -* prototypes for the SL protocol module, which implements -* processing of SimpleLink Commands. -* -* AUTHOR: -* -\*******************************************************************************/ - -#ifndef _SL_PROTOCOL_TYPES_H_ -#define _SL_PROTOCOL_TYPES_H_ - -/**************************************************************************** -** -** User I/F pools definitions -** -****************************************************************************/ - -/**************************************************************************** -** -** Definitions for SimpleLink Commands -** -****************************************************************************/ - - -/* pattern for LE 8/16/32 or BE*/ -#define H2N_SYNC_PATTERN {0xBBDDEEFF,0x4321,0x34,0x12} -#define H2N_CNYS_PATTERN {0xBBDDEEFF,0x8765,0x78,0x56} - -#define H2N_DUMMY_PATTERN (_u32)0xFFFFFFFF -#define N2H_SYNC_PATTERN (_u32)0xABCDDCBA -#define SYNC_PATTERN_LEN (_u32)sizeof(_u32) -#define UART_SET_MODE_MAGIC_CODE (_u32)0xAA55AA55 -#define SPI_16BITS_BUG(pattern) (_u32)((_u32)pattern & (_u32)0xFFFF7FFF) -#define SPI_8BITS_BUG(pattern) (_u32)((_u32)pattern & (_u32)0xFFFFFF7F) - - - -typedef struct -{ - _u16 Opcode; - _u16 Len; -}_SlGenericHeader_t; - - -typedef struct -{ - _u32 Long; - _u16 Short; - _u8 Byte1; - _u8 Byte2; -}_SlSyncPattern_t; - -typedef _SlGenericHeader_t _SlCommandHeader_t; - -typedef struct -{ - _SlGenericHeader_t GenHeader; - _u8 TxPoolCnt; - _u8 DevStatus; - _u8 SocketTXFailure; - _u8 SocketNonBlocking; -}_SlResponseHeader_t; - -#define _SL_RESP_SPEC_HDR_SIZE (sizeof(_SlResponseHeader_t) - sizeof(_SlGenericHeader_t)) -#define _SL_RESP_HDR_SIZE sizeof(_SlResponseHeader_t) -#define _SL_CMD_HDR_SIZE sizeof(_SlCommandHeader_t) - -#define _SL_RESP_ARGS_START(_pMsg) (((_SlResponseHeader_t *)(_pMsg)) + 1) - -/* Used only in NWP! */ -typedef struct -{ - _SlCommandHeader_t sl_hdr; - _u8 func_args_start; -} T_SCMD; - - -#define WLAN_CONN_STATUS_BIT 0x01 -#define EVENTS_Q_STATUS_BIT 0x02 -#define PENDING_RCV_CMD_BIT 0x04 -#define FW_BUSY_PACKETS_BIT 0x08 - -#define INIT_STA_OK 0x11111111 -#define INIT_STA_ERR 0x22222222 -#define INIT_AP_OK 0x33333333 -#define INIT_AP_ERR 0x44444444 -#define INIT_P2P_OK 0x55555555 -#define INIT_P2P_ERR 0x66666666 - -/**************************************************************************** -** OPCODES -****************************************************************************/ -#define SL_IPV4_IPV6_OFFSET ( 9 ) -#define SL_OPCODE_IPV4 ( 0x0 << SL_IPV4_IPV6_OFFSET ) -#define SL_OPCODE_IPV6 ( 0x1 << SL_IPV4_IPV6_OFFSET ) - -#define SL_SYNC_ASYNC_OFFSET ( 10 ) -#define SL_OPCODE_SYNC (0x1 << SL_SYNC_ASYNC_OFFSET ) -#define SL_OPCODE_SILO_OFFSET ( 11 ) -#define SL_OPCODE_SILO_MASK ( 0xF << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_DEVICE ( 0x0 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_WLAN ( 0x1 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_SOCKET ( 0x2 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETAPP ( 0x3 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NVMEM ( 0x4 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETCFG ( 0x5 << SL_OPCODE_SILO_OFFSET ) - -#define SL_FAMILY_SHIFT (0x4) -#define SL_FLAGS_MASK (0xF) - -#define SL_OPCODE_DEVICE_INITCOMPLETE 0x0008 -#define SL_OPCODE_DEVICE_ABORT 0x000C -#define SL_OPCODE_DEVICE_STOP_COMMAND 0x8473 -#define SL_OPCODE_DEVICE_STOP_RESPONSE 0x0473 -#define SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE 0x0073 -#define SL_OPCODE_DEVICE_DEVICEASYNCDUMMY 0x0063 - -#define SL_OPCODE_DEVICE_VERSIONREADCOMMAND 0x8470 -#define SL_OPCODE_DEVICE_VERSIONREADRESPONSE 0x0470 -#define SL_OPCODE_DEVICE_DEVICEASYNCFATALERROR 0x0078 -#define SL_OPCODE_WLAN_WLANCONNECTCOMMAND 0x8C80 -#define SL_OPCODE_WLAN_WLANCONNECTRESPONSE 0x0C80 -#define SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE 0x0880 -#define SL_OPCODE_WLAN_P2P_DEV_FOUND 0x0830 -#define SL_OPCODE_WLAN_CONNECTION_FAILED 0x0831 -#define SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED 0x0832 - -#define SL_OPCODE_WLAN_WLANDISCONNECTCOMMAND 0x8C81 -#define SL_OPCODE_WLAN_WLANDISCONNECTRESPONSE 0x0C81 -#define SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE 0x0881 -#define SL_OPCODE_WLAN_WLANCONNECTEAPCOMMAND 0x8C82 -#define SL_OPCODE_WLAN_WLANCONNECTEAPCRESPONSE 0x0C82 -#define SL_OPCODE_WLAN_PROFILEADDCOMMAND 0x8C83 -#define SL_OPCODE_WLAN_PROFILEADDRESPONSE 0x0C83 -#define SL_OPCODE_WLAN_PROFILEGETCOMMAND 0x8C84 -#define SL_OPCODE_WLAN_PROFILEGETRESPONSE 0x0C84 -#define SL_OPCODE_WLAN_PROFILEDELCOMMAND 0x8C85 -#define SL_OPCODE_WLAN_PROFILEDELRESPONSE 0x0C85 -#define SL_OPCODE_WLAN_POLICYSETCOMMAND 0x8C86 -#define SL_OPCODE_WLAN_POLICYSETRESPONSE 0x0C86 -#define SL_OPCODE_WLAN_POLICYGETCOMMAND 0x8C87 -#define SL_OPCODE_WLAN_POLICYGETRESPONSE 0x0C87 -#define SL_OPCODE_WLAN_FILTERADD 0x8C88 -#define SL_OPCODE_WLAN_FILTERADDRESPONSE 0x0C88 -#define SL_OPCODE_WLAN_FILTERGET 0x8C89 -#define SL_OPCODE_WLAN_FILTERGETRESPONSE 0x0C89 -#define SL_OPCODE_WLAN_FILTERDELETE 0x8C8A -#define SL_OPCODE_WLAN_FILTERDELETERESPOSNE 0x0C8A -#define SL_OPCODE_WLAN_WLANGETSTATUSCOMMAND 0x8C8F -#define SL_OPCODE_WLAN_WLANGETSTATUSRESPONSE 0x0C8F -#define SL_OPCODE_WLAN_STARTTXCONTINUESCOMMAND 0x8CAA -#define SL_OPCODE_WLAN_STARTTXCONTINUESRESPONSE 0x0CAA -#define SL_OPCODE_WLAN_STOPTXCONTINUESCOMMAND 0x8CAB -#define SL_OPCODE_WLAN_STOPTXCONTINUESRESPONSE 0x0CAB -#define SL_OPCODE_WLAN_STARTRXSTATCOMMAND 0x8CAC -#define SL_OPCODE_WLAN_STARTRXSTATRESPONSE 0x0CAC -#define SL_OPCODE_WLAN_STOPRXSTATCOMMAND 0x8CAD -#define SL_OPCODE_WLAN_STOPRXSTATRESPONSE 0x0CAD -#define SL_OPCODE_WLAN_GETRXSTATCOMMAND 0x8CAF -#define SL_OPCODE_WLAN_GETRXSTATRESPONSE 0x0CAF -#define SL_OPCODE_WLAN_POLICYSETCOMMANDNEW 0x8CB0 -#define SL_OPCODE_WLAN_POLICYSETRESPONSENEW 0x0CB0 -#define SL_OPCODE_WLAN_POLICYGETCOMMANDNEW 0x8CB1 -#define SL_OPCODE_WLAN_POLICYGETRESPONSENEW 0x0CB1 - -#define SL_OPCODE_WLAN_SMART_CONFIG_START_COMMAND 0x8CB2 -#define SL_OPCODE_WLAN_SMART_CONFIG_START_RESPONSE 0x0CB2 -#define SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE 0x08B2 -#define SL_OPCODE_WLAN_SMART_CONFIG_STOP_COMMAND 0x8CB3 -#define SL_OPCODE_WLAN_SMART_CONFIG_STOP_RESPONSE 0x0CB3 -#define SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE 0x08B3 -#define SL_OPCODE_WLAN_SET_MODE 0x8CB4 -#define SL_OPCODE_WLAN_SET_MODE_RESPONSE 0x0CB4 -#define SL_OPCODE_WLAN_CFG_SET 0x8CB5 -#define SL_OPCODE_WLAN_CFG_SET_RESPONSE 0x0CB5 -#define SL_OPCODE_WLAN_CFG_GET 0x8CB6 -#define SL_OPCODE_WLAN_CFG_GET_RESPONSE 0x0CB6 -#define SL_OPCODE_WLAN_STA_CONNECTED 0x082E -#define SL_OPCODE_WLAN_STA_DISCONNECTED 0x082F -#define SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND 0x8C67 -#define SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND_RESPONSE 0x0C67 - -#define SL_OPCODE_SOCKET_SOCKET 0x9401 -#define SL_OPCODE_SOCKET_SOCKETRESPONSE 0x1401 -#define SL_OPCODE_SOCKET_CLOSE 0x9402 -#define SL_OPCODE_SOCKET_CLOSERESPONSE 0x1402 -#define SL_OPCODE_SOCKET_ACCEPT 0x9403 -#define SL_OPCODE_SOCKET_ACCEPTRESPONSE 0x1403 -#define SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE 0x1003 -#define SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 0x1203 -#define SL_OPCODE_SOCKET_BIND 0x9404 -#define SL_OPCODE_SOCKET_BIND_V6 0x9604 -#define SL_OPCODE_SOCKET_BINDRESPONSE 0x1404 -#define SL_OPCODE_SOCKET_LISTEN 0x9405 -#define SL_OPCODE_SOCKET_LISTENRESPONSE 0x1405 -#define SL_OPCODE_SOCKET_CONNECT 0x9406 -#define SL_OPCODE_SOCKET_CONNECT_V6 0x9606 -#define SL_OPCODE_SOCKET_CONNECTRESPONSE 0x1406 -#define SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE 0x1006 -#define SL_OPCODE_SOCKET_SELECT 0x9407 -#define SL_OPCODE_SOCKET_SELECTRESPONSE 0x1407 -#define SL_OPCODE_SOCKET_SELECTASYNCRESPONSE 0x1007 -#define SL_OPCODE_SOCKET_SETSOCKOPT 0x9408 -#define SL_OPCODE_SOCKET_SETSOCKOPTRESPONSE 0x1408 -#define SL_OPCODE_SOCKET_GETSOCKOPT 0x9409 -#define SL_OPCODE_SOCKET_GETSOCKOPTRESPONSE 0x1409 -#define SL_OPCODE_SOCKET_RECV 0x940A -#define SL_OPCODE_SOCKET_RECVASYNCRESPONSE 0x100A -#define SL_OPCODE_SOCKET_RECVFROM 0x940B -#define SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE 0x100B -#define SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 0x120B -#define SL_OPCODE_SOCKET_SEND 0x940C -#define SL_OPCODE_SOCKET_SENDTO 0x940D -#define SL_OPCODE_SOCKET_SENDTO_V6 0x960D -#define SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE 0x100E -#define SL_OPCODE_SOCKET_SOCKETASYNCEVENT 0x100F -#define SL_OPCODE_NETAPP_START_COMMAND 0x9C0A -#define SL_OPCODE_NETAPP_START_RESPONSE 0x1C0A -#define SL_OPCODE_NETAPP_NETAPPSTARTRESPONSE 0x1C0A -#define SL_OPCODE_NETAPP_STOP_COMMAND 0x9C61 -#define SL_OPCODE_NETAPP_STOP_RESPONSE 0x1C61 -#define SL_OPCODE_NETAPP_NETAPPSET 0x9C0B -#define SL_OPCODE_NETAPP_NETAPPSETRESPONSE 0x1C0B -#define SL_OPCODE_NETAPP_NETAPPGET 0x9C27 -#define SL_OPCODE_NETAPP_NETAPPGETRESPONSE 0x1C27 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAME 0x9C20 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMERESPONSE 0x1C20 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE 0x1820 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE_V6 0x1A20 -#define SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE 0x9C71 -#define SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE_RESPONSE 0x1C72 -#define SL_OPCODE_NETAPP_MDNSREGISTERSERVICE 0x9C34 -#define SL_OPCODE_NETAPP_MDNSREGISTERSERVICERESPONSE 0x1C34 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICE 0x9C35 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICERESPONSE 0x1C35 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE 0x1835 -#define SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE_V6 0x1A35 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDR 0x9C26 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDR_V6 0x9E26 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDRRESPONSE 0x1C26 -#define SL_OPCODE_NETAPP_DNSGETHOSTBYADDRASYNCRESPONSE 0x1826 -#define SL_OPCODE_NETAPP_PINGSTART 0x9C21 -#define SL_OPCODE_NETAPP_PINGSTART_V6 0x9E21 -#define SL_OPCODE_NETAPP_PINGSTARTRESPONSE 0x1C21 -#define SL_OPCODE_NETAPP_PINGREPORTREQUEST 0x9C22 -#define SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE 0x1822 -#define SL_OPCODE_NETAPP_PINGSTOP 0x9C23 -#define SL_OPCODE_NETAPP_PINGSTOPRESPONSE 0x1C23 -#define SL_OPCODE_NETAPP_ARPFLUSH 0x9C24 -#define SL_OPCODE_NETAPP_ARPFLUSHRESPONSE 0x1C24 -#define SL_OPCODE_NETAPP_IPACQUIRED 0x1825 -#define SL_OPCODE_NETAPP_IPV4_LOST 0x1832 -#define SL_OPCODE_NETAPP_DHCP_IPV4_ACQUIRE_TIMEOUT 0x1833 -#define SL_OPCODE_NETAPP_IPACQUIRED_V6 0x1A25 -#define SL_OPCODE_NETAPP_IPERFSTARTCOMMAND 0x9C28 -#define SL_OPCODE_NETAPP_IPERFSTARTRESPONSE 0x1C28 -#define SL_OPCODE_NETAPP_IPERFSTOPCOMMAND 0x9C29 -#define SL_OPCODE_NETAPP_IPERFSTOPRESPONSE 0x1C29 -#define SL_OPCODE_NETAPP_CTESTSTARTCOMMAND 0x9C2A -#define SL_OPCODE_NETAPP_CTESTSTARTRESPONSE 0x1C2A -#define SL_OPCODE_NETAPP_CTESTASYNCRESPONSE 0x182A -#define SL_OPCODE_NETAPP_CTESTSTOPCOMMAND 0x9C2B -#define SL_OPCODE_NETAPP_CTESTSTOPRESPONSE 0x1C2B -#define SL_OPCODE_NETAPP_IP_LEASED 0x182C -#define SL_OPCODE_NETAPP_IP_RELEASED 0x182D -#define SL_OPCODE_NETAPP_HTTPGETTOKENVALUE 0x182E -#define SL_OPCODE_NETAPP_HTTPSENDTOKENVALUE 0x9C2F -#define SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE 0x1830 -#define SL_OPCODE_NVMEM_FILEOPEN 0xA43C -#define SL_OPCODE_NVMEM_FILEOPENRESPONSE 0x243C -#define SL_OPCODE_NVMEM_FILECLOSE 0xA43D -#define SL_OPCODE_NVMEM_FILECLOSERESPONSE 0x243D -#define SL_OPCODE_NVMEM_FILEREADCOMMAND 0xA440 -#define SL_OPCODE_NVMEM_FILEREADRESPONSE 0x2440 -#define SL_OPCODE_NVMEM_FILEWRITECOMMAND 0xA441 -#define SL_OPCODE_NVMEM_FILEWRITERESPONSE 0x2441 -#define SL_OPCODE_NVMEM_FILEGETINFOCOMMAND 0xA442 -#define SL_OPCODE_NVMEM_FILEGETINFORESPONSE 0x2442 -#define SL_OPCODE_NVMEM_FILEDELCOMMAND 0xA443 -#define SL_OPCODE_NVMEM_FILEDELRESPONSE 0x2443 -#define SL_OPCODE_NVMEM_NVMEMFORMATCOMMAND 0xA444 -#define SL_OPCODE_NVMEM_NVMEMFORMATRESPONSE 0x2444 - -#define SL_OPCODE_DEVICE_SETDEBUGLEVELCOMMAND 0x846A -#define SL_OPCODE_DEVICE_SETDEBUGLEVELRESPONSE 0x046A - -#define SL_OPCODE_DEVICE_NETCFG_SET_COMMAND 0x8432 -#define SL_OPCODE_DEVICE_NETCFG_SET_RESPONSE 0x0432 -#define SL_OPCODE_DEVICE_NETCFG_GET_COMMAND 0x8433 -#define SL_OPCODE_DEVICE_NETCFG_GET_RESPONSE 0x0433 -/* */ -#define SL_OPCODE_DEVICE_SETUARTMODECOMMAND 0x846B -#define SL_OPCODE_DEVICE_SETUARTMODERESPONSE 0x046B -#define SL_OPCODE_DEVICE_SSISIZESETCOMMAND 0x846B -#define SL_OPCODE_DEVICE_SSISIZESETRESPONSE 0x046B - -/* */ -#define SL_OPCODE_DEVICE_EVENTMASKSET 0x8464 -#define SL_OPCODE_DEVICE_EVENTMASKSETRESPONSE 0x0464 -#define SL_OPCODE_DEVICE_EVENTMASKGET 0x8465 -#define SL_OPCODE_DEVICE_EVENTMASKGETRESPONSE 0x0465 - -#define SL_OPCODE_DEVICE_DEVICEGET 0x8466 -#define SL_OPCODE_DEVICE_DEVICEGETRESPONSE 0x0466 -#define SL_OPCODE_DEVICE_DEVICESET 0x84B7 -#define SL_OPCODE_DEVICE_DEVICESETRESPONSE 0x04B7 - -#define SL_OPCODE_WLAN_SCANRESULTSGETCOMMAND 0x8C8C -#define SL_OPCODE_WLAN_SCANRESULTSGETRESPONSE 0x0C8C -#define SL_OPCODE_WLAN_SMARTCONFIGOPTSET 0x8C8D -#define SL_OPCODE_WLAN_SMARTCONFIGOPTSETRESPONSE 0x0C8D -#define SL_OPCODE_WLAN_SMARTCONFIGOPTGET 0x8C8E -#define SL_OPCODE_WLAN_SMARTCONFIGOPTGETRESPONSE 0x0C8E - - -/* Rx Filters opcodes */ -#define SL_OPCODE_WLAN_WLANRXFILTERADDCOMMAND 0x8C6C -#define SL_OPCODE_WLAN_WLANRXFILTERADDRESPONSE 0x0C6C -#define SL_OPCODE_WLAN_WLANRXFILTERSETCOMMAND 0x8C6D -#define SL_OPCODE_WLAN_WLANRXFILTERSETRESPONSE 0x0C6D -#define SL_OPCODE_WLAN_WLANRXFILTERGETSTATISTICSINFOCOMMAND 0x8C6E -#define SL_OPCODE_WLAN_WLANRXFILTERGETSTATISTICSINFORESPONSE 0x0C6E -#define SL_OPCODE_WLAN_WLANRXFILTERGETCOMMAND 0x8C6F -#define SL_OPCODE_WLAN_WLANRXFILTERGETRESPONSE 0x0C6F -#define SL_OPCODE_WLAN_WLANRXFILTERGETINFO 0x8C70 -#define SL_OPCODE_WLAN_WLANRXFILTERGETINFORESPONSE 0x0C70 - - -/******************************************************************************************/ -/* Device structs */ -/******************************************************************************************/ -typedef _u32 InitStatus_t; - - -typedef struct -{ - _i32 Status; -}InitComplete_t; - -typedef struct -{ - _i16 status; - _u16 padding; - -}_BasicResponse_t; - -typedef struct -{ - _u16 Timeout; - _u16 padding; -}_DevStopCommand_t; - -typedef struct -{ - _u32 group; - _u32 mask; -}_DevMaskEventSetCommand_t; - -typedef _BasicResponse_t _DevMaskEventSetResponse_t; - - -typedef struct -{ - _u32 group; -}_DevMaskEventGetCommand_t; - - -typedef struct -{ - _u32 group; - _u32 mask; -}_DevMaskEventGetResponse_t; - - -typedef struct -{ - _u32 group; -}_DevStatusGetCommand_t; - - -typedef struct -{ - _u32 group; - _u32 status; -}_DevStatusGetResponse_t; - -typedef struct -{ - _u32 ChipId; - _u32 FwVersion[4]; - _u8 PhyVersion[4]; -}_Device_VersionReadResponsePart_t; - -typedef struct -{ - _Device_VersionReadResponsePart_t part; - _u32 NwpVersion[4]; - _u16 RomVersion; - _u16 Padding; -}_Device_VersionReadResponseFull_t; - - -typedef struct -{ - _u32 BaudRate; - _u8 FlowControlEnable; -}_DevUartSetModeCommand_t; - -typedef _BasicResponse_t _DevUartSetModeResponse_t; - -/******************************************************/ - -typedef struct -{ - _u8 SsiSizeInBytes; - _u8 Padding[3]; -}_StellarisSsiSizeSet_t; - -/*****************************************************************************************/ -/* WLAN structs */ -/*****************************************************************************************/ -#define MAXIMAL_PASSWORD_LENGTH (64) - -typedef struct{ - _u8 SecType; - _u8 SsidLen; - _u8 Bssid[6]; - _u8 PasswordLen; -}_WlanConnectCommon_t; - -#define SSID_STRING(pCmd) (_i8 *)((_WlanConnectCommon_t *)(pCmd) + 1) -#define PASSWORD_STRING(pCmd) (SSID_STRING(pCmd) + ((_WlanConnectCommon_t *)(pCmd))->SsidLen) - -typedef struct{ - _WlanConnectCommon_t Common; - _u8 UserLen; - _u8 AnonUserLen; - _u8 CertIndex; - _u32 EapBitmask; -}_WlanConnectEapCommand_t; - -#define EAP_SSID_STRING(pCmd) (_i8 *)((_WlanConnectEapCommand_t *)(pCmd) + 1) -#define EAP_PASSWORD_STRING(pCmd) (EAP_SSID_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->Common.SsidLen) -#define EAP_USER_STRING(pCmd) (EAP_PASSWORD_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->Common.PasswordLen) -#define EAP_ANON_USER_STRING(pCmd) (EAP_USER_STRING(pCmd) + ((_WlanConnectEapCommand_t *)(pCmd))->UserLen) - - -typedef struct -{ - _u8 PolicyType; - _u8 Padding; - _u8 PolicyOption; - _u8 PolicyOptionLen; -}_WlanPoliciySetGet_t; - - -typedef struct{ - _u32 minDwellTime; - _u32 maxDwellTime; - _u32 numProbeResponse; - _u32 G_Channels_mask; - _i32 rssiThershold; - _i32 snrThershold; - _i32 defaultTXPower; - _u16 intervalList[16]; -}_WlanScanParamSetCommand_t; - - -typedef struct{ - _i8 SecType; - _u8 SsidLen; - _u8 Priority; - _u8 Bssid[6]; - _u8 PasswordLen; - _u8 WepKeyId; -}_WlanAddGetProfile_t; - - -typedef struct{ - _WlanAddGetProfile_t Common; - _u8 UserLen; - _u8 AnonUserLen; - _u8 CertIndex; - _u16 padding; - _u32 EapBitmask; -}_WlanAddGetEapProfile_t; - - - - -#define PROFILE_SSID_STRING(pCmd) ((_i8 *)((_WlanAddGetProfile_t *)(pCmd) + 1)) -#define PROFILE_PASSWORD_STRING(pCmd) (PROFILE_SSID_STRING(pCmd) + ((_WlanAddGetProfile_t *)(pCmd))->SsidLen) - -#define EAP_PROFILE_SSID_STRING(pCmd) (_i8 *)((_WlanAddGetEapProfile_t *)(pCmd) + 1) -#define EAP_PROFILE_PASSWORD_STRING(pCmd) (EAP_PROFILE_SSID_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->Common.SsidLen) -#define EAP_PROFILE_USER_STRING(pCmd) (EAP_PROFILE_PASSWORD_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->Common.PasswordLen) -#define EAP_PROFILE_ANON_USER_STRING(pCmd) (EAP_PROFILE_USER_STRING(pCmd) + ((_WlanAddGetEapProfile_t *)(pCmd))->UserLen) - - - -typedef struct -{ - _u8 index; - _u8 padding[3]; -}_WlanProfileDelGetCommand_t; - -typedef _BasicResponse_t _WlanGetNetworkListResponse_t; - -typedef struct -{ - _u8 index; - _u8 count; - _i8 padding[2]; -}_WlanGetNetworkListCommand_t; - - - - -typedef struct -{ - _u32 groupIdBitmask; - _u8 cipher; - _u8 publicKeyLen; - _u8 group1KeyLen; - _u8 group2KeyLen; -}_WlanSmartConfigStartCommand_t; - -#define SMART_CONFIG_START_PUBLIC_KEY_STRING(pCmd) ((_i8 *)((_WlanSmartConfigStartCommand_t *)(pCmd) + 1)) -#define SMART_CONFIG_START_GROUP1_KEY_STRING(pCmd) ((_i8 *) (SMART_CONFIG_START_PUBLIC_KEY_STRING(pCmd) + ((_WlanSmartConfigStartCommand_t *)(pCmd))->publicKeyLen)) -#define SMART_CONFIG_START_GROUP2_KEY_STRING(pCmd) ((_i8 *) (SMART_CONFIG_START_GROUP1_KEY_STRING(pCmd) + ((_WlanSmartConfigStartCommand_t *)(pCmd))->group1KeyLen)) - - - -typedef struct -{ - _u8 mode; - _u8 padding[3]; -}_WlanSetMode_t; - - - - -typedef struct -{ - _u16 Status; - _u16 ConfigId; - _u16 ConfigOpt; - _u16 ConfigLen; -}_WlanCfgSetGet_t; - - -/* ******************************************************************************/ -/* RX filters - Start */ -/* ******************************************************************************/ -/* -- 80 bytes */ -typedef struct _WlanRxFilterAddCommand_t -{ - /* -- 1 byte */ - SlrxFilterRuleType_t RuleType; - /* -- 1 byte */ - SlrxFilterFlags_t FilterFlags; - /* -- 1 byte */ - SlrxFilterID_t FilterId; - /* -- 1 byte */ - _u8 Padding; - /* -- 56 byte */ - SlrxFilterRule_t Rule; - /* -- 12 byte ( 3 padding ) */ - SlrxFilterTrigger_t Trigger; - /* -- 8 byte */ - SlrxFilterAction_t Action; -}_WlanRxFilterAddCommand_t; - - - -/* -- 4 bytes */ -typedef struct l_WlanRxFilterAddCommandReponse_t -{ - /* -- 1 byte */ - SlrxFilterID_t FilterId; - /* -- 1 Byte */ - _u8 Status; - /* -- 2 byte */ - _u8 Padding[2]; - -}_WlanRxFilterAddCommandReponse_t; - - - -/* - * \struct _WlanRxFilterSetCommand_t - */ -typedef struct _WlanRxFilterSetCommand_t -{ - _u16 InputBufferLength; - /* 1 byte */ - SLrxFilterOperation_t RxFilterOperation; - _u8 Padding[1]; -}_WlanRxFilterSetCommand_t; - -/** - * \struct _WlanRxFilterSetCommandReponse_t - */ -typedef struct _WlanRxFilterSetCommandReponse_t -{ - /* 1 byte */ - _u8 Status; - /* 3 bytes */ - _u8 Padding[3]; - -}_WlanRxFilterSetCommandReponse_t; - -/** - * \struct _WlanRxFilterGetCommand_t - */ -typedef struct _WlanRxFilterGetCommand_t -{ - _u16 OutputBufferLength; - /* 1 byte */ - SLrxFilterOperation_t RxFilterOperation; - _u8 Padding[1]; -}_WlanRxFilterGetCommand_t; - -/** - * \struct _WlanRxFilterGetCommandReponse_t - */ -typedef struct _WlanRxFilterGetCommandReponse_t -{ - /* 1 byte */ - _u8 Status; - /* 1 bytes */ - _u8 Padding; - /* 2 byte */ - _u16 OutputBufferLength; - -}_WlanRxFilterGetCommandReponse_t; - - - -/* ******************************************************************************/ -/* RX filters -- End */ -/* ******************************************************************************/ - -typedef struct -{ - _u16 status; - _u8 WlanRole; /* 0 = station, 2 = AP */ - _u8 Ipv6Enabled; - _u8 Ipv6DhcpEnabled; - - _u32 ipV6Global[4]; - _u32 ipV6Local[4]; - _u32 ipV6DnsServer[4]; - _u8 Ipv6DhcpState; - -}_NetappIpV6configRetArgs_t; - - -typedef struct -{ - _u8 ipV4[4]; - _u8 ipV4Mask[4]; - _u8 ipV4Gateway[4]; - _u8 ipV4DnsServer[4]; - _u8 ipV4Start[4]; - _u8 ipV4End[4]; -}_NetCfgIpV4AP_Args_t; - - - -typedef struct -{ - _u16 status; - _u8 MacAddr[6]; -} _MAC_Address_SetGet_t; - - -typedef struct -{ - _u16 Status; - _u16 ConfigId; - _u16 ConfigOpt; - _u16 ConfigLen; -}_NetCfgSetGet_t; - -typedef struct -{ - _u16 Status; - _u16 DeviceSetId; - _u16 Option; - _u16 ConfigLen; -}_DeviceSetGet_t; - - - - -/******************************************************************************************/ -/* Socket structs */ -/******************************************************************************************/ - -typedef struct -{ - _u8 Domain; - _u8 Type; - _u8 Protocol; - _u8 Padding; -}_SocketCommand_t; - - -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 padding; -}_SocketResponse_t; - -typedef struct -{ - _u8 sd; - _u8 family; - _u8 padding1; - _u8 padding2; -}_AcceptCommand_t; - - -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 family; - _u16 port; - _u16 paddingOrAddr; - _u32 address; -}_SocketAddrAsyncIPv4Response_t; - -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 family; - _u16 port; - _u8 address[6]; -}_SocketAddrAsyncIPv6EUI48Response_t; -typedef struct -{ - _i16 statusOrLen; - _u8 sd; - _u8 family; - _u16 port; - _u16 paddingOrAddr; - _u32 address[4]; -}_SocketAddrAsyncIPv6Response_t; - - -typedef struct -{ - _i16 lenOrPadding; - _u8 sd; - _u8 FamilyAndFlags; - _u16 port; - _u16 paddingOrAddr; - _u32 address; -}_SocketAddrIPv4Command_t; - -typedef struct -{ - _i16 lenOrPadding; - _u8 sd; - _u8 FamilyAndFlags; - _u16 port; - _u8 address[6]; -}_SocketAddrIPv6EUI48Command_t; -typedef struct -{ - _i16 lenOrPadding; - _u8 sd; - _u8 FamilyAndFlags; - _u16 port; - _u16 paddingOrAddr; - _u32 address[4]; -}_SocketAddrIPv6Command_t; - -typedef union { - _SocketAddrIPv4Command_t IpV4; - _SocketAddrIPv6EUI48Command_t IpV6EUI48; -#ifdef SL_SUPPORT_IPV6 - _SocketAddrIPv6Command_t IpV6; -#endif -} _SocketAddrCommand_u; - -typedef union { - _SocketAddrAsyncIPv4Response_t IpV4; - _SocketAddrAsyncIPv6EUI48Response_t IpV6EUI48; -#ifdef SL_SUPPORT_IPV6 - _SocketAddrAsyncIPv6Response_t IpV6; -#endif -} _SocketAddrResponse_u; - -typedef struct -{ - _u8 sd; - _u8 backlog; - _u8 padding1; - _u8 padding2; -}_ListenCommand_t; - -typedef struct -{ - _u8 sd; - _u8 padding0; - _u8 padding1; - _u8 padding2; -}_CloseCommand_t; - - -typedef struct -{ - _u8 nfds; - _u8 readFdsCount; - _u8 writeFdsCount; - _u8 padding; - _u16 readFds; - _u16 writeFds; - _u16 tv_usec; - _u16 tv_sec; -}_SelectCommand_t; - - -typedef struct -{ - _u16 status; - _u8 readFdsCount; - _u8 writeFdsCount; - _u16 readFds; - _u16 writeFds; -}_SelectAsyncResponse_t; - -typedef struct -{ - _u8 sd; - _u8 level; - _u8 optionName; - _u8 optionLen; -}_setSockOptCommand_t; - -typedef struct -{ - _u8 sd; - _u8 level; - _u8 optionName; - _u8 optionLen; -}_getSockOptCommand_t; - -typedef struct -{ - _i16 status; - _u8 sd; - _u8 optionLen; -}_getSockOptResponse_t; - - -typedef struct -{ - _u16 StatusOrLen; - _u8 sd; - _u8 FamilyAndFlags; -}_sendRecvCommand_t; - -/***************************************************************************************** -* NETAPP structs -******************************************************************************************/ - - -typedef _BasicResponse_t _NetAppStartStopResponse_t; - -typedef struct -{ - _u32 appId; -}_NetAppStartStopCommand_t; - -typedef struct -{ - _u16 Status; - _u16 AppId; - _u16 ConfigOpt; - _u16 ConfigLen; -}_NetAppSetGet_t; -typedef struct -{ - _u16 port_number; -} _NetAppHttpServerGetSet_port_num_t; - -typedef struct -{ - _u8 auth_enable; -}_NetAppHttpServerGetSet_auth_enable_t; - -typedef struct _sl_NetAppHttpServerGetToken_t -{ - _u8 token_name_len; - _u8 padd1; - _u16 padd2; -}sl_NetAppHttpServerGetToken_t; - -typedef struct _sl_NetAppHttpServerSendToken_t -{ - _u8 token_value_len; - _u8 token_name_len; - _u8 token_name[MAX_TOKEN_NAME_LEN]; - _u16 padd; -}sl_NetAppHttpServerSendToken_t; - -typedef struct _sl_NetAppHttpServerPostToken_t -{ - _u8 post_action_len; - _u8 token_name_len; - _u8 token_value_len; - _u8 padding; -}sl_NetAppHttpServerPostToken_t; - - -typedef struct -{ - _u16 Len; - _u8 family; - _u8 padding; -}_GetHostByNameCommand_t; - -typedef struct -{ - _u16 status; - _u16 padding; - _u32 ip0; - _u32 ip1; - _u32 ip2; - _u32 ip3; -}_GetHostByNameIPv6AsyncResponse_t; - -typedef struct -{ - _u16 status; - _u8 padding1; - _u8 padding2; - _u32 ip0; -}_GetHostByNameIPv4AsyncResponse_t; - - - - -typedef enum -{ - CTST_BSD_UDP_TX, - CTST_BSD_UDP_RX, - CTST_BSD_TCP_TX, - CTST_BSD_TCP_RX, - CTST_BSD_TCP_SERVER_BI_DIR, - CTST_BSD_TCP_CLIENT_BI_DIR, - CTST_BSD_UDP_BI_DIR, - CTST_BSD_RAW_TX, - CTST_BSD_RAW_RX, - CTST_BSD_RAW_BI_DIR, - CTST_BSD_SECURED_TCP_TX, - CTST_BSD_SECURED_TCP_RX, - CTST_BSD_SECURED_TCP_SERVER_BI_DIR, - CTST_BSD_SECURED_TCP_CLIENT_BI_DIR - }CommTest_e; - -typedef struct _sl_protocol_CtestStartCommand_t -{ - _u32 Test; - _u16 DestPort; - _u16 SrcPort; - _u32 DestAddr[4]; - _u32 PayloadSize; - _u32 timeout; - _u32 csEnabled; - _u32 secure; - _u32 rawProtocol; - _u8 reserved1[4]; -}_CtestStartCommand_t; - -typedef struct -{ - _u8 test; - _u8 socket; - _i16 status; - _u32 startTime; - _u32 endTime; - _u16 txKbitsSec; - _u16 rxKbitsSec; - _u32 outOfOrderPackets; - _u32 missedPackets; - _i16 token; -}_CtestAsyncResponse_t; - -typedef struct -{ - _u32 pingIntervalTime; - _u16 PingSize; - _u16 pingRequestTimeout; - _u32 totalNumberOfAttempts; - _u32 flags; - _u32 ip0; - _u32 ip1OrPaadding; - _u32 ip2OrPaadding; - _u32 ip3OrPaadding; -}_PingStartCommand_t; - -typedef struct -{ - _u16 status; - _u16 rttMin; - _u16 rttMax; - _u16 rttAvg; - _u32 numSuccsessPings; - _u32 numSendsPings; - _u32 testTime; -}_PingReportResponse_t; - - -typedef struct -{ - _u32 ip; - _u32 gateway; - _u32 dns; -}_IpV4AcquiredAsync_t; - - -typedef enum -{ - ACQUIRED_IPV6_LOCAL = 1, - ACQUIRED_IPV6_GLOBAL -}IpV6AcquiredType_e; - - -typedef struct -{ - _u32 type; - _u32 ip[4]; - _u32 gateway[4]; - _u32 dns[4]; -}_IpV6AcquiredAsync_t; - - -typedef union -{ - _SocketCommand_t EventMask; - _sendRecvCommand_t DeviceInit; -}_device_commands_t; - -/***************************************************************************************** -* FS structs -******************************************************************************************/ - -typedef struct -{ - _u32 FileHandle; - _u32 Offset; - _u16 Len; - _u16 Padding; -}_FsReadCommand_t; - -typedef struct -{ - _u32 Mode; - _u32 Token; -}_FsOpenCommand_t; - -typedef struct -{ - _u32 FileHandle; - _u32 Token; -}_FsOpenResponse_t; - - -typedef struct -{ - _u32 FileHandle; - _u32 CertificFileNameLength; - _u32 SignatureLen; -}_FsCloseCommand_t; - - -typedef _BasicResponse_t _FsReadResponse_t; -typedef _BasicResponse_t _FsDeleteResponse_t; -typedef _BasicResponse_t _FsCloseResponse_t; - -typedef struct -{ - _u16 Status; - _u16 flags; - _u32 FileLen; - _u32 AllocatedLen; - _u32 Token[4]; -}_FsGetInfoResponse_t; - -typedef struct -{ - _u8 DeviceID; - _u8 Padding[3]; -}_FsFormatCommand_t; - -typedef _BasicResponse_t _FsFormatResponse_t; - -typedef struct -{ - _u32 Token; -}_FsDeleteCommand_t; - -typedef _FsDeleteCommand_t _FsGetInfoCommand_t; - -typedef struct -{ - _u32 FileHandle; - _u32 Offset; - _u16 Len; - _u16 Padding; -}_FsWriteCommand_t; - -typedef _BasicResponse_t _FsWriteResponse_t; - - - -/* TODO: Set MAx Async Payload length depending on flavor (Tiny, Small, etc.) */ - - -#ifdef SL_TINY_EXT -#define SL_ASYNC_MAX_PAYLOAD_LEN 120 /* size must be aligned to 4 */ -#else -#define SL_ASYNC_MAX_PAYLOAD_LEN 160 /* size must be aligned to 4 */ -#endif - -#define SL_ASYNC_MAX_MSG_LEN (_SL_RESP_HDR_SIZE + SL_ASYNC_MAX_PAYLOAD_LEN) - -#define RECV_ARGS_SIZE (sizeof(_SocketResponse_t)) -#define RECVFROM_IPV4_ARGS_SIZE (sizeof(_SocketAddrAsyncIPv4Response_t)) -#define RECVFROM_IPV6_ARGS_SIZE (sizeof(_SocketAddrAsyncIPv6Response_t)) - -#define SL_IPV4_ADDRESS_SIZE (sizeof(_u32)) -#define SL_IPV6_ADDRESS_SIZE (4 * sizeof(_u32)) - -#endif /* _SL_PROTOCOL_TYPES_H_ */ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/simplelink.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/simplelink.h deleted file mode 100644 index 19ca17f0..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/simplelink.h +++ /dev/null @@ -1,948 +0,0 @@ -/* - * simplelink.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - -/*! - \mainpage SimpleLink Driver - - \section intro_sec Introduction - - The SimpleLink CC31xx/CC2xx family allows to add Wi-Fi and networking capabilities - to low-cost embedded products without having prior Wi-Fi, RF or networking expertise. - The CC31xx/CC32xx is an ideal solution for microcontroller-based sensor and control - applications such as home appliances, home automation and smart metering. - The CC31xx/CC32xx has integrated a comprehensive TCP/IP network stack, Wi-Fi driver and - security supplicant leading to easier portability to microcontrollers, to an - ultra-low memory footprint, all without compromising the capabilities and robustness - of the final application. - - - - \section modules_sec Module Names - To make it simple, TI's SimpleLink CC31xx/CC32xx platform capabilities were divided into modules by topic (Silo). - These capabilities range from basic device management through wireless - network configuration, standard BSD socket and much more. - Listed below are the various modules in the SimpleLink CC31xx/CC32xx driver: - -# \ref device - controls the behaviour of the CC31xx/CC32xx device (start/stop, events masking and obtaining specific device status) - -# \ref wlan - controls the use of the WiFi WLAN module including: - - Connection features, such as: profiles, policies, SmartConfig� - - Advanced WLAN features, such as: scans, rx filters and rx statistics collection - -# \ref socket - controls standard client/server sockets programming options and capabilities - -# \ref netapp - activates networking applications, such as: HTTP Server, DHCP Server, Ping, DNS and mDNS. - -# \ref netcfg - controls the configuration of the device addresses (i.e. IP and MAC addresses) - -# \ref FileSystem - provides file system capabilities to TI's CC31XX that can be used by both the CC31XX device and the user. - - - \section proting_sec Porting Guide - - The porting of the SimpleLink driver to any new platform is based on few simple steps. - This guide takes you through this process step by step. Please follow the instructions - carefully to avoid any problems during this process and to enable efficient and proper - work with the device. - Please notice that all modifications and porting adjustments of the driver should be - made in the user.h header file only. - Keep making any of the changes only in this file will ensure smoothly transaction to - new versions of the driver at the future! - - - \subsection porting_step1 Step 1 - Create your own user.h file - - The first step is to create a user.h file that will include your configurations and - adjustments. You can use the empty template provided as part of this driver or - you can choose to base your file on file from one of the wide range of examples - applications provided by Texas Instruments - - - \subsection porting_step2 Step 2 - Select the capabilities set required for your application - - Texas Instruments made a lot of efforts to build set of predefined capability sets that would - fit most of the target application. - It is recommended to try and choose one of this predefined capabilities set before going to - build your own customized set. If you find compatible set you can skip the rest of this step. - - The available sets are: - -# SL_TINY - Compatible to be used on platforms with very limited resources. Provides - the best in class foot print in terms of Code and Data consumption. - -# SL_SMALL - Compatible to most common networking applications. Provide the most - common APIs with decent balance between code size, data size, functionality - and performances - -# SL_FULL - Provide access to all SimpleLink functionalities - - - \subsection porting_step3 Step 3 - Bind the device enable/disable output line - - The enable/disable line (nHib) provide mechanism to enter the device into the least current - consumption mode. This mode could be used when no traffic is required (tx/rx). - when this line is not connected to any IO of the host this define should be left empty. - Not connecting this line results in ability to start the driver only once. - - - \subsection porting_step4 Step 4 - Writing your interface communication driver - - The SimpleLink device support several standard communication protocol among SPI and - UART. Depending on your needs and your hardware design, you should choose the - communication channel type. - The interface for this communication channel should include 4 simple access functions: - -# open - -# close - -# read - -# write - - The way this driver would be implemented is directly effecting the efficiency and - the performances of the SimpleLink device on this platform. - If your system has DMA you should consider to use it in order to increase the utilization - of the communication channel - If you have enough memory resources you should consider using a buffer to increase the - efficiency of the write operations. - - - \subsection porting_step5 Step 5 - Choose your memory management model - - The SimpleLink driver support two memory models: - -# Static (default) - -# Dynamic - - If you choose to work in dynamic model you will have to provide alloc and free functions - to be used by the Simple Link driver otherwise nothing need to be done. - - - \subsection porting_step6 Step 6 - OS adaptation - - The SimpleLink driver could run on two kind of platforms: - -# Non-Os / Single Threaded (default) - -# Multi-Threaded - - If you choose to work in multi-threaded environment under operating system you will have to - provide some basic adaptation routines to allow the driver to protect access to resources - for different threads (locking object) and to allow synchronization between threads (sync objects). - In additional the driver support running without dedicated thread allocated solely to the simple - link driver. If you choose to work in this mode, you should also supply a spawn method that - will enable to run function on a temporary context. - - - \subsection porting_step7 Step 7 - Set your asynchronous event handlers routines - - The SimpleLink device generate asynchronous events in several situations. - These asynchronous events could be masked. - In order to catch these events you have to provide handler routines. - Please notice that if you not provide a handler routine and the event is received, - the driver will drop this event without any indication of this drop. - - - \subsection porting_step8 Step 8 - Run diagnostic tools to validate the correctness of your porting - - The driver is delivered with some porting diagnostic tools to simplify the porting validation process - and to reduce issues latter. It is very important to follow carefully this process. - - The diagnostic process include: - -# Validating Interface Communication Driver - -# Validating OS adaptation layer - -# Validating HW integrity - -# Validating basic work with the device - - - \section sw_license License - - * - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -#ifndef __SIMPLELINK_H__ -#define __SIMPLELINK_H__ - -#include "user.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - - -/*! \attention Async event activation notes - Function prototypes for event callback handlers - Event handler function names should be defined in the user.h file - e.g. - "#define sl_WlanEvtHdlr SLWlanEventHandler" - Indicates all WLAN events are handled by User func "SLWlanEventHandler" - Important notes: - 1. Event handlers cannot activate another SimpleLink API from the event's context - 2. Event's data is valid during event's context. Any application data - which is required for the user application should be copied or marked - into user's variables - 3. It is not recommended to delay the execution of the event callback handler - -*/ - -/*! - - \addtogroup UserEvents - @{ - -*/ - - -/*****************************************************************************/ -/* Macro declarations for Host Driver version */ -/*****************************************************************************/ -#define SL_DRIVER_VERSION "1.0.0.10" -#define SL_MAJOR_VERSION_NUM 1L -#define SL_MINOR_VERSION_NUM 0L -#define SL_VERSION_NUM 0L -#define SL_SUB_VERSION_NUM 10L - - -/*****************************************************************************/ -/* Macro declarations for predefined configurations */ -/*****************************************************************************/ - -#ifdef SL_TINY -#undef SL_INC_ARG_CHECK -#undef SL_INC_EXT_API -#undef SL_INC_SOCK_SERVER_SIDE_API -#undef SL_INC_WLAN_PKG -#undef SL_INC_NET_CFG_PKG -#undef SL_INC_FS_PKG -#undef SL_INC_SET_UART_MODE -#undef SL_INC_STD_BSD_API_NAMING -#undef SL_INC_SOCK_CLIENT_SIDE_API -#undef SL_INC_NET_APP_PKG -#undef SL_INC_SOCK_RECV_API -#undef SL_INC_SOCK_SEND_API -#undef SL_INC_SOCKET_PKG -#endif - -#ifdef SL_SMALL -#undef SL_INC_EXT_API -#undef SL_INC_NET_APP_PKG -#undef SL_INC_NET_CFG_PKG -#undef SL_INC_FS_PKG -#define SL_INC_ARG_CHECK -#define SL_INC_WLAN_PKG -#define SL_INC_SOCKET_PKG -#define SL_INC_SOCK_CLIENT_SIDE_API -#define SL_INC_SOCK_SERVER_SIDE_API -#define SL_INC_SOCK_RECV_API -#define SL_INC_SOCK_SEND_API -#define SL_INC_SET_UART_MODE -#endif - -#ifdef SL_FULL -#define SL_INC_EXT_API -#define SL_INC_NET_APP_PKG -#define SL_INC_NET_CFG_PKG -#define SL_INC_FS_PKG -#define SL_INC_ARG_CHECK -#define SL_INC_WLAN_PKG -#define SL_INC_SOCKET_PKG -#define SL_INC_SOCK_CLIENT_SIDE_API -#define SL_INC_SOCK_SERVER_SIDE_API -#define SL_INC_SOCK_RECV_API -#define SL_INC_SOCK_SEND_API -#define SL_INC_SET_UART_MODE -#endif - -#define SL_RET_CODE_OK (0) -#define SL_RET_CODE_INVALID_INPUT (-2) -#define SL_RET_CODE_SELF_ERROR (-3) -#define SL_RET_CODE_NWP_IF_ERROR (-4) -#define SL_RET_CODE_MALLOC_ERROR (-5) - -#define sl_Memcpy memcpy -#define sl_Memset memset - -#define sl_SyncObjClear(pObj) sl_SyncObjWait(pObj,SL_OS_NO_WAIT) - -#ifndef SL_TINY_EXT -#define SL_MAX_SOCKETS (8) -#else -#define SL_MAX_SOCKETS (2) -#endif - - -/*****************************************************************************/ -/* Types definitions */ -/*****************************************************************************/ -typedef void (*_SlSpawnEntryFunc_t)(void* pValue); - -#ifndef NULL -#define NULL (0) -#endif - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -#ifndef OK -#define OK (0) -#endif - -#ifndef _SL_USER_TYPES - typedef unsigned char _u8; - typedef signed char _i8; - - typedef unsigned short _u16; - typedef signed short _i16; - - typedef unsigned long _u32; - typedef signed long _i32; - #define _volatile volatile - #define _const const -#endif - -typedef _u16 _SlOpcode_t; -typedef _u8 _SlArgSize_t; -typedef _i16 _SlDataSize_t; -typedef _i16 _SlReturnVal_t; - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - - -/* - * This event status used to block or continue the event propagation - * through all the registered external libs/user application - * - */ - - typedef enum { - EVENT_PROPAGATION_BLOCK = 0, - EVENT_PROPAGATION_CONTINUE - - } _SlEventPropogationStatus_e; - - - - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ - -#ifdef SL_PLATFORM_MULTI_THREADED - #include "spawn.h" -#else - #include "nonos.h" -#endif - - -/* - objInclusion.h and user.h must be included before all api header files - objInclusion.h must be the last arrangement just before including the API header files - since it based on the other configurations to decide which object should be included -*/ -#include "objInclusion.h" -#include "trace.h" -#include "fs.h" -#include "socket.h" -#include "netapp.h" -#include "wlan.h" -#include "device.h" -#include "netcfg.h" -#include "wlan_rx_filters.h" - - - /* The general events dispatcher which is - * initialized to the user handler */ -#ifdef sl_GeneralEvtHdlr -#define _SlDrvHandleGeneralEvents sl_GeneralEvtHdlr -#endif - - /* The wlan events dispatcher which is - * initialized to the user handler */ -#ifdef sl_WlanEvtHdlr -#define _SlDrvHandleWlanEvents sl_WlanEvtHdlr -#endif - - /* The NetApp events dispatcher which is - * initialized to the user handler */ -#ifdef sl_NetAppEvtHdlr -#define _SlDrvHandleNetAppEvents sl_NetAppEvtHdlr -#endif - - /* The http server events dispatcher which is - * initialized to the user handler if exists */ -#ifdef sl_HttpServerCallback -#define _SlDrvHandleHttpServerEvents sl_HttpServerCallback -#endif - - /* The socket events dispatcher which is - * initialized to the user handler */ -#ifdef sl_SockEvtHdlr -#define _SlDrvHandleSockEvents sl_SockEvtHdlr -#endif - - -#ifndef __CONCAT -#define __CONCAT(x,y) x ## y -#endif -#define __CONCAT2(x,y) __CONCAT(x,y) - - -/* - * The section below handles the external lib event registration - * according to the desired events it specified in its API header file. - * The external lib should be first installed by the user (see user.h) - */ -#ifdef SL_EXT_LIB_1 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib1GeneralEventHandler __CONCAT2(SL_EXT_LIB_1, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib1WlanEventHandler __CONCAT2(SL_EXT_LIB_1, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib1NetAppEventHandler __CONCAT2(SL_EXT_LIB_1, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib1HttpServerEventHandler __CONCAT2(SL_EXT_LIB_1, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_1, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_1, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib1SockEventHandler __CONCAT2(SL_EXT_LIB_1, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_2 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib2GeneralEventHandler __CONCAT2(SL_EXT_LIB_2, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib2WlanEventHandler __CONCAT2(SL_EXT_LIB_2, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib2NetAppEventHandler __CONCAT2(SL_EXT_LIB_2, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib2HttpServerEventHandler __CONCAT2(SL_EXT_LIB_2, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_2, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_2, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib2SockEventHandler __CONCAT2(SL_EXT_LIB_2, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_3 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib3GeneralEventHandler __CONCAT2(SL_EXT_LIB_3, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib3WlanEventHandler __CONCAT2(SL_EXT_LIB_3, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib3NetAppEventHandler __CONCAT2(SL_EXT_LIB_3, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib3HttpServerEventHandler __CONCAT2(SL_EXT_LIB_3, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_3, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_3, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib3SockEventHandler __CONCAT2(SL_EXT_LIB_3, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_4 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib4GeneralEventHandler __CONCAT2(SL_EXT_LIB_4, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib4WlanEventHandler __CONCAT2(SL_EXT_LIB_4, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib4NetAppEventHandler __CONCAT2(SL_EXT_LIB_4, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib4HttpServerEventHandler __CONCAT2(SL_EXT_LIB_4, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_4, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_4, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib4SockEventHandler __CONCAT2(SL_EXT_LIB_4, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - -#ifdef SL_EXT_LIB_5 - - /* General Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_GENERAL_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _GeneralEventHdl) (SlDeviceEvent_t *); - #define SlExtLib5GeneralEventHandler __CONCAT2(SL_EXT_LIB_5, _GeneralEventHdl) - - #undef EXT_LIB_REGISTERED_GENERAL_EVENTS - #define EXT_LIB_REGISTERED_GENERAL_EVENTS - #endif - - /* Wlan Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_WLAN_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _WlanEventHdl) (SlWlanEvent_t *); - #define SlExtLib5WlanEventHandler __CONCAT2(SL_EXT_LIB_5, _WlanEventHdl) - - #undef EXT_LIB_REGISTERED_WLAN_EVENTS - #define EXT_LIB_REGISTERED_WLAN_EVENTS - #endif - - /* NetApp Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_NETAPP_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _NetAppEventHdl) (SlNetAppEvent_t *); - #define SlExtLib5NetAppEventHandler __CONCAT2(SL_EXT_LIB_5, _NetAppEventHdl) - - #undef EXT_LIB_REGISTERED_NETAPP_EVENTS - #define EXT_LIB_REGISTERED_NETAPP_EVENTS - #endif - - /* Http Server Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_HTTP_SERVER_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _HttpServerEventHdl) (SlHttpServerEvent_t* , SlHttpServerResponse_t*); - #define SlExtLib5HttpServerEventHandler __CONCAT2(SL_EXT_LIB_5, _HttpServerEventHdl) - - #undef EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #define EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS - #endif - - /* Socket Event Registration */ - #if __CONCAT2(SL_EXT_LIB_5, _NOTIFY_SOCK_EVENT) - extern _SlEventPropogationStatus_e __CONCAT2(SL_EXT_LIB_5, _SockEventHdl) (SlSockEvent_t *); - #define SlExtLib5SockEventHandler __CONCAT2(SL_EXT_LIB_5, _SockEventHdl) - - #undef EXT_LIB_REGISTERED_SOCK_EVENTS - #define EXT_LIB_REGISTERED_SOCK_EVENTS - #endif - -#endif - - - -#if defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) -extern void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent); -#endif - -#if defined(EXT_LIB_REGISTERED_WLAN_EVENTS) -extern void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent); -#endif - -#if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS) -extern void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent); -#endif - -#if defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) -extern void _SlDrvHandleHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse); -#endif - - -#if defined(EXT_LIB_REGISTERED_SOCK_EVENTS) -extern void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent); -#endif - - -typedef void (*_SlSpawnEntryFunc_t)(void* pValue); - - -/* Async functions description*/ - -/*! - \brief General async event for inspecting general events - - \param[out] pSlDeviceEvent pointer to SlDeviceEvent_t - - \par - Parameters: \n - - pSlDeviceEvent->Event = SL_DEVICE_FATAL_ERROR_EVENT - - pSlDeviceEvent->EventData.deviceEvent fields: - - status: An error code indication from the device - - sender: The sender originator which is based on SlErrorSender_e enum - - - pSlDeviceEvent->Event = SL_DEVICE_ABORT_ERROR_EVENT - Indicates a severe error occured and the device stopped - - pSlDeviceEvent->EventData.deviceReport fields: - - AbortType: An idication of the event type - - AbortData: Additional info about the data error - - - \par Example for fatal error: - \code - printf(General Event Handler - ID=%d Sender=%d\n\n", - pSlDeviceEvent->EventData.deviceEvent.status, // status of the general event - pSlDeviceEvent->EventData.deviceEvent.sender); // sender type - \endcode - \par Example for abort request: - \code - printf(Abort type =%d Abort Data=%d\n\n", - pSlDeviceEvent->EventData.deviceReport.AbortType, - pSlDeviceEvent->EventData.deviceReport.AbortData); - - \endcode -*/ -#if (defined(sl_GeneralEvtHdlr)) -extern void sl_GeneralEvtHdlr(SlDeviceEvent_t *pSlDeviceEvent); -#endif - - -/*! - \brief WLAN Async event handler - - \param[out] pSlWlanEvent pointer to SlWlanEvent_t data - - \par - Parameters: - - - pSlWlanEvent->Event = SL_WLAN_CONNECT_EVENT , STA or P2P client connection indication event - - pSlWlanEvent->EventData.STAandP2PModeWlanConnected main fields: - - ssid_name - - ssid_len - - bssid - - go_peer_device_name - - go_peer_device_name_len - - - pSlWlanEvent->Event = SL_WLAN_DISCONNECT_EVENT , STA or P2P client disconnection event - - pSlWlanEvent->EventData.STAandP2PModeDisconnected main fields: - - ssid_name - - ssid_len - - reason_code - - - pSlWlanEvent->Event = SL_WLAN_STA_CONNECTED_EVENT , AP/P2P(Go) connected STA/P2P(Client) - - pSlWlanEvent->EventData.APModeStaConnected fields: - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - own_ssid_len: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_STA_DISCONNECTED_EVENT , AP/P2P(Go) disconnected STA/P2P(Client) - - pSlWlanEvent->EventData.APModestaDisconnected fields: - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - own_ssid_len: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_SMART_CONFIG_COMPLETE_EVENT - - pSlWlanEvent->EventData.smartConfigStartResponse fields: - - status - - ssid_len - - ssid - - private_token_len - - private_token - - - pSlWlanEvent->Event = SL_WLAN_SMART_CONFIG_STOP_EVENT - - pSlWlanEvent->EventData.smartConfigStopResponse fields: - - status - - - pSlWlanEvent->Event = SL_WLAN_P2P_DEV_FOUND_EVENT - - pSlWlanEvent->EventData.P2PModeDevFound fields: - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - own_ssid_len: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT - - pSlWlanEvent->EventData.P2PModeNegReqReceived fields - - go_peer_device_name - - mac - - go_peer_device_name_len - - wps_dev_password_id - - own_ssid: relevant for event sta-connected only - - - pSlWlanEvent->Event = SL_WLAN_CONNECTION_FAILED_EVENT , P2P only - - pSlWlanEvent->EventData.P2PModewlanConnectionFailure fields: - - status -*/ -#if (defined(sl_WlanEvtHdlr)) -extern void sl_WlanEvtHdlr(SlWlanEvent_t* pSlWlanEvent); -#endif - - -/*! - \brief NETAPP Async event handler - - \param[out] pSlNetApp pointer to SlNetAppEvent_t data - - \par - Parameters: - - pSlNetApp->Event = SL_NETAPP_IPV4_IPACQUIRED_EVENT, IPV4 acquired event - - pSlNetApp->EventData.ipAcquiredV4 fields: - - ip - - gateway - - dns - - - pSlNetApp->Event = SL_NETAPP_IP_LEASED_EVENT, AP or P2P go dhcp lease event - - pSlNetApp->EventData.ipLeased fields: - - ip_address - - lease_time - - mac - - - pSlNetApp->Event = SL_NETAPP_IP_RELEASED_EVENT, AP or P2P go dhcp ip release event - - pSlNetApp->EventData.ipReleased fields - - ip_address - - mac - - reason - -*/ -#if (defined(sl_NetAppEvtHdlr)) -extern void sl_NetAppEvtHdlr(SlNetAppEvent_t* pSlNetApp); -#endif - -/*! - \brief Socket Async event handler - - \param[out] pSlSockEvent pointer to SlSockEvent_t data - - \par - Parameters:\n - - pSlSockEvent->Event = SL_SOCKET_TX_FAILED_EVENT - - pSlSockEvent->SockTxFailData fields: - - sd - - status - - pSlSockEvent->Event = SL_SOCKET_ASYNC_EVENT - - pSlSockEvent->SockAsyncData fields: - - sd - - type: SSL_ACCEPT or RX_FRAGMENTATION_TOO_BIG or OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED - - val - -*/ -#if (defined(sl_SockEvtHdlr)) -extern void sl_SockEvtHdlr(SlSockEvent_t* pSlSockEvent); -#endif - -/*! - \brief HTTP server async event - - \param[out] pSlHttpServerEvent pointer to SlHttpServerEvent_t - \param[in] pSlHttpServerResponse pointer to SlHttpServerResponse_t - - \par - Parameters: \n - - - pSlHttpServerEvent->Event = SL_NETAPP_HTTPGETTOKENVALUE_EVENT - - pSlHttpServerEvent->EventData fields: - - httpTokenName - - data - - len - - pSlHttpServerResponse->ResponseData fields: - - data - - len - - - pSlHttpServerEvent->Event = SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT - - pSlHttpServerEvent->EventData.httpPostData fields: - - action - - token_name - - token_value - - pSlHttpServerResponse->ResponseData fields: - - data - - len - -*/ -#if (defined(sl_HttpServerCallback)) -extern void sl_HttpServerCallback(SlHttpServerEvent_t *pSlHttpServerEvent, SlHttpServerResponse_t *pSlHttpServerResponse); -#endif -/*! - - Close the Doxygen group. - @} - - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __SIMPLELINK_H__ */ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/socket.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/socket.h deleted file mode 100644 index 81554d4a..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/socket.h +++ /dev/null @@ -1,1573 +0,0 @@ -/* - * socket.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef __SL_SOCKET_H__ -#define __SL_SOCKET_H__ - - - - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - - \addtogroup socket - @{ - -*/ - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define SL_FD_SETSIZE SL_MAX_SOCKETS /* Number of sockets to select on - same is max sockets! */ -#define BSD_SOCKET_ID_MASK (0x0F) /* Index using the LBS 4 bits for socket id 0-7 */ -/* Define some BSD protocol constants. */ -#define SL_SOCK_STREAM (1) /* TCP Socket */ -#define SL_SOCK_DGRAM (2) /* UDP Socket */ -#define SL_SOCK_RAW (3) /* Raw socket */ -#define SL_IPPROTO_TCP (6) /* TCP Raw Socket */ -#define SL_IPPROTO_UDP (17) /* UDP Raw Socket */ -#define SL_IPPROTO_RAW (255) /* Raw Socket */ -#define SL_SEC_SOCKET (100) /* Secured Socket Layer (SSL,TLS) */ - -/* Address families. */ -#define SL_AF_INET (2) /* IPv4 socket (UDP, TCP, etc) */ -#define SL_AF_INET6 (3) /* IPv6 socket (UDP, TCP, etc) */ -#define SL_AF_INET6_EUI_48 (9) -#define SL_AF_RF (6) /* data include RF parameter, All layer by user (Wifi could be disconnected) */ -#define SL_AF_PACKET (17) -/* Protocol families, same as address families. */ -#define SL_PF_INET AF_INET -#define SL_PF_INET6 AF_INET6 -#define SL_INADDR_ANY (0) /* bind any address */ - -/* error codes */ -#define SL_SOC_ERROR (-1) /* Failure. */ -#define SL_SOC_OK ( 0) /* Success. */ -#define SL_INEXE (-8) /* socket command in execution */ -#define SL_EBADF (-9) /* Bad file number */ -#define SL_ENSOCK (-10) /* The system limit on the total number of open socket, has been reached */ -#define SL_EAGAIN (-11) /* Try again */ -#define SL_EWOULDBLOCK SL_EAGAIN -#define SL_ENOMEM (-12) /* Out of memory */ -#define SL_EACCES (-13) /* Permission denied */ -#define SL_EFAULT (-14) /* Bad address */ -#define SL_ECLOSE (-15) /* close socket operation failed to transmit all queued packets */ -#define SL_EALREADY_ENABLED (-21) /* Transceiver - Transceiver already ON. there could be only one */ -#define SL_EINVAL (-22) /* Invalid argument */ -#define SL_EAUTO_CONNECT_OR_CONNECTING (-69) /* Transceiver - During connection, connected or auto mode started */ -#define SL_CONNECTION_PENDING (-72) /* Transceiver - Device is connected, disconnect first to open transceiver */ -#define SL_EUNSUPPORTED_ROLE (-86) /* Transceiver - Trying to start when WLAN role is AP or P2P GO */ -#define SL_EDESTADDRREQ (-89) /* Destination address required */ -#define SL_EPROTOTYPE (-91) /* Protocol wrong type for socket */ -#define SL_ENOPROTOOPT (-92) /* Protocol not available */ -#define SL_EPROTONOSUPPORT (-93) /* Protocol not supported */ -#define SL_ESOCKTNOSUPPORT (-94) /* Socket type not supported */ -#define SL_EOPNOTSUPP (-95) /* Operation not supported on transport endpoint */ -#define SL_EAFNOSUPPORT (-97) /* Address family not supported by protocol */ -#define SL_EADDRINUSE (-98) /* Address already in use */ -#define SL_EADDRNOTAVAIL (-99) /* Cannot assign requested address */ -#define SL_ENETUNREACH (-101) /* Network is unreachable */ -#define SL_ENOBUFS (-105) /* No buffer space available */ -#define SL_EOBUFF SL_ENOBUFS -#define SL_EISCONN (-106) /* Transport endpoint is already connected */ -#define SL_ENOTCONN (-107) /* Transport endpoint is not connected */ -#define SL_ETIMEDOUT (-110) /* Connection timed out */ -#define SL_ECONNREFUSED (-111) /* Connection refused */ -#define SL_EALREADY (-114) /* Non blocking connect in progress, try again */ - -#define SL_ESEC_RSA_WRONG_TYPE_E (-130) /* RSA wrong block type for RSA function */ -#define SL_ESEC_RSA_BUFFER_E (-131) /* RSA buffer error, output too small or */ -#define SL_ESEC_BUFFER_E (-132) /* output buffer too small or input too large */ -#define SL_ESEC_ALGO_ID_E (-133) /* setting algo id error */ -#define SL_ESEC_PUBLIC_KEY_E (-134) /* setting public key error */ -#define SL_ESEC_DATE_E (-135) /* setting date validity error */ -#define SL_ESEC_SUBJECT_E (-136) /* setting subject name error */ -#define SL_ESEC_ISSUER_E (-137) /* setting issuer name error */ -#define SL_ESEC_CA_TRUE_E (-138) /* setting CA basic constraint true error */ -#define SL_ESEC_EXTENSIONS_E (-139) /* setting extensions error */ -#define SL_ESEC_ASN_PARSE_E (-140) /* ASN parsing error, invalid input */ -#define SL_ESEC_ASN_VERSION_E (-141) /* ASN version error, invalid number */ -#define SL_ESEC_ASN_GETINT_E (-142) /* ASN get big _i16 error, invalid data */ -#define SL_ESEC_ASN_RSA_KEY_E (-143) /* ASN key init error, invalid input */ -#define SL_ESEC_ASN_OBJECT_ID_E (-144) /* ASN object id error, invalid id */ -#define SL_ESEC_ASN_TAG_NULL_E (-145) /* ASN tag error, not null */ -#define SL_ESEC_ASN_EXPECT_0_E (-146) /* ASN expect error, not zero */ -#define SL_ESEC_ASN_BITSTR_E (-147) /* ASN bit string error, wrong id */ -#define SL_ESEC_ASN_UNKNOWN_OID_E (-148) /* ASN oid error, unknown sum id */ -#define SL_ESEC_ASN_DATE_SZ_E (-149) /* ASN date error, bad size */ -#define SL_ESEC_ASN_BEFORE_DATE_E (-150) /* ASN date error, current date before */ -#define SL_ESEC_ASN_AFTER_DATE_E (-151) /* ASN date error, current date after */ -#define SL_ESEC_ASN_SIG_OID_E (-152) /* ASN signature error, mismatched oid */ -#define SL_ESEC_ASN_TIME_E (-153) /* ASN time error, unknown time type */ -#define SL_ESEC_ASN_INPUT_E (-154) /* ASN input error, not enough data */ -#define SL_ESEC_ASN_SIG_CONFIRM_E (-155) /* ASN sig error, confirm failure */ -#define SL_ESEC_ASN_SIG_HASH_E (-156) /* ASN sig error, unsupported hash type */ -#define SL_ESEC_ASN_SIG_KEY_E (-157) /* ASN sig error, unsupported key type */ -#define SL_ESEC_ASN_DH_KEY_E (-158) /* ASN key init error, invalid input */ -#define SL_ESEC_ASN_NTRU_KEY_E (-159) /* ASN ntru key decode error, invalid input */ -#define SL_ESEC_ECC_BAD_ARG_E (-170) /* ECC input argument of wrong type */ -#define SL_ESEC_ASN_ECC_KEY_E (-171) /* ASN ECC bad input */ -#define SL_ESEC_ECC_CURVE_OID_E (-172) /* Unsupported ECC OID curve type */ -#define SL_ESEC_BAD_FUNC_ARG (-173) /* Bad function argument provided */ -#define SL_ESEC_NOT_COMPILED_IN (-174) /* Feature not compiled in */ -#define SL_ESEC_UNICODE_SIZE_E (-175) /* Unicode password too big */ -#define SL_ESEC_NO_PASSWORD (-176) /* no password provided by user */ -#define SL_ESEC_ALT_NAME_E (-177) /* alt name size problem, too big */ -#define SL_ESEC_AES_GCM_AUTH_E (-180) /* AES-GCM Authentication check failure */ -#define SL_ESEC_AES_CCM_AUTH_E (-181) /* AES-CCM Authentication check failure */ -#define SL_SOCKET_ERROR_E (-208) /* Error state on socket */ - -#define SL_ESEC_MEMORY_ERROR (-203) /* out of memory */ -#define SL_ESEC_VERIFY_FINISHED_ERROR (-204) /* verify problem on finished */ -#define SL_ESEC_VERIFY_MAC_ERROR (-205) /* verify mac problem */ -#define SL_ESEC_UNKNOWN_HANDSHAKE_TYPE (-207) /* weird handshake type */ -#define SL_ESEC_SOCKET_ERROR_E (-208) /* error state on socket */ -#define SL_ESEC_SOCKET_NODATA (-209) /* expected data, not there */ -#define SL_ESEC_INCOMPLETE_DATA (-210) /* don't have enough data to complete task */ -#define SL_ESEC_UNKNOWN_RECORD_TYPE (-211) /* unknown type in record hdr */ -#define SL_ESEC_FATAL_ERROR (-213) /* recvd alert fatal error */ -#define SL_ESEC_ENCRYPT_ERROR (-214) /* error during encryption */ -#define SL_ESEC_NO_PEER_KEY (-216) /* need peer's key */ -#define SL_ESEC_NO_PRIVATE_KEY (-217) /* need the private key */ -#define SL_ESEC_RSA_PRIVATE_ERROR (-218) /* error during rsa priv op */ -#define SL_ESEC_NO_DH_PARAMS (-219) /* server missing DH params */ -#define SL_ESEC_BUILD_MSG_ERROR (-220) /* build message failure */ -#define SL_ESEC_BAD_HELLO (-221) /* client hello malformed */ -#define SL_ESEC_DOMAIN_NAME_MISMATCH (-222) /* peer subject name mismatch */ -#define SL_ESEC_WANT_READ (-223) /* want read, call again */ -#define SL_ESEC_NOT_READY_ERROR (-224) /* handshake layer not ready */ -#define SL_ESEC_PMS_VERSION_ERROR (-225) /* pre m secret version error */ -#define SL_ESEC_VERSION_ERROR (-226) /* record layer version error */ -#define SL_ESEC_WANT_WRITE (-227) /* want write, call again */ -#define SL_ESEC_BUFFER_ERROR (-228) /* malformed buffer input */ -#define SL_ESEC_VERIFY_CERT_ERROR (-229) /* verify cert error */ -#define SL_ESEC_VERIFY_SIGN_ERROR (-230) /* verify sign error */ - -#define SL_ESEC_LENGTH_ERROR (-241) /* record layer length error */ -#define SL_ESEC_PEER_KEY_ERROR (-242) /* can't decode peer key */ -#define SL_ESEC_ZERO_RETURN (-243) /* peer sent close notify */ -#define SL_ESEC_SIDE_ERROR (-244) /* wrong client/server type */ -#define SL_ESEC_NO_PEER_CERT (-245) /* peer didn't send key */ -#define SL_ESEC_ECC_CURVETYPE_ERROR (-250) /* Bad ECC Curve Type */ -#define SL_ESEC_ECC_CURVE_ERROR (-251) /* Bad ECC Curve */ -#define SL_ESEC_ECC_PEERKEY_ERROR (-252) /* Bad Peer ECC Key */ -#define SL_ESEC_ECC_MAKEKEY_ERROR (-253) /* Bad Make ECC Key */ -#define SL_ESEC_ECC_EXPORT_ERROR (-254) /* Bad ECC Export Key */ -#define SL_ESEC_ECC_SHARED_ERROR (-255) /* Bad ECC Shared Secret */ -#define SL_ESEC_NOT_CA_ERROR (-257) /* Not a CA cert error */ -#define SL_ESEC_BAD_PATH_ERROR (-258) /* Bad path for opendir */ -#define SL_ESEC_BAD_CERT_MANAGER_ERROR (-259) /* Bad Cert Manager */ -#define SL_ESEC_MAX_CHAIN_ERROR (-268) /* max chain depth exceeded */ -#define SL_ESEC_SUITES_ERROR (-271) /* suites pointer error */ -#define SL_ESEC_SSL_NO_PEM_HEADER (-272) /* no PEM header found */ -#define SL_ESEC_OUT_OF_ORDER_E (-273) /* out of order message */ -#define SL_ESEC_SANITY_CIPHER_E (-275) /* sanity check on cipher error */ -#define SL_ESEC_GEN_COOKIE_E (-277) /* Generate Cookie Error */ -#define SL_ESEC_NO_PEER_VERIFY (-278) /* Need peer cert verify Error */ -#define SL_ESEC_UNKNOWN_SNI_HOST_NAME_E (-281) /* Unrecognized host name Error */ -/* begin negotiation parameter errors */ -#define SL_ESEC_UNSUPPORTED_SUITE (-290) /* unsupported cipher suite */ -#define SL_ESEC_MATCH_SUITE_ERROR (-291 ) /* can't match cipher suite */ - -/* ssl tls security start with -300 offset */ -#define SL_ESEC_CLOSE_NOTIFY (-300) /* ssl/tls alerts */ -#define SL_ESEC_UNEXPECTED_MESSAGE (-310) /* ssl/tls alerts */ -#define SL_ESEC_BAD_RECORD_MAC (-320) /* ssl/tls alerts */ -#define SL_ESEC_DECRYPTION_FAILED (-321) /* ssl/tls alerts */ -#define SL_ESEC_RECORD_OVERFLOW (-322) /* ssl/tls alerts */ -#define SL_ESEC_DECOMPRESSION_FAILURE (-330) /* ssl/tls alerts */ -#define SL_ESEC_HANDSHAKE_FAILURE (-340) /* ssl/tls alerts */ -#define SL_ESEC_NO_CERTIFICATE (-341) /* ssl/tls alerts */ -#define SL_ESEC_BAD_CERTIFICATE (-342) /* ssl/tls alerts */ -#define SL_ESEC_UNSUPPORTED_CERTIFICATE (-343) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_REVOKED (-344) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_EXPIRED (-345) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_UNKNOWN (-346) /* ssl/tls alerts */ -#define SL_ESEC_ILLEGAL_PARAMETER (-347) /* ssl/tls alerts */ -#define SL_ESEC_UNKNOWN_CA (-348) /* ssl/tls alerts */ -#define SL_ESEC_ACCESS_DENIED (-349) /* ssl/tls alerts */ -#define SL_ESEC_DECODE_ERROR (-350) /* ssl/tls alerts */ -#define SL_ESEC_DECRYPT_ERROR (-351) /* ssl/tls alerts */ -#define SL_ESEC_EXPORT_RESTRICTION (-360) /* ssl/tls alerts */ -#define SL_ESEC_PROTOCOL_VERSION (-370) /* ssl/tls alerts */ -#define SL_ESEC_INSUFFICIENT_SECURITY (-371) /* ssl/tls alerts */ -#define SL_ESEC_INTERNAL_ERROR (-380) /* ssl/tls alerts */ -#define SL_ESEC_USER_CANCELLED (-390) /* ssl/tls alerts */ -#define SL_ESEC_NO_RENEGOTIATION (-400) /* ssl/tls alerts */ -#define SL_ESEC_UNSUPPORTED_EXTENSION (-410) /* ssl/tls alerts */ -#define SL_ESEC_CERTIFICATE_UNOBTAINABLE (-411) /* ssl/tls alerts */ -#define SL_ESEC_UNRECOGNIZED_NAME (-412) /* ssl/tls alerts */ -#define SL_ESEC_BAD_CERTIFICATE_STATUS_RESPONSE (-413) /* ssl/tls alerts */ -#define SL_ESEC_BAD_CERTIFICATE_HASH_VALUE (-414) /* ssl/tls alerts */ -/* propierty secure */ -#define SL_ESECGENERAL (-450) /* error secure level general error */ -#define SL_ESECDECRYPT (-451) /* error secure level, decrypt recv packet fail */ -#define SL_ESECCLOSED (-452) /* secure layrer is closed by other size , tcp is still connected */ -#define SL_ESECSNOVERIFY (-453) /* Connected without server verification */ -#define SL_ESECNOCAFILE (-454) /* error secure level CA file not found*/ -#define SL_ESECMEMORY (-455) /* error secure level No memory space available */ -#define SL_ESECBADCAFILE (-456) /* error secure level bad CA file */ -#define SL_ESECBADCERTFILE (-457) /* error secure level bad Certificate file */ -#define SL_ESECBADPRIVATEFILE (-458) /* error secure level bad private file */ -#define SL_ESECBADDHFILE (-459) /* error secure level bad DH file */ -#define SL_ESECT00MANYSSLOPENED (-460) /* MAX SSL Sockets are opened */ -#define SL_ESECDATEERROR (-461) /* connected with certificate date verification error */ -#define SL_ESECHANDSHAKETIMEDOUT (-462) /* connection timed out due to handshake time */ - -/* end error codes */ - -/* Max payload size by protocol */ -#define SL_SOCKET_PAYLOAD_TYPE_MASK (0xF0) /*4 bits type, 4 bits sockets id */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 (0x00) /* 1472 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 (0x10) /* 1460 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 (0x20) /* 1452 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 (0x30) /* 1440 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE (0x40) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE (0x50) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE (0x60) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE (0x70) /* */ -#define SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER (0x80) /* 1536 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET (0x90) /* 1536 bytes */ -#define SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 (0xa0) -#define SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 (SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 ) - - - -#define SL_SOL_SOCKET (1) /* Define the socket option category. */ -#define SL_IPPROTO_IP (2) /* Define the IP option category. */ -#define SL_SOL_PHY_OPT (3) /* Define the PHY option category. */ - -#define SL_SO_RCVBUF (8) /* Setting TCP receive buffer size */ -#define SL_SO_KEEPALIVE (9) /* Connections are kept alive with periodic messages */ -#define SL_SO_RCVTIMEO (20) /* Enable receive timeout */ -#define SL_SO_NONBLOCKING (24) /* Enable . disable nonblocking mode */ -#define SL_SO_SECMETHOD (25) /* security metohd */ -#define SL_SO_SECURE_MASK (26) /* security mask */ -#define SL_SO_SECURE_FILES (27) /* security files */ -#define SL_SO_CHANGE_CHANNEL (28) /* This option is available only when transceiver started */ -#define SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME (30) /* This option used to configue secure file */ -#define SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME (31) /* This option used to configue secure file */ -#define SL_SO_SECURE_FILES_CA_FILE_NAME (32) /* This option used to configue secure file */ -#define SL_SO_SECURE_FILES_DH_KEY_FILE_NAME (33) /* This option used to configue secure file */ - -#define SL_IP_MULTICAST_IF (60) /* Specify outgoing multicast interface */ -#define SL_IP_MULTICAST_TTL (61) /* Specify the TTL value to use for outgoing multicast packet. */ -#define SL_IP_ADD_MEMBERSHIP (65) /* Join IPv4 multicast membership */ -#define SL_IP_DROP_MEMBERSHIP (66) /* Leave IPv4 multicast membership */ -#define SL_IP_HDRINCL (67) /* Raw socket IPv4 header included. */ -#define SL_IP_RAW_RX_NO_HEADER (68) /* Proprietary socket option that does not includeIPv4/IPv6 header (and extension headers) on received raw sockets*/ -#define SL_IP_RAW_IPV6_HDRINCL (69) /* Transmitted buffer over IPv6 socket contains IPv6 header. */ - -#define SL_SO_PHY_RATE (100) /* WLAN Transmit rate */ -#define SL_SO_PHY_TX_POWER (101) /* TX Power level */ -#define SL_SO_PHY_NUM_FRAMES_TO_TX (102) /* Number of frames to transmit */ -#define SL_SO_PHY_PREAMBLE (103) /* Preamble for transmission */ - -#define SL_SO_SEC_METHOD_SSLV3 (0) /* security metohd SSL v3*/ -#define SL_SO_SEC_METHOD_TLSV1 (1) /* security metohd TLS v1*/ -#define SL_SO_SEC_METHOD_TLSV1_1 (2) /* security metohd TLS v1_1*/ -#define SL_SO_SEC_METHOD_TLSV1_2 (3) /* security metohd TLS v1_2*/ -#define SL_SO_SEC_METHOD_SSLv3_TLSV1_2 (4) /* use highest possible version from SSLv3 - TLS 1.2*/ -#define SL_SO_SEC_METHOD_DLSV1 (5) /* security metohd DTL v1 */ - -#define SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA (1 << 0) -#define SL_SEC_MASK_SSL_RSA_WITH_RC4_128_MD5 (1 << 1) -#define SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA (1 << 2) -#define SL_SEC_MASK_TLS_DHE_RSA_WITH_AES_256_CBC_SHA (1 << 3) -#define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (1 << 4) -#define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_RC4_128_SHA (1 << 5) -#define SL_SEC_MASK_TLS_RSA_WITH_AES_128_CBC_SHA256 (1 << 6) -#define SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA256 (1 << 7) -#define SL_SEC_MASK_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (1 << 8) -#define SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (1 << 9) - - -#define SL_SEC_MASK_SECURE_DEFAULT ((SL_SEC_MASK_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 << 1) - 1) - -#define SL_MSG_DONTWAIT (0x00000008) /* Nonblocking IO */ - -/* AP DHCP Server - IP Release reason code */ -#define SL_IP_LEASE_PEER_RELEASE (0) -#define SL_IP_LEASE_PEER_DECLINE (1) -#define SL_IP_LEASE_EXPIRED (2) - -/* possible types when receiving SL_SOCKET_ASYNC_EVENT*/ -#define SSL_ACCEPT (1) /* accept failed due to ssl issue ( tcp pass) */ -#define RX_FRAGMENTATION_TOO_BIG (2) /* connection less mode, rx packet fragmentation > 16K, packet is being released */ -#define OTHER_SIDE_CLOSE_SSL_DATA_NOT_ENCRYPTED (3) /* remote side down from secure to unsecure */ - - - -#ifdef SL_INC_STD_BSD_API_NAMING - -#define FD_SETSIZE SL_FD_SETSIZE - -#define SOCK_STREAM SL_SOCK_STREAM -#define SOCK_DGRAM SL_SOCK_DGRAM -#define SOCK_RAW SL_SOCK_RAW -#define IPPROTO_TCP SL_IPPROTO_TCP -#define IPPROTO_UDP SL_IPPROTO_UDP -#define IPPROTO_RAW SL_IPPROTO_RAW - -#define AF_INET SL_AF_INET -#define AF_INET6 SL_AF_INET6 -#define AF_INET6_EUI_48 SL_AF_INET6_EUI_48 -#define AF_RF SL_AF_RF -#define AF_PACKET SL_AF_PACKET - -#define PF_INET SL_PF_INET -#define PF_INET6 SL_PF_INET6 - -#define INADDR_ANY SL_INADDR_ANY -#define ERROR SL_SOC_ERROR -#define INEXE SL_INEXE -#define EBADF SL_EBADF -#define ENSOCK SL_ENSOCK -#define EAGAIN SL_EAGAIN -#define EWOULDBLOCK SL_EWOULDBLOCK -#define ENOMEM SL_ENOMEM -#define EACCES SL_EACCES -#define EFAULT SL_EFAULT -#define EINVAL SL_EINVAL -#define EDESTADDRREQ SL_EDESTADDRREQ -#define EPROTOTYPE SL_EPROTOTYPE -#define ENOPROTOOPT SL_ENOPROTOOPT -#define EPROTONOSUPPORT SL_EPROTONOSUPPORT -#define ESOCKTNOSUPPORT SL_ESOCKTNOSUPPORT -#define EOPNOTSUPP SL_EOPNOTSUPP -#define EAFNOSUPPORT SL_EAFNOSUPPORT -#define EADDRINUSE SL_EADDRINUSE -#define EADDRNOTAVAIL SL_EADDRNOTAVAIL -#define ENETUNREACH SL_ENETUNREACH -#define ENOBUFS SL_ENOBUFS -#define EOBUFF SL_EOBUFF -#define EISCONN SL_EISCONN -#define ENOTCONN SL_ENOTCONN -#define ETIMEDOUT SL_ETIMEDOUT -#define ECONNREFUSED SL_ECONNREFUSED - -#define SOL_SOCKET SL_SOL_SOCKET -#define IPPROTO_IP SL_IPPROTO_IP -#define SO_KEEPALIVE SL_SO_KEEPALIVE - -#define SO_RCVTIMEO SL_SO_RCVTIMEO -#define SO_NONBLOCKING SL_SO_NONBLOCKING - -#define IP_MULTICAST_IF SL_IP_MULTICAST_IF -#define IP_MULTICAST_TTL SL_IP_MULTICAST_TTL -#define IP_ADD_MEMBERSHIP SL_IP_ADD_MEMBERSHIP -#define IP_DROP_MEMBERSHIP SL_IP_DROP_MEMBERSHIP - -#define socklen_t SlSocklen_t -#define timeval SlTimeval_t -#define sockaddr SlSockAddr_t -#define in6_addr SlIn6Addr_t -#define sockaddr_in6 SlSockAddrIn6_t -#define in_addr SlInAddr_t -#define sockaddr_in SlSockAddrIn_t - -#define MSG_DONTWAIT SL_MSG_DONTWAIT - -#define FD_SET SL_FD_SET -#define FD_CLR SL_FD_CLR -#define FD_ISSET SL_FD_ISSET -#define FD_ZERO SL_FD_ZERO -#define fd_set SlFdSet_t - -#define socket sl_Socket -#define close sl_Close -#define accept sl_Accept -#define bind sl_Bind -#define listen sl_Listen -#define connect sl_Connect -#define select sl_Select -#define setsockopt sl_SetSockOpt -#define getsockopt sl_GetSockOpt -#define recv sl_Recv -#define recvfrom sl_RecvFrom -#define write sl_Write -#define send sl_Send -#define sendto sl_SendTo -#define gethostbyname sl_NetAppDnsGetHostByName -#define htonl sl_Htonl -#define ntohl sl_Ntohl -#define htons sl_Htons -#define ntohs sl_Ntohs -#endif - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -/* Internet address */ -typedef struct SlInAddr_t -{ -#ifndef s_addr - _u32 s_addr; /* Internet address 32 bits */ -#else - union S_un { - struct { _u8 s_b1,s_b2,s_b3,s_b4; } S_un_b; - struct { _u8 s_w1,s_w2; } S_un_w; - _u32 S_addr; - } S_un; -#endif -}SlInAddr_t; - - -/* sockopt */ -typedef struct -{ - _u32 KeepaliveEnabled; /* 0 = disabled;1 = enabled; default = 1*/ -}SlSockKeepalive_t; - -typedef struct -{ - _u32 ReuseaddrEnabled; /* 0 = disabled; 1 = enabled; default = 1*/ -}SlSockReuseaddr_t; - -typedef struct -{ - _u32 Winsize; /* receive window size for tcp sockets */ -}SlSockWinsize_t; - -typedef struct -{ - _u32 NonblockingEnabled;/* 0 = disabled;1 = enabled;default = 1*/ -}SlSockNonblocking_t; - - -typedef struct -{ - _u8 sd; - _u8 type; - _i16 val; - _u8* pExtraInfo; -} SlSocketAsyncEvent_t; - -typedef struct -{ - _i16 status; - _u8 sd; - _u8 padding; -} SlSockTxFailEventData_t; - - -typedef union -{ - SlSockTxFailEventData_t SockTxFailData; - SlSocketAsyncEvent_t SockAsyncData; -} SlSockEventData_u; - - -typedef struct -{ - _u32 Event; - SlSockEventData_u socketAsyncEvent; -} SlSockEvent_t; - - - - - - -typedef struct -{ - _u32 secureMask; -} SlSockSecureMask; - -typedef struct -{ - _u8 secureMethod; -} SlSockSecureMethod; - -typedef enum -{ - SL_BSD_SECURED_PRIVATE_KEY_IDX = 0, - SL_BSD_SECURED_CERTIFICATE_IDX, - SL_BSD_SECURED_CA_IDX, - SL_BSD_SECURED_DH_IDX -}slBsd_secureSocketFilesIndex_e; - -typedef struct -{ - SlInAddr_t imr_multiaddr; /* The IPv4 multicast address to join */ - SlInAddr_t imr_interface; /* The interface to use for this group */ -} SlSockIpMreq; - - -/* sockopt */ -typedef _u32 SlTime_t; -typedef _u32 SlSuseconds_t; - -typedef struct SlTimeval_t -{ - SlTime_t tv_sec; /* Seconds */ - SlSuseconds_t tv_usec; /* Microseconds */ -}SlTimeval_t; - -typedef _u16 SlSocklen_t; - -/* IpV4 socket address */ -typedef struct SlSockAddr_t -{ - _u16 sa_family; /* Address family (e.g. , AF_INET) */ - _u8 sa_data[14]; /* Protocol- specific address information*/ -}SlSockAddr_t; - - -/* IpV6 or Ipv6 EUI64 */ -typedef struct SlIn6Addr_t -{ - union - { - _u8 _S6_u8[16]; - _u32 _S6_u32[4]; - } _S6_un; -}SlIn6Addr_t; - -typedef struct SlSockAddrIn6_t -{ - _u16 sin6_family; /* AF_INET6 || AF_INET6_EUI_48*/ - _u16 sin6_port; /* Transport layer port. */ - _u32 sin6_flowinfo; /* IPv6 flow information. */ - SlIn6Addr_t sin6_addr; /* IPv6 address. */ - _u32 sin6_scope_id; /* set of interfaces for a scope. */ -}SlSockAddrIn6_t; - -/* Socket address, Internet style. */ - -typedef struct SlSockAddrIn_t -{ - _u16 sin_family; /* Internet Protocol (AF_INET). */ - _u16 sin_port; /* Address port (16 bits). */ - SlInAddr_t sin_addr; /* Internet address (32 bits). */ - _i8 sin_zero[8]; /* Not used. */ -}SlSockAddrIn_t; - -typedef struct -{ - _u32 ip; - _u32 gateway; - _u32 dns; -}SlIpV4AcquiredAsync_t; - -typedef struct -{ - _u32 type; - _u32 ip[4]; - _u32 gateway[4]; - _u32 dns[4]; -}SlIpV6AcquiredAsync_t; - -typedef struct -{ - _u32 ip_address; - _u32 lease_time; - _u8 mac[6]; - _u16 padding; -}SlIpLeasedAsync_t; - -typedef struct -{ - _u32 ip_address; - _u8 mac[6]; - _u16 reason; -}SlIpReleasedAsync_t; - - -typedef union -{ - SlIpV4AcquiredAsync_t ipAcquiredV4; /*SL_NETAPP_IPV4_IPACQUIRED_EVENT*/ - SlIpV6AcquiredAsync_t ipAcquiredV6; /*SL_NETAPP_IPV6_IPACQUIRED_EVENT*/ - _u32 sd; /*SL_SOCKET_TX_FAILED_EVENT*/ - SlIpLeasedAsync_t ipLeased; /* SL_NETAPP_IP_LEASED_EVENT */ - SlIpReleasedAsync_t ipReleased; /* SL_NETAPP_IP_RELEASED_EVENT */ -} SlNetAppEventData_u; - -typedef struct -{ - _u32 Event; - SlNetAppEventData_u EventData; -}SlNetAppEvent_t; - - -typedef struct sock_secureFiles -{ - _u8 secureFiles[4]; -}SlSockSecureFiles_t; - - -typedef struct SlFdSet_t /* The select socket array manager */ -{ - _u32 fd_array[(SL_FD_SETSIZE + 31)/32]; /* Bit map of SOCKET Descriptors */ -} SlFdSet_t; - -typedef struct -{ - _u8 rate; /* Recevied Rate */ - _u8 channel; /* The received channel*/ - _i8 rssi; /* The computed RSSI value in db of current frame */ - _u8 padding; /* pad to align to 32 bits */ - _u32 timestamp; /* Timestamp in microseconds, */ -}SlTransceiverRxOverHead_t; - - - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - -/*! - - \brief create an endpoint for communication - - The socket function creates a new socket of a certain socket type, identified - by an integer number, and allocates system resources to it. - This function is called by the application layer to obtain a socket handle. - - \param[in] domain specifies the protocol family of the created socket. - For example: - AF_INET for network protocol IPv4 - AF_RF for starting transceiver mode. Notes: - - sending and receiving any packet overriding 802.11 header - - for optimized power consumption the socket will be started in TX - only mode until receive command is activated - AF_INET6 for IPv6 - - - \param[in] type specifies the communication semantic, one of: - SOCK_STREAM (reliable stream-oriented service or Stream Sockets) - SOCK_DGRAM (datagram service or Datagram Sockets) - SOCK_RAW (raw protocols atop the network layer) - when used with AF_RF: - SOCK_DGRAM - L2 socket - SOCK_RAW - L1 socket - bypass WLAN CCA (Clear Channel Assessment) - - \param[in] protocol specifies a particular transport to be used with - the socket. - The most common are IPPROTO_TCP, IPPROTO_SCTP, IPPROTO_UDP, - IPPROTO_DCCP. - The value 0 may be used to select a default - protocol from the selected domain and type - - - \return On success, socket handle that is used for consequent socket operations. - A successful return code should be a positive number (int16) - On error, a negative (int16) value will be returned specifying the error code. - SL_EAFNOSUPPORT - illegal domain parameter - SL_EPROTOTYPE - illegal type parameter - SL_EACCES - permission denied - SL_ENSOCK - exceeded maximal number of socket - SL_ENOMEM - memory allocation error - SL_EINVAL - error in socket configuration - SL_EPROTONOSUPPORT - illegal protocol parameter - SL_EOPNOTSUPP - illegal combination of protocol and type parameters - - - \sa sl_Close - \note belongs to \ref basic_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Socket) -_i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol); -#endif - -/*! - \brief gracefully close socket - - This function causes the system to release resources allocated to a socket. \n - In case of TCP, the connection is terminated. - - \param[in] sd socket handle (received in sl_Socket) - - \return On success, zero is returned. - On error, a negative number is returned. - - \sa sl_Socket - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Close) -_i16 sl_Close(_i16 sd); -#endif - -/*! - \brief Accept a connection on a socket - - This function is used with connection-based socket types (SOCK_STREAM). - It extracts the first connection request on the queue of pending - connections, creates a new connected socket, and returns a new file - descriptor referring to that socket. - The newly created socket is not in the listening state. The - original socket sd is unaffected by this call. - The argument sd is a socket that has been created with - sl_Socket(), bound to a local address with sl_Bind(), and is - listening for connections after a sl_Listen(). The argument \b - \e addr is a pointer to a sockaddr structure. This structure - is filled in with the address of the peer socket, as known to - the communications layer. The exact format of the address - returned addr is determined by the socket's address family. - The \b \e addrlen argument is a value-result argument: it - should initially contain the size of the structure pointed to - by addr, on return it will contain the actual length (in - bytes) of the address returned. - - \param[in] sd socket descriptor (handle) - \param[out] addr the argument addr is a pointer - to a sockaddr structure. This - structure is filled in with the - address of the peer socket, as - known to the communications - layer. The exact format of the - address returned addr is - determined by the socket's - address\n - sockaddr:\n - code for the - address format. On this version - only AF_INET is supported.\n - - socket address, the length - depends on the code format - \param[out] addrlen the addrlen argument is a value-result - argument: it should initially contain the - size of the structure pointed to by addr - - \return On success, a socket handle. - On a non-blocking accept a possible negative value is SL_EAGAIN. - On failure, negative value. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Socket sl_Bind sl_Listen - \note belongs to \ref server_side - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Accept) -_i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen); -#endif - -/*! - \brief assign a name to a socket - - This function gives the socket the local address addr. - addr is addrlen bytes long. Traditionally, this is called - When a socket is created with socket, it exists in a name - space (address family) but has no name assigned. - It is necessary to assign a local address before a SOCK_STREAM - socket may receive connections. - - \param[in] sd socket descriptor (handle) - \param[in] addr specifies the destination - addrs\n sockaddr:\n - code for - the address format. On this - version only AF_INET is - supported.\n - socket address, - the length depends on the code - format - \param[in] addrlen contains the size of the structure pointed to by addr - - \return On success, zero is returned. On error, a negative error code is returned. - - \sa sl_Socket sl_Accept sl_Listen - \note belongs to \ref basic_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Bind) -_i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen); -#endif - -/*! - \brief listen for connections on a socket - - The willingness to accept incoming connections and a queue - limit for incoming connections are specified with listen(), - and then the connections are accepted with accept. - The listen() call applies only to sockets of type SOCK_STREAM - The backlog parameter defines the maximum length the queue of - pending connections may grow to. - - \param[in] sd socket descriptor (handle) - \param[in] backlog specifies the listen queue depth. - - - \return On success, zero is returned. On error, a negative error code is returned. - - \sa sl_Socket sl_Accept sl_Bind - \note belongs to \ref server_side - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Listen) -_i16 sl_Listen(_i16 sd, _i16 backlog); -#endif - -/*! - \brief Initiate a connection on a socket - - Function connects the socket referred to by the socket - descriptor sd, to the address specified by addr. The addrlen - argument specifies the size of addr. The format of the - address in addr is determined by the address space of the - socket. If it is of type SOCK_DGRAM, this call specifies the - peer with which the socket is to be associated; this address - is that to which datagrams are to be sent, and the only - address from which datagrams are to be received. If the - socket is of type SOCK_STREAM, this call attempts to make a - connection to another socket. The other socket is specified - by address, which is an address in the communications space - of the socket. - - - \param[in] sd socket descriptor (handle) - \param[in] addr specifies the destination addr\n - sockaddr:\n - code for the - address format. On this version - only AF_INET is supported.\n - - socket address, the length - depends on the code format - - \param[in] addrlen contains the size of the structure pointed - to by addr - - \return On success, a socket handle. - On a non-blocking connect a possible negative value is SL_EALREADY. - On failure, negative value. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Socket - \note belongs to \ref client_side - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Connect) -_i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen); -#endif - -/*! - \brief Monitor socket activity - - Select allow a program to monitor multiple file descriptors, - waiting until one or more of the file descriptors become - "ready" for some class of I/O operation - - - \param[in] nfds the highest-numbered file descriptor in any of the - three sets, plus 1. - \param[out] readsds socket descriptors list for read monitoring and accept monitoring - \param[out] writesds socket descriptors list for connect monitoring only, write monitoring is not supported, non blocking connect is supported - \param[out] exceptsds socket descriptors list for exception monitoring, not supported. - \param[in] timeout is an upper bound on the amount of time elapsed - before select() returns. Null or above 0xffff seconds means - infinity timeout. The minimum timeout is 10 milliseconds, - less than 10 milliseconds will be set automatically to 10 milliseconds. - Max microseconds supported is 0xfffc00. - - \return On success, select() returns the number of - file descriptors contained in the three returned - descriptor sets (that is, the total number of bits that - are set in readfds, writefds, exceptfds) which may be - zero if the timeout expires before anything interesting - happens. On error, a negative value is returned. - readsds - return the sockets on which Read request will - return without delay with valid data. - writesds - return the sockets on which Write request - will return without delay. - exceptsds - return the sockets closed recently. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Socket - \note If the timeout value set to less than 5ms it will automatically set - to 5ms to prevent overload of the system - belongs to \ref basic_api - - Only one sl_Select can be handled at a time. - Calling this API while the same command is called from another thread, may result - in one of the two scenarios: - 1. The command will wait (internal) until the previous command finish, and then be executed. - 2. There are not enough resources and SL_POOL_IS_EMPTY error will return. - In this case, MAX_CONCURRENT_ACTIONS can be increased (result in memory increase) or try - again later to issue the command. - - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Select) -_i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout); - - -/*! - \brief Select's SlFdSet_t SET function - - Sets current socket descriptor on SlFdSet_t container -*/ -void SL_FD_SET(_i16 fd, SlFdSet_t *fdset); - -/*! - \brief Select's SlFdSet_t CLR function - - Clears current socket descriptor on SlFdSet_t container -*/ -void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset); - - -/*! - \brief Select's SlFdSet_t ISSET function - - Checks if current socket descriptor is set (TRUE/FALSE) - - \return Returns TRUE if set, FALSE if unset - -*/ -_i16 SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset); - -/*! - \brief Select's SlFdSet_t ZERO function - - Clears all socket descriptors from SlFdSet_t -*/ -void SL_FD_ZERO(SlFdSet_t *fdset); - - - -#endif - -/*! - \brief set socket options - - This function manipulate the options associated with a socket. - Options may exist at multiple protocol levels; they are always - present at the uppermost socket level. - - When manipulating socket options the level at which the option resides - and the name of the option must be specified. To manipulate options at - the socket level, level is specified as SOL_SOCKET. To manipulate - options at any other level the protocol number of the appropriate proto- - col controlling the option is supplied. For example, to indicate that an - option is to be interpreted by the TCP protocol, level should be set to - the protocol number of TCP; - - The parameters optval and optlen are used to access optval - - ues for setsockopt(). For getsockopt() they identify a - buffer in which the value for the requested option(s) are to - be returned. For getsockopt(), optlen is a value-result - parameter, initially containing the size of the buffer - pointed to by option_value, and modified on return to - indicate the actual size of the value returned. If no option - value is to be supplied or returned, option_value may be - NULL. - - \param[in] sd socket handle - \param[in] level defines the protocol level for this option - - SL_SOL_SOCKET Socket level configurations (L4, transport layer) - - SL_IPPROTO_IP IP level configurations (L3, network layer) - - SL_SOL_PHY_OPT Link level configurations (L2, link layer) - \param[in] optname defines the option name to interrogate - - SL_SOL_SOCKET - - SL_SO_KEEPALIVE \n - Enable/Disable periodic keep alive. - Keeps TCP connections active by enabling the periodic transmission of messages \n - Timeout is 5 minutes.\n - Default: Enabled \n - This options takes SlSockKeepalive_t struct as parameter - - SL_SO_RCVTIMEO \n - Sets the timeout value that specifies the maximum amount of time an input function waits until it completes. \n - Default: No timeout \n - This options takes SlTimeval_t struct as parameter - - SL_SO_RCVBUF \n - Sets tcp max recv window size. \n - This options takes SlSockWinsize_t struct as parameter - - SL_SO_NONBLOCKING \n - Sets socket to non-blocking operation Impacts: connect, accept, send, sendto, recv and recvfrom. \n - Default: Blocking. - This options takes SlSockNonblocking_t struct as parameter - - SL_SO_SECMETHOD \n - Sets method to tcp secured socket (SL_SEC_SOCKET) \n - Default: SL_SO_SEC_METHOD_SSLv3_TLSV1_2 \n - This options takes SlSockSecureMethod struct as parameter - - SL_SO_SEC_MASK \n - Sets specific cipher to tcp secured socket (SL_SEC_SOCKET) \n - Default: "Best" cipher suitable to method \n - This options takes SlSockSecureMask struct as parameter - - SL_SO_SECURE_FILES_CA_FILE_NAME \n - Map secured socket to CA file by name \n - This options takes _u8 buffer as parameter - - SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME \n - Map secured socket to private key by name \n - This options takes _u8 buffer as parameter - - SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME \n - Map secured socket to certificate file by name \n - This options takes _u8 buffer as parameter - - SL_SO_SECURE_FILES_DH_KEY_FILE_NAME \n - Map secured socket to Diffie Hellman file by name \n - This options takes _u8 buffer as parameter - - SL_SO_CHANGE_CHANNEL \n - Sets channel in transceiver mode. - This options takes _u32 as channel number parameter - - SL_IPPROTO_IP - - SL_IP_MULTICAST_TTL \n - Set the time-to-live value of outgoing multicast packets for this socket. \n - This options takes _u8 as parameter - - SL_IP_ADD_MEMBERSHIP \n - UDP socket, Join a multicast group. \n - This options takes SlSockIpMreq struct as parameter - - SL_IP_DROP_MEMBERSHIP \n - UDP socket, Leave a multicast group \n - This options takes SlSockIpMreq struct as parameter - - SL_IP_RAW_RX_NO_HEADER \n - Raw socket remove IP header from received data. \n - Default: data includes ip header \n - This options takes _u32 as parameter - - SL_IP_HDRINCL \n - RAW socket only, the IPv4 layer generates an IP header when sending a packet unless \n - the IP_HDRINCL socket option is enabled on the socket. \n - When it is enabled, the packet must contain an IP header. \n - Default: disabled, IPv4 header generated by Network Stack \n - This options takes _u32 as parameter - - SL_IP_RAW_IPV6_HDRINCL (inactive) \n - RAW socket only, the IPv6 layer generates an IP header when sending a packet unless \n - the IP_HDRINCL socket option is enabled on the socket. When it is enabled, the packet must contain an IP header \n - Default: disabled, IPv4 header generated by Network Stack \n - This options takes _u32 as parameter - - SL_SOL_PHY_OPT - - SL_SO_PHY_RATE \n - RAW socket, set WLAN PHY transmit rate \n - The values are based on RateIndex_e \n - This options takes _u32 as parameter - - SL_SO_PHY_TX_POWER \n - RAW socket, set WLAN PHY TX power \n - Valid rage is 1-15 \n - This options takes _u32 as parameter - - SL_SO_PHY_NUM_FRAMES_TO_TX \n - RAW socket, set number of frames to transmit in transceiver mode. - Default: 1 packet - This options takes _u32 as parameter - - SL_SO_PHY_PREAMBLE \n - RAW socket, set WLAN PHY preamble for Long/Short\n - This options takes _u32 as parameter - - \param[in] optval specifies a value for the option - \param[in] optlen specifies the length of the - option value - - \return On success, zero is returned. - On error, a negative value is returned. - \sa sl_getsockopt - \note belongs to \ref basic_api - \warning - \par Examples: - \par - SL_SO_KEEPALIVE: (disable Keepalive) - \code - SlSockKeepalive_t enableOption; - enableOption.KeepaliveEnabled = 0; - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_KEEPALIVE, (_u8 *)&enableOption,sizeof(enableOption)); - \endcode - \par - SL_SO_RCVTIMEO: - \code - struct SlTimeval_t timeVal; - timeVal.tv_sec = 1; // Seconds - timeVal.tv_usec = 0; // Microseconds. 10000 microseconds resolution - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_RCVTIMEO, (_u8 *)&timeVal, sizeof(timeVal)); // Enable receive timeout - \endcode - \par - SL_SO_RCVBUF: - \code - SlSockWinsize_t size; - size.Winsize = 3000; // bytes - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_RCVBUF, (_u8 *)&size, sizeof(size)); - \endcode - \par - SL_SO_NONBLOCKING: - \code - SlSockNonblocking_t enableOption; - enableOption.NonblockingEnabled = 1; - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_NONBLOCKING, (_u8 *)&enableOption,sizeof(enableOption)); // Enable/disable nonblocking mode - \endcode - \par - SL_SO_SECMETHOD: - \code - SlSockSecureMethod method; - method.secureMethod = SL_SO_SEC_METHOD_SSLV3; // security method we want to use - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET); - sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_SECMETHOD, (_u8 *)&method, sizeof(method)); - \endcode - \par - SL_SO_SECURE_MASK: - \code - SlSockSecureMask cipher; - cipher.secureMask = SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA; // cipher type - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, SL_SEC_SOCKET); - sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_SEC_MASK,(_u8 *)&cipher, sizeof(cipher)); - \endcode - \par - SL_SO_SECURE_FILES_CA_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CA_FILE_NAME,"exuifaxCaCert.der",strlen("exuifaxCaCert.der")); - \endcode - - \par - SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME,"myPrivateKey.der",strlen("myPrivateKey.der")); - \endcode - - \par - SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME,"myCertificate.der",strlen("myCertificate.der")); - \endcode - - \par - SL_SO_SECURE_FILES_DH_KEY_FILE_NAME: - \code - sl_SetSockOpt(SockID,SL_SOL_SOCKET,SL_SO_SECURE_FILES_DH_KEY_FILE_NAME,"myDHinServerMode.der",strlen("myDHinServerMode.der")); - \endcode - - \par - SL_IP_MULTICAST_TTL: - \code - _u8 ttl = 20; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_MULTICAST_TTL, &ttl, sizeof(ttl)); - \endcode - - \par - SL_IP_ADD_MEMBERSHIP: - \code - SlSockIpMreq mreq; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - \endcode - - \par - SL_IP_DROP_MEMBERSHIP: - \code - SlSockIpMreq mreq; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); - \endcode - - \par - SL_SO_CHANGE_CHANNEL: - \code - _u32 newChannel = 6; // range is 1-13 - sl_SetSockOpt(SockID, SL_SOL_SOCKET, SL_SO_CHANGE_CHANNEL, &newChannel, sizeof(newChannel)); - \endcode - - \par - SL_IP_RAW_RX_NO_HEADER: - \code - _u32 header = 1; // remove ip header - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_RAW_RX_NO_HEADER, &header, sizeof(header)); - \endcode - - \par - SL_IP_HDRINCL: - \code - _u32 header = 1; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_HDRINCL, &header, sizeof(header)); - \endcode - \par - SL_IP_RAW_IPV6_HDRINCL: - \code - _u32 header = 1; - sl_SetSockOpt(SockID, SL_IPPROTO_IP, SL_IP_RAW_IPV6_HDRINCL, &header, sizeof(header)); - \endcode - - \par - SL_SO_PHY_RATE: - \code - _u32 rate = 6; // see wlan.h RateIndex_e for values - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_RATE, &rate, sizeof(rate)); - \endcode - - \par - SL_SO_PHY_TX_POWER: - \code - _u32 txpower = 1; // valid range is 1-15 - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_TX_POWER, &txpower, sizeof(txpower)); - \endcode - - \par - SL_SO_PHY_NUM_FRAMES_TO_TX: - \code - _u32 numframes = 1; - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_NUM_FRAMES_TO_TX, &numframes, sizeof(numframes)); - \endcode - - \par - SL_SO_PHY_PREAMBLE: - \code - _u32 preamble = 1; - sl_SetSockOpt(SockID, SL_SOL_PHY_OPT, SL_SO_PHY_PREAMBLE, &preamble, sizeof(preamble)); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_SetSockOpt) -_i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen); -#endif - -/*! - \brief Get socket options - - This function manipulate the options associated with a socket. - Options may exist at multiple protocol levels; they are always - present at the uppermost socket level. - - When manipulating socket options the level at which the option resides - and the name of the option must be specified. To manipulate options at - the socket level, level is specified as SOL_SOCKET. To manipulate - options at any other level the protocol number of the appropriate proto- - col controlling the option is supplied. For example, to indicate that an - option is to be interpreted by the TCP protocol, level should be set to - the protocol number of TCP; - - The parameters optval and optlen are used to access optval - - ues for setsockopt(). For getsockopt() they identify a - buffer in which the value for the requested option(s) are to - be returned. For getsockopt(), optlen is a value-result - parameter, initially containing the size of the buffer - pointed to by option_value, and modified on return to - indicate the actual size of the value returned. If no option - value is to be supplied or returned, option_value may be - NULL. - - - \param[in] sd socket handle - \param[in] level defines the protocol level for this option - \param[in] optname defines the option name to interrogate - \param[out] optval specifies a value for the option - \param[out] optlen specifies the length of the - option value - - \return On success, zero is returned. - On error, a negative value is returned. - \sa sl_SetSockOpt - \note See sl_SetSockOpt - belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_GetSockOpt) -_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen); -#endif - -/*! - \brief read data from TCP socket - - function receives a message from a connection-mode socket - - \param[in] sd socket handle - \param[out] buf Points to the buffer where the - message should be stored. - \param[in] Len Specifies the length in bytes of - the buffer pointed to by the buffer argument. - Range: 1-16000 bytes - \param[in] flags Specifies the type of message - reception. On this version, this parameter is not - supported. - - \return return the number of bytes received, - or a negative value if an error occurred. - using a non-blocking recv a possible negative value is SL_EAGAIN. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_RecvFrom - \note belongs to \ref recv_api - \warning - \par Examples: - \code An example of receiving data using TCP socket: - - SlSockAddrIn_t Addr; - SlSockAddrIn_t LocalAddr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID, newSockID; - _i16 Status; - _i8 Buf[RECV_BUF_LEN]; - - LocalAddr.sin_family = SL_AF_INET; - LocalAddr.sin_port = sl_Htons(5001); - LocalAddr.sin_addr.s_addr = 0; - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(5001); - Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); - Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize); - Status = sl_Listen(SockID, 0); - newSockID = sl_Accept(SockID, (SlSockAddr_t*)&Addr, (SlSocklen_t*) &AddrSize); - Status = sl_Recv(newSockID, Buf, 1460, 0); - \endcode - \code Example code for Rx transceiver mode using a raw socket - _i8 buffer[1536]; - _i16 sd; - _u16 size; - SlTransceiverRxOverHead_t *transHeader; - sd = sl_Socket(SL_AF_RF,SL_SOCK_RAW,11); // channel 11 - while(1) - { - size = sl_Recv(sd,buffer,1536,0); - transHeader = (SlTransceiverRxOverHead_t *)buffer; - printf("RSSI is %d frame type is 0x%x size %d\n",transHeader->rssi,buffer[sizeof(SlTransceiverRxOverHead_t)],size); - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_Recv) -_i16 sl_Recv(_i16 sd, void *buf, _i16 Len, _i16 flags); -#endif - -/*! - \brief read data from socket - - function receives a message from a connection-mode or - connectionless-mode socket - - \param[in] sd socket handle - \param[out] buf Points to the buffer where the message should be stored. - \param[in] Len Specifies the length in bytes of the buffer pointed to by the buffer argument. - Range: 1-16000 bytes - \param[in] flags Specifies the type of message - reception. On this version, this parameter is not - supported. - \param[in] from pointer to an address structure - indicating the source - address.\n sockaddr:\n - code - for the address format. On this - version only AF_INET is - supported.\n - socket address, - the length depends on the code - format - \param[in] fromlen source address structure - size. This parameter MUST be set to the size of the structure pointed to by addr. - - - \return return the number of bytes received, - or a negative value if an error occurred. - using a non-blocking recv a possible negative value is SL_EAGAIN. - SL_RET_CODE_INVALID_INPUT (-2) will be returned if fromlen has incorrect length. - SL_POOL_IS_EMPTY may be return in case there are no resources in the system - In this case try again later or increase MAX_CONCURRENT_ACTIONS - - \sa sl_Recv - \note belongs to \ref recv_api - \warning - \par Example: - \code An example of receiving data: - - SlSockAddrIn_t Addr; - SlSockAddrIn_t LocalAddr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID; - _i16 Status; - _i8 Buf[RECV_BUF_LEN]; - - LocalAddr.sin_family = SL_AF_INET; - LocalAddr.sin_port = sl_Htons(5001); - LocalAddr.sin_addr.s_addr = 0; - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0); - Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize); - Status = sl_RecvFrom(SockID, Buf, 1472, 0, (SlSockAddr_t *)&Addr, (SlSocklen_t*)&AddrSize); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_RecvFrom) -_i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen); -#endif - -/*! - \brief write data to TCP socket - - This function is used to transmit a message to another socket. - Returns immediately after sending data to device. - In case of TCP failure an async event SL_SOCKET_TX_FAILED_EVENT is going to - be received. - In case of a RAW socket (transceiver mode), extra 4 bytes should be reserved at the end of the - frame data buffer for WLAN FCS - - \param[in] sd socket handle - \param[in] buf Points to a buffer containing - the message to be sent - \param[in] Len message size in bytes. Range: 1-1460 bytes - \param[in] flags Specifies the type of message - transmission. On this version, this parameter is not - supported for TCP. - For transceiver mode, the SL_RAW_RF_TX_PARAMS macro can be used to determine - transmission parameters (channel,rate,tx_power,preamble) - - - \return Return the number of bytes transmitted, - or -1 if an error occurred - - \sa sl_SendTo - \note belongs to \ref send_api - \warning - \par Example: - \code An example of sending data: - - SlSockAddrIn_t Addr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID; - _i16 Status; - _i8 Buf[SEND_BUF_LEN]; - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(5001); - Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); - Status = sl_Connect(SockID, (SlSockAddr_t *)&Addr, AddrSize); - Status = sl_Send(SockID, Buf, 1460, 0 ); - - \endcode - */ -#if _SL_INCLUDE_FUNC(sl_Send ) -_i16 sl_Send(_i16 sd, const void *buf, _i16 Len, _i16 flags); -#endif - -/*! - \brief write data to socket - - This function is used to transmit a message to another socket - (connection less socket SOCK_DGRAM, SOCK_RAW). - Returns immediately after sending data to device. - In case of transmission failure an async event SL_SOCKET_TX_FAILED_EVENT is going to - be received. - - \param[in] sd socket handle - \param[in] buf Points to a buffer containing - the message to be sent - \param[in] Len message size in bytes. Range: 1-1460 bytes - \param[in] flags Specifies the type of message - transmission. On this version, this parameter is not - supported - \param[in] to pointer to an address structure - indicating the destination - address.\n sockaddr:\n - code - for the address format. On this - version only AF_INET is - supported.\n - socket address, - the length depends on the code - format - \param[in] tolen destination address structure size - - \return Return the number of transmitted bytes, - or -1 if an error occurred - - \sa sl_Send - \note belongs to \ref send_api - \warning - \par Example: - \code An example of sending data: - - SlSockAddrIn_t Addr; - _i16 AddrSize = sizeof(SlSockAddrIn_t); - _i16 SockID; - _i16 Status; - _i8 Buf[SEND_BUF_LEN]; - - Addr.sin_family = SL_AF_INET; - Addr.sin_port = sl_Htons(5001); - Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200)); - - SockID = sl_Socket(SL_AF_INET,SL_SOCK_DGRAM, 0); - Status = sl_SendTo(SockID, Buf, 1472, 0, (SlSockAddr_t *)&Addr, AddrSize); - - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_SendTo) -_i16 sl_SendTo(_i16 sd, const void *buf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen); -#endif - -/*! - \brief Reorder the bytes of a 32-bit unsigned value - - This function is used to Reorder the bytes of a 32-bit unsigned value from processor order to network order. - - \param[in] var variable to reorder - - \return Return the reorder variable, - - \sa sl_SendTo sl_Bind sl_Connect sl_RecvFrom sl_Accept - \note belongs to \ref send_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Htonl ) -_u32 sl_Htonl( _u32 val ); - -#define sl_Ntohl sl_Htonl /* Reorder the bytes of a 16-bit unsigned value from network order to processor orde. */ -#endif - -/*! - \brief Reorder the bytes of a 16-bit unsigned value - - This function is used to Reorder the bytes of a 16-bit unsigned value from processor order to network order. - - \param[in] var variable to reorder - - \return Return the reorder variable, - - \sa sl_SendTo sl_Bind sl_Connect sl_RecvFrom sl_Accept - \note belongs to \ref send_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_Htons ) -_u16 sl_Htons( _u16 val ); - -#define sl_Ntohs sl_Htons /* Reorder the bytes of a 16-bit unsigned value from network order to processor orde. */ -#endif - -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __SOCKET_H__ */ - - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/spawn.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/spawn.h deleted file mode 100644 index 82c112d2..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/spawn.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * spawn.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -#ifndef __NONOS_H__ -#define __NONOS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -#if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) - -extern void _SlInternalSpawnTaskEntry(); -extern _i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags); - -#undef sl_Spawn -#define sl_Spawn(pEntry,pValue,flags) _SlInternalSpawn(pEntry,pValue,flags) - -#undef _SlTaskEntry -#define _SlTaskEntry _SlInternalSpawnTaskEntry - - -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/trace.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/trace.h deleted file mode 100644 index 4ca42c77..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/trace.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * trace.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -#include "simplelink.h" - -#ifndef __SIMPLELINK_TRACE_H__ -#define __SIMPLELINK_TRACE_H__ - - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define SL_SYNC_SCAN_THRESHOLD (( _u32 )2000) - -#define _SL_ASSERT(expr) { ASSERT(expr); } -#define _SL_ERROR(expr, error) { if(!(expr)){return (error); } } - -#define SL_HANDLING_ASSERT 2 -#define SL_HANDLING_ERROR 1 -#define SL_HANDLING_NONE 0 - -#define SL_SELF_COND_HANDLING SL_HANDLING_NONE -#define SL_PROTOCOL_HANDLING SL_HANDLING_NONE -#define SL_DRV_RET_CODE_HANDLING SL_HANDLING_NONE -#define SL_NWP_IF_HANDLING SL_HANDLING_NONE -#define SL_OSI_RET_OK_HANDLING SL_HANDLING_NONE -#define SL_MALLOC_OK_HANDLING SL_HANDLING_NONE -#define SL_USER_ARGS_HANDLING SL_HANDLING_NONE - -#if (SL_DRV_RET_CODE_HANDLING == SL_HANDLING_ASSERT) -#define VERIFY_RET_OK(Func) {_SlReturnVal_t _RetVal = (Func); _SL_ASSERT((_SlReturnVal_t)SL_OS_RET_CODE_OK == _RetVal)} -#elif (SL_DRV_RET_CODE_HANDLING == SL_HANDLING_ERROR) -#define VERIFY_RET_OK(Func) {_SlReturnVal_t _RetVal = (Func); if (SL_OS_RET_CODE_OK != _RetVal) return _RetVal;} -#else -#define VERIFY_RET_OK(Func) (Func); -#endif - -#if (SL_PROTOCOL_HANDLING == SL_HANDLING_ASSERT) -#define VERIFY_PROTOCOL(expr) _SL_ASSERT(expr) -#elif (SL_PROTOCOL_HANDLING == SL_HANDLING_ERROR) -#define VERIFY_PROTOCOL(expr) _SL_ERROR(expr, SL_RET_CODE_PROTOCOL_ERROR) -#else -#define VERIFY_PROTOCOL(expr) -#endif - -#if (defined(PROTECT_SOCKET_ASYNC_RESP) && (SL_SELF_COND_HANDLING == SL_HANDLING_ASSERT)) -#define VERIFY_SOCKET_CB(expr) _SL_ASSERT(expr) -#elif (defined(PROTECT_SOCKET_ASYNC_RESP) && (SL_SELF_COND_HANDLING == SL_HANDLING_ERROR)) -#define VERIFY_SOCKET_CB(expr) _SL_ERROR(expr, SL_RET_CODE_SELF_ERROR) -#else -#define VERIFY_SOCKET_CB(expr) -#endif - -#if (SL_NWP_IF_HANDLING == SL_HANDLING_ASSERT) -#define NWP_IF_WRITE_CHECK(fd,pBuff,len) { _i16 RetSize, ExpSize = (len); RetSize = sl_IfWrite((fd),(pBuff),ExpSize); _SL_ASSERT(ExpSize == RetSize)} -#define NWP_IF_READ_CHECK(fd,pBuff,len) { _i16 RetSize, ExpSize = (len); RetSize = sl_IfRead((fd),(pBuff),ExpSize); _SL_ASSERT(ExpSize == RetSize)} -#elif (SL_NWP_IF_HANDLING == SL_HANDLING_ERROR) -#define NWP_IF_WRITE_CHECK(fd,pBuff,len) { _SL_ERROR((len == sl_IfWrite((fd),(pBuff),(len))), SL_RET_CODE_NWP_IF_ERROR);} -#define NWP_IF_READ_CHECK(fd,pBuff,len) { _SL_ERROR((len == sl_IfRead((fd),(pBuff),(len))), SL_RET_CODE_NWP_IF_ERROR);} -#else -#define NWP_IF_WRITE_CHECK(fd,pBuff,len) { sl_IfWrite((fd),(pBuff),(len));} -#define NWP_IF_READ_CHECK(fd,pBuff,len) { sl_IfRead((fd),(pBuff),(len));} -#endif - -#if (SL_OSI_RET_OK_HANDLING == SL_HANDLING_ASSERT) -#define OSI_RET_OK_CHECK(Func) {_SlReturnVal_t _RetVal = (Func); _SL_ASSERT((_SlReturnVal_t)SL_OS_RET_CODE_OK == _RetVal)} -#elif (SL_OSI_RET_OK_HANDLING == SL_HANDLING_ERROR) -#define OSI_RET_OK_CHECK(Func) {_SlReturnVal_t _RetVal = (Func); if (SL_OS_RET_CODE_OK != _RetVal) return _RetVal;} -#else -#define OSI_RET_OK_CHECK(Func) (Func); -#endif - -#if (SL_MALLOC_OK_HANDLING == SL_HANDLING_ASSERT) -#define MALLOC_OK_CHECK(Ptr) _SL_ASSERT(NULL != Ptr) -#elif (SL_MALLOC_OK_HANDLING == SL_HANDLING_ERROR) -#define MALLOC_OK_CHECK(Ptr) _SL_ERROR((NULL != Ptr), SL_RET_CODE_MALLOC_ERROR) -#else -#define MALLOC_OK_CHECK(Ptr) -#endif - -#ifdef SL_INC_ARG_CHECK - -#if (SL_USER_ARGS_HANDLING == SL_HANDLING_ASSERT) -#define ARG_CHECK_PTR(Ptr) _SL_ASSERT(NULL != Ptr) -#elif (SL_USER_ARGS_HANDLING == SL_HANDLING_ERROR) -#define ARG_CHECK_PTR(Ptr) _SL_ERROR((NULL != Ptr), SL_RET_CODE_INVALID_INPUT) -#else -#define ARG_CHECK_PTR(Ptr) -#endif - -#else -#define ARG_CHECK_PTR(Ptr) -#endif - -#define SL_TRACE0(level,msg_id,str) -#define SL_TRACE1(level,msg_id,str,p1) -#define SL_TRACE2(level,msg_id,str,p1,p2) -#define SL_TRACE3(level,msg_id,str,p1,p2,p3) -#define SL_TRACE4(level,msg_id,str,p1,p2,p3,p4) -#define SL_ERROR_TRACE(msg_id,str) -#define SL_ERROR_TRACE1(msg_id,str,p1) -#define SL_ERROR_TRACE2(msg_id,str,p1,p2) -#define SL_ERROR_TRACE3(msg_id,str,p1,p2,p3) -#define SL_ERROR_TRACE4(msg_id,str,p1,p2,p3,p4) -#define SL_TRACE_FLUSH() - -/* #define SL_DBG_CNT_ENABLE */ -#ifdef SL_DBG_CNT_ENABLE -#define _SL_DBG_CNT_INC(Cnt) g_DbgCnt. ## Cnt++ -#define _SL_DBG_SYNC_LOG(index,value) {if(index < SL_DBG_SYNC_LOG_SIZE){*(_u32 *)&g_DbgCnt.SyncLog[index] = *(_u32 *)(value);}} - -#else -#define _SL_DBG_CNT_INC(Cnt) -#define _SL_DBG_SYNC_LOG(index,value) -#endif - -#define SL_DBG_LEVEL_1 1 -#define SL_DBG_LEVEL_2 2 -#define SL_DBG_LEVEL_3 4 -#define SL_DBG_LEVEL_MASK (SL_DBG_LEVEL_2|SL_DBG_LEVEL_3) - -#define SL_INCLUDE_DBG_FUNC(Name) ((Name ## _DBG_LEVEL) & SL_DBG_LEVEL_MASK) - -#define _SlDrvPrintStat_DBG_LEVEL SL_DBG_LEVEL_3 -#define _SlDrvOtherFunc_DBG_LEVEL SL_DBG_LEVEL_1 - -#ifdef __cplusplus -} -#endif - - -#endif /*__SIMPLELINK_TRACE_H__*/ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/wlan.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/wlan.h deleted file mode 100644 index 156b94ea..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/wlan.h +++ /dev/null @@ -1,1308 +0,0 @@ -/* - * wlan.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef __WLAN_H__ -#define __WLAN_H__ - - - - -#ifdef __cplusplus -extern "C" { -#endif - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/*! - - \addtogroup wlan - @{ - -*/ - -#define SL_BSSID_LENGTH (6) -#define MAXIMAL_SSID_LENGTH (32) - -#define NUM_OF_RATE_INDEXES (20) -#define SIZE_OF_RSSI_HISTOGRAM (6) - -/* WLAN Disconnect Reason Codes */ -#define SL_DISCONNECT_RESERVED_0 (0) -#define SL_DISCONNECT_UNSPECIFIED_REASON (1) -#define SL_PREVIOUS_AUTHENTICATION_NO_LONGER_VALID (2) -#define SL_DEAUTHENTICATED_BECAUSE_SENDING_STATION_IS_LEAVING (3) -#define SL_DISASSOCIATED_DUE_TO_INACTIVITY (4) -#define SL_DISASSOCIATED_BECAUSE_AP_IS_UNABLE_TO_HANDLE_ALL_CURRENTLY_ASSOCIATED_STATIONS (5) -#define SL_CLASS_2_FRAME_RECEIVED_FROM_NONAUTHENTICATED_STATION (6) -#define SL_CLASS_3_FRAME_RECEIVED_FROM_NONASSOCIATED_STATION (7) -#define SL_DISASSOCIATED_BECAUSE_SENDING_STATION_IS_LEAVING_BSS (8) -#define SL_STATION_REQUESTING_ASSOCIATION_IS_NOT_AUTHENTICATED_WITH_RESPONDING_STATION (9) -#define SL_DISASSOCIATED_BECAUSE_THE_INFORMATION_IN_THE_POWER_CAPABILITY_ELEMENT_IS_UNACCEPTABLE (10) -#define SL_DISASSOCIATED_BECAUSE_THE_INFORMATION_IN_THE_SUPPORTED_CHANNELS_ELEMENT_IS_UNACCEPTABLE (11) -#define SL_DISCONNECT_RESERVED_1 (12) -#define SL_INVALID_INFORMATION_ELEMENT (13) -#define SL_MESSAGE_INTEGRITY_CODE_MIC_FAILURE (14) -#define SL_FOUR_WAY_HANDSHAKE_TIMEOUT (15) -#define SL_GROUP_KEY_HANDSHAKE_TIMEOUT (16) -#define SL_RE_ASSOCIATION_REQUEST_PROBE_RESPONSE_BEACON_FRAME (17) -#define SL_INVALID_GROUP_CIPHER (18) -#define SL_INVALID_PAIRWISE_CIPHER (19) -#define SL_INVALID_AKMP (20) -#define SL_UNSUPPORTED_RSN_INFORMATION_ELEMENT_VERSION (21) -#define SL_INVALID_RSN_INFORMATION_ELEMENT_CAPABILITIES (22) -#define SL_IEEE_802_1X_AUTHENTICATION_FAILED (23) -#define SL_CIPHER_SUITE_REJECTED_BECAUSE_OF_THE_SECURITY_POLICY (24) -#define SL_DISCONNECT_RESERVED_2 (25) -#define SL_DISCONNECT_RESERVED_3 (26) -#define SL_DISCONNECT_RESERVED_4 (27) -#define SL_DISCONNECT_RESERVED_5 (28) -#define SL_DISCONNECT_RESERVED_6 (29) -#define SL_DISCONNECT_RESERVED_7 (30) -#define SL_DISCONNECT_RESERVED_8 (31) -#define SL_USER_INITIATED_DISCONNECTION (200) - -/* Wlan error codes */ -#define SL_ERROR_KEY_ERROR (-3) -#define SL_ERROR_INVALID_ROLE (-71) -#define SL_ERROR_INVALID_SECURITY_TYPE (-84) -#define SL_ERROR_PASSPHRASE_TOO_LONG (-85) -#define SL_ERROR_WPS_NO_PIN_OR_WRONG_PIN_LEN (-87) -#define SL_ERROR_EAP_WRONG_METHOD (-88) -#define SL_ERROR_PASSWORD_ERROR (-89) -#define SL_ERROR_EAP_ANONYMOUS_LEN_ERROR (-90) -#define SL_ERROR_SSID_LEN_ERROR (-91) -#define SL_ERROR_USER_ID_LEN_ERROR (-92) -#define SL_ERROR_ILLEGAL_WEP_KEY_INDEX (-95) -#define SL_ERROR_INVALID_DWELL_TIME_VALUES (-96) -#define SL_ERROR_INVALID_POLICY_TYPE (-97) -#define SL_ERROR_PM_POLICY_INVALID_OPTION (-98) -#define SL_ERROR_PM_POLICY_INVALID_PARAMS (-99) -#define SL_ERROR_WIFI_ALREADY_DISCONNECTED (-129) -#define SL_ERROR_WIFI_NOT_CONNECTED (-59) - - - -#define SL_SEC_TYPE_OPEN (0) -#define SL_SEC_TYPE_WEP (1) -#define SL_SEC_TYPE_WPA (2) /* deprecated */ -#define SL_SEC_TYPE_WPA_WPA2 (2) -#define SL_SEC_TYPE_WPS_PBC (3) -#define SL_SEC_TYPE_WPS_PIN (4) -#define SL_SEC_TYPE_WPA_ENT (5) -#define SL_SEC_TYPE_P2P_PBC (6) -#define SL_SEC_TYPE_P2P_PIN_KEYPAD (7) -#define SL_SEC_TYPE_P2P_PIN_DISPLAY (8) -#define SL_SEC_TYPE_P2P_PIN_AUTO (9) /* NOT Supported yet */ - - - -#define SL_SCAN_SEC_TYPE_OPEN (0) -#define SL_SCAN_SEC_TYPE_WEP (1) -#define SL_SCAN_SEC_TYPE_WPA (2) -#define SL_SCAN_SEC_TYPE_WPA2 (3) - - - -#define TLS (0x1) -#define MSCHAP (0x0) -#define PSK (0x2) -#define TTLS (0x10) -#define PEAP0 (0x20) -#define PEAP1 (0x40) -#define FAST (0x80) - -#define FAST_AUTH_PROVISIONING (0x02) -#define FAST_UNAUTH_PROVISIONING (0x01) -#define FAST_NO_PROVISIONING (0x00) - -#define EAPMETHOD_PHASE2_SHIFT (8) -#define EAPMETHOD_PAIRWISE_CIPHER_SHIFT (19) -#define EAPMETHOD_GROUP_CIPHER_SHIFT (27) - -#define WPA_CIPHER_CCMP (0x1) -#define WPA_CIPHER_TKIP (0x2) -#define CC31XX_DEFAULT_CIPHER (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) - -#define EAPMETHOD(phase1,phase2,pairwise_cipher,group_cipher) \ -((phase1) | \ - ((phase2) << EAPMETHOD_PHASE2_SHIFT ) |\ - ((_u32)(pairwise_cipher) << EAPMETHOD_PAIRWISE_CIPHER_SHIFT ) |\ - ((_u32)(group_cipher) << EAPMETHOD_GROUP_CIPHER_SHIFT )) - -/* phase1 phase2 pairwise_cipher group_cipher */ -#define SL_ENT_EAP_METHOD_TLS EAPMETHOD(TLS , 0 , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_TTLS_TLS EAPMETHOD(TTLS , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_TTLS_MSCHAPv2 EAPMETHOD(TTLS , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_TTLS_PSK EAPMETHOD(TTLS , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP0_TLS EAPMETHOD(PEAP0 , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP0_MSCHAPv2 EAPMETHOD(PEAP0 , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP0_PSK EAPMETHOD(PEAP0 , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP1_TLS EAPMETHOD(PEAP1 , TLS , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP1_MSCHAPv2 EAPMETHOD(PEAP1 , MSCHAP , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_PEAP1_PSK EAPMETHOD(PEAP1 , PSK , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_FAST_AUTH_PROVISIONING EAPMETHOD(FAST , FAST_AUTH_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_FAST_UNAUTH_PROVISIONING EAPMETHOD(FAST , FAST_UNAUTH_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) -#define SL_ENT_EAP_METHOD_FAST_NO_PROVISIONING EAPMETHOD(FAST , FAST_NO_PROVISIONING , CC31XX_DEFAULT_CIPHER , CC31XX_DEFAULT_CIPHER) - -#define SL_LONG_PREAMBLE (0) -#define SL_SHORT_PREAMBLE (1) - -#define SL_RAW_RF_TX_PARAMS_CHANNEL_SHIFT (0) -#define SL_RAW_RF_TX_PARAMS_RATE_SHIFT (6) -#define SL_RAW_RF_TX_PARAMS_POWER_SHIFT (11) -#define SL_RAW_RF_TX_PARAMS_PREAMBLE_SHIFT (15) - -#define SL_RAW_RF_TX_PARAMS(chan,rate,power,preamble) \ - ((chan << SL_RAW_RF_TX_PARAMS_CHANNEL_SHIFT) | \ - (rate << SL_RAW_RF_TX_PARAMS_RATE_SHIFT) | \ - (power << SL_RAW_RF_TX_PARAMS_POWER_SHIFT) | \ - (preamble << SL_RAW_RF_TX_PARAMS_PREAMBLE_SHIFT)) - - -/* wlan config application IDs */ -#define SL_WLAN_CFG_AP_ID (0) -#define SL_WLAN_CFG_GENERAL_PARAM_ID (1) -#define SL_WLAN_CFG_P2P_PARAM_ID (2) - -/* wlan AP Config set/get options */ -#define WLAN_AP_OPT_SSID (0) -#define WLAN_AP_OPT_CHANNEL (3) -#define WLAN_AP_OPT_HIDDEN_SSID (4) -#define WLAN_AP_OPT_SECURITY_TYPE (6) -#define WLAN_AP_OPT_PASSWORD (7) -#define WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE (9) -#define WLAN_GENERAL_PARAM_OPT_STA_TX_POWER (10) -#define WLAN_GENERAL_PARAM_OPT_AP_TX_POWER (11) - -#define WLAN_P2P_OPT_DEV_NAME (12) -#define WLAN_P2P_OPT_DEV_TYPE (13) -#define WLAN_P2P_OPT_CHANNEL_N_REGS (14) -#define WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT (16) -#define WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS (18) /* change the scan channels and RSSI threshold using this configuration option */ - -/* SmartConfig CIPHER options */ -#define SMART_CONFIG_CIPHER_SFLASH (0) /* password is not delivered by the application. The Simple Manager should */ - /* check if the keys are stored in the Flash. */ -#define SMART_CONFIG_CIPHER_AES (1) /* AES (other types are not supported) */ -#define SMART_CONFIG_CIPHER_NONE (0xFF) /* do not check in the flash */ - - -#define SL_POLICY_CONNECTION (0x10) -#define SL_POLICY_SCAN (0x20) -#define SL_POLICY_PM (0x30) -#define SL_POLICY_P2P (0x40) - -#define VAL_2_MASK(position,value) ((1 & (value))<<(position)) -#define MASK_2_VAL(position,mask) (((1 << position) & (mask)) >> (position)) - -#define SL_CONNECTION_POLICY(Auto,Fast,Open,anyP2P,autoSmartConfig) (VAL_2_MASK(0,Auto) | VAL_2_MASK(1,Fast) | VAL_2_MASK(2,Open) | VAL_2_MASK(3,anyP2P) | VAL_2_MASK(4,autoSmartConfig)) -#define SL_SCAN_POLICY_EN(policy) (MASK_2_VAL(0,policy)) -#define SL_SCAN_POLICY(Enable) (VAL_2_MASK(0,Enable)) - - -#define SL_NORMAL_POLICY (0) -#define SL_LOW_LATENCY_POLICY (1) -#define SL_LOW_POWER_POLICY (2) -#define SL_ALWAYS_ON_POLICY (3) -#define SL_LONG_SLEEP_INTERVAL_POLICY (4) - -#define SL_P2P_ROLE_NEGOTIATE (3) -#define SL_P2P_ROLE_GROUP_OWNER (15) -#define SL_P2P_ROLE_CLIENT (0) - -#define SL_P2P_NEG_INITIATOR_ACTIVE (0) -#define SL_P2P_NEG_INITIATOR_PASSIVE (1) -#define SL_P2P_NEG_INITIATOR_RAND_BACKOFF (2) - -#define POLICY_VAL_2_OPTIONS(position,mask,policy) ((mask & policy) << position ) - -#define SL_P2P_POLICY(p2pNegType,p2pNegInitiator) (POLICY_VAL_2_OPTIONS(0,0xF,(p2pNegType > SL_P2P_ROLE_GROUP_OWNER ? SL_P2P_ROLE_GROUP_OWNER : p2pNegType)) | \ - POLICY_VAL_2_OPTIONS(4,0x1,(p2pNegType > SL_P2P_ROLE_GROUP_OWNER ? 1:0)) | \ - POLICY_VAL_2_OPTIONS(5,0x3, p2pNegInitiator)) - - -/* Info elements */ - -#define INFO_ELEMENT_DEFAULT_ID (0) /* 221 will be used */ - -/* info element size is up to 252 bytes (+ 3 bytes of OUI). */ -#define INFO_ELEMENT_MAX_SIZE (252) - -/* For AP - the total length of all info elements is 300 bytes (for example - 4 info elements of 75 bytes each) */ -#define INFO_ELEMENT_MAX_TOTAL_LENGTH_AP (300) -/* For P2P - the total length of all info elements is 150 bytes (for example - 4 info elements of 40 bytes each) */ -#define INFO_ELEMENT_MAX_TOTAL_LENGTH_P2P_GO (160) - -#define INFO_ELEMENT_AP_ROLE (0) -#define INFO_ELEMENT_P2P_GO_ROLE (1) - -/* we support up to 4 info elements per Role. */ -#define MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED (4) - -#define INFO_ELEMENT_DEFAULT_OUI_0 (0x08) -#define INFO_ELEMENT_DEFAULT_OUI_1 (0x00) -#define INFO_ELEMENT_DEFAULT_OUI_2 (0x28) - -#define INFO_ELEMENT_DEFAULT_OUI (0x000000) /* 08, 00, 28 will be used */ - -/*****************************************************************************/ -/* Structure/Enum declarations */ -/*****************************************************************************/ - -typedef enum -{ - RATE_1M = 1, - RATE_2M = 2, - RATE_5_5M = 3, - RATE_11M = 4, - RATE_6M = 6, - RATE_9M = 7, - RATE_12M = 8, - RATE_18M = 9, - RATE_24M = 10, - RATE_36M = 11, - RATE_48M = 12, - RATE_54M = 13, - RATE_MCS_0 = 14, - RATE_MCS_1 = 15, - RATE_MCS_2 = 16, - RATE_MCS_3 = 17, - RATE_MCS_4 = 18, - RATE_MCS_5 = 19, - RATE_MCS_6 = 20, - RATE_MCS_7 = 21, - MAX_NUM_RATES = 0xFF -}SlRateIndex_e; - -typedef enum { - DEV_PW_DEFAULT=0, - DEV_PW_PIN_KEYPAD=1, - DEV_PW_PUSH_BUTTON=4, - DEV_PW_PIN_DISPLAY=5 -} sl_p2p_dev_password_method; - - -typedef struct -{ - _u32 status; - _u32 ssid_len; - _u8 ssid[32]; - _u32 private_token_len; - _u8 private_token[32]; -}slSmartConfigStartAsyncResponse_t; - -typedef struct -{ - _u16 status; - _u16 padding; -}slSmartConfigStopAsyncResponse_t; - -typedef struct -{ - _u16 status; - _u16 padding; -}slWlanConnFailureAsyncResponse_t; - -typedef struct -{ - _u8 connection_type;/* 0-STA,3-P2P_CL */ - _u8 ssid_len; - _u8 ssid_name[32]; - _u8 go_peer_device_name_len; - _u8 go_peer_device_name[32]; - _u8 bssid[6]; - _u8 reason_code; - _u8 padding[2]; -} slWlanConnectAsyncResponse_t; - -typedef struct -{ - _u8 go_peer_device_name[32]; - _u8 mac[6]; - _u8 go_peer_device_name_len; - _u8 wps_dev_password_id; - _u8 own_ssid[32];/* relevant for event sta-connected only */ - _u8 own_ssid_len;/* relevant for event sta-connected only */ - _u8 padding[3]; -}slPeerInfoAsyncResponse_t; - - -typedef union -{ - slSmartConfigStartAsyncResponse_t smartConfigStartResponse; /*SL_WLAN_SMART_CONFIG_COMPLETE_EVENT*/ - slSmartConfigStopAsyncResponse_t smartConfigStopResponse; /*SL_WLAN_SMART_CONFIG_STOP_EVENT */ - slPeerInfoAsyncResponse_t APModeStaConnected; /* SL_WLAN_STA_CONNECTED_EVENT - relevant only in AP mode - holds information regarding a new STA connection */ - slPeerInfoAsyncResponse_t APModestaDisconnected; /* SL_WLAN_STA_DISCONNECTED_EVENT - relevant only in AP mode - holds information regarding a STA disconnection */ - slWlanConnectAsyncResponse_t STAandP2PModeWlanConnected; /* SL_WLAN_CONNECT_EVENT - relevant only in STA and P2P mode - holds information regarding a new connection */ - slWlanConnectAsyncResponse_t STAandP2PModeDisconnected; /* SL_WLAN_DISCONNECT_EVENT - relevant only in STA and P2P mode - holds information regarding a disconnection */ - slPeerInfoAsyncResponse_t P2PModeDevFound; /* SL_WLAN_P2P_DEV_FOUND_EVENT - relevant only in P2P mode */ - slPeerInfoAsyncResponse_t P2PModeNegReqReceived; /* SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT - relevant only in P2P mode */ - slWlanConnFailureAsyncResponse_t P2PModewlanConnectionFailure; /* SL_WLAN_CONNECTION_FAILED_EVENT - relevant only in P2P mode */ - -} SlWlanEventData_u; - -typedef struct -{ - _u32 Event; - SlWlanEventData_u EventData; -} SlWlanEvent_t; - - -typedef struct -{ - _u32 ReceivedValidPacketsNumber; /* sum of the packets that been received OK (include filtered) */ - _u32 ReceivedFcsErrorPacketsNumber; /* sum of the packets that been dropped due to FCS error */ - _u32 ReceivedAddressMismatchPacketsNumber; /* sum of the packets that been received but filtered out by one of the HW filters */ - _i16 AvarageDataCtrlRssi; /* average RSSI for all valid data packets received */ - _i16 AvarageMgMntRssi; /* average RSSI for all valid management packets received */ - _u16 RateHistogram[NUM_OF_RATE_INDEXES]; /* rate histogram for all valid packets received */ - _u16 RssiHistogram[SIZE_OF_RSSI_HISTOGRAM]; /* RSSI histogram from -40 until -87 (all below and above\n RSSI will appear in the first and last cells */ - _u32 StartTimeStamp; /* the time stamp started collecting the statistics in uSec */ - _u32 GetTimeStamp; /* the time stamp called the get statistics command */ -}SlGetRxStatResponse_t; - - -typedef struct -{ - _u8 ssid[MAXIMAL_SSID_LENGTH]; - _u8 ssid_len; - _u8 sec_type; - _u8 bssid[SL_BSSID_LENGTH]; - _i8 rssi; - _i8 reserved[3]; -}Sl_WlanNetworkEntry_t; - - -typedef struct -{ - _u8 Type; - _i8* Key; - _u8 KeyLen; -}SlSecParams_t; - -typedef struct -{ - _i8* User; - _u8 UserLen; - _i8* AnonUser; - _u8 AnonUserLen; - _u8 CertIndex; /* not supported */ - _u32 EapMethod; -}SlSecParamsExt_t; - -typedef struct -{ - _i8 User[32]; - _u8 UserLen; - _i8 AnonUser[32]; - _u8 AnonUserLen; - _u8 CertIndex; /* not supported */ - _u32 EapMethod; -}SlGetSecParamsExt_t; - -typedef enum -{ - ROLE_STA = 0, - ROLE_AP = 2, - ROLE_P2P = 3, - ROLE_STA_ERR = -1, /* Failure to load MAC/PHY in STA role */ - ROLE_AP_ERR = -ROLE_AP, /* Failure to load MAC/PHY in AP role */ - ROLE_P2P_ERR = -ROLE_P2P /* Failure to load MAC/PHY in P2P role */ -}SlWlanMode_t; - -typedef struct -{ - _u32 G_Channels_mask; - _i32 rssiThershold; -}slWlanScanParamCommand_t; - - -typedef struct -{ - _u8 id; - _u8 oui[3]; - _u16 length; - _u8 data[252]; -} sl_protocol_InfoElement_t; - -typedef struct -{ - _u8 index; /* 0 - MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED */ - _u8 role; /* bit0: AP = 0, GO = 1 */ - sl_protocol_InfoElement_t ie; -} sl_protocol_WlanSetInfoElement_t; - - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ - - -/*! - \brief Connect to wlan network as a station - - \param[in] pName up to 32 bytes in case of STA the name is the SSID of the Access Point - \param[in] NameLen name length - \param[in] pMacAddr 6 bytes for MAC address - \param[in] pSecParams Security parameters (use NULL key for SL_SEC_TYPE_OPEN) - Security types options: \n - - SL_SEC_TYPE_OPEN - - SL_SEC_TYPE_WEP - - SL_SEC_TYPE_WPA_WPA2 - - SL_SEC_TYPE_WPA_ENT - - SL_SEC_TYPE_WPS_PBC - - SL_SEC_TYPE_WPS_PIN - - \param[in] pSecExtParams Enterprise parameters (set NULL in case Enterprise parameters is not in use) - - \return On success, zero is returned. On error, negative is returned - In case error number (-71) is returned, it indicates a connection was activated while the device it running in AP role - - \sa sl_WlanDisconnect - \note belongs to \ref ext_api - \warning In this version only single enterprise mode could be used - SL_SEC_TYPE_WPA is a deprecated definition, the new definition is SL_SEC_TYPE_WPA_WPA2 -*/ -#if _SL_INCLUDE_FUNC(sl_WlanConnect) -_i16 sl_WlanConnect(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams); -#endif - -/*! - \brief wlan disconnect - - Disconnect connection - - \return 0 disconnected done, other already disconnected - - \sa sl_WlanConnect - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanDisconnect) -_i16 sl_WlanDisconnect(void); -#endif - -/*! - \brief add profile - - When auto start is enabled, the device connects to a - station from the profiles table. Up to 7 profiles are - supported. If several profiles configured the device chose - the highest priority profile, within each priority group, - device will chose profile based on security policy, signal - strength, etc parameters. - - - \param[in] pName up to 32 bytes in case of STA the name is the - SSID of the Access Point - in case of P2P the name is the remote device name - \param[in] NameLen name length - \param[in] pMacAddr 6 bytes for MAC address - \param[in] pSecParams Security parameters - security type - (SL_SEC_TYPE_OPEN,SL_SEC_TYPE_WEP,SL_SEC_TYPE_WPA_WPA2, - SL_SEC_TYPE_P2P_PBC,SL_SEC_TYPE_P2P_PIN_KEYPAD,SL_SEC_TYPE_P2P_PIN_DISPLAY, SL_SEC_TYPE_WPA_ENT), key, and key length - in case of p2p security type pin the key refers to pin code - \param[in] pSecExtParams Enterprise parameters - identity, identity length, - Anonymous, Anonymous length, CertIndex (not supported, - certificates need to be placed in a specific file ID), - EapMethod.Use NULL in case Enterprise parameters is not in use - - \param[in] Priority profile priority. Lowest priority: 0 - \param[in] Options Not supported - - \return On success, profile stored index is returned. On error, negative value is returned - - \sa sl_WlanProfileGet , sl_WlanProfileDel - \note belongs to \ref ext_api - \warning Only one Enterprise profile is supported. - Please Note that in case of adding an existing profile (compared by pName,pMACAddr and security type) - the old profile will be deleted and the same index will be returned. - SL_SEC_TYPE_WPA is a deprecated definition, the new definition is SL_SEC_TYPE_WPA_WPA2 - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanProfileAdd) -_i16 sl_WlanProfileAdd(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams,const _u32 Priority,const _u32 Options); -#endif - -/*! - \brief get profile - - read profile from the device - - \param[in] Index profile stored index, if index does not exists - error is return - \param[out] pName up to 32 bytes, in case of sta mode the name of the Access Point - in case of p2p mode the name of the Remote Device - \param[out] pNameLen name length - \param[out] pMacAddr 6 bytes for MAC address - \param[out] pSecParams security parameters - security type - (SL_SEC_TYPE_OPEN, SL_SEC_TYPE_WEP, SL_SEC_TYPE_WPA_WPA2 or - SL_SEC_TYPE_WPS_PBC, SL_SEC_TYPE_WPS_PIN, SL_SEC_TYPE_WPA_ENT,SL_SEC_TYPE_P2P_PBC,SL_SEC_TYPE_P2P_PIN_KEYPAD or SL_SEC_TYPE_P2P_PIN_DISPLAY), key and key length are not - in case of p2p security type pin the key refers to pin code - return due to security reasons. - \param[out] pSecExtParams enterprise parameters - identity, identity - length, Anonymous, Anonymous length - CertIndex (not supported), EapMethod. - \param[out] Priority profile priority - - \return On success, Profile security type is returned (0 or positive number). On error, -1 is - returned - - \sa sl_WlanProfileAdd , sl_WlanProfileDel - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanProfileGet) -_i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAddr, SlSecParams_t* pSecParams, SlGetSecParamsExt_t* pSecExtParams, _u32 *pPriority); -#endif - -/*! - \brief Delete WLAN profile - - Delete WLAN profile - - \param[in] index number of profile to delete.Possible values are 0 to 6. - Index value 255 will delete all saved profiles - - \return On success, zero is returned. On error, -1 is - returned - - \sa sl_WlanProfileAdd , sl_WlanProfileGet - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanProfileDel) -_i16 sl_WlanProfileDel(const _i16 Index); -#endif - -/*! - \brief Set policy values - - \param[in] Type Type of policy to be modified. The Options are:\n - - SL_POLICY_CONNECTION - - SL_POLICY_SCAN - - SL_POLICY_PM - - SL_POLICY_P2P - \param[in] Policy The option value which depends on action type - \param[in] pVal An optional value pointer - \param[in] ValLen An optional value length, in bytes - \return On success, zero is returned. On error, -1 is - returned - \sa sl_WlanPolicyGet - \note belongs to \ref ext_api - \warning - \par - SL_POLICY_CONNECTION type defines three options available to connect the CC31xx device to the AP: \n - - - If Auto Connect is set, the CC31xx device tries to automatically reconnect to one of its stored profiles, each time the connection fails or the device is rebooted.\n - To set this option, use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(1,0,0,0,0),NULL,0) - - If Fast Connect is set, the CC31xx device tries to establish a fast connection to AP. \n - To set this option, use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,1,0,0,0),NULL,0) - - (relevant for P2P mode only) - If Any P2P is set, CC31xx/CC32xx device tries to automatically connect to the first P2P device available, \n - supporting push button only. To set this option, use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,0,0,1,0),NULL,0) - - For auto smart config upon restart (any command from Host will end this state) use: \n - sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(0,0,0,0,1),NULL,0) \n - The options above could be combined to a single action, if more than one action is required. \n - \par - SL_POLICY_SCAN defines system scan time interval.Default interval is 10 minutes. \n - After settings scan interval, an immediate scan is activated. The next scan will be based on the interval settings. \n - - For example, setting scan interval to 1 minute interval use: \n - _u32 intervalInSeconds = 60; \n - #define SL_SCAN_ENABLE 1 \n - sl_WlanPolicySet(SL_POLICY_SCAN,SL_SCAN_ENABLE, (_u8 *)&intervalInSeconds,sizeof(intervalInSeconds)); \n - - - For example, disable scan: \n - #define SL_SCAN_DISABLE 0 \n - sl_WlanPolicySet(SL_POLICY_SCAN,SL_SCAN_DISABLE,0,0); \n - \par - SL_POLICY_PM defines a power management policy for Station mode only: - - For setting normal power management (default) policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_NORMAL_POLICY, NULL,0) - - For setting low latency power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_LOW_LATENCY_POLICY, NULL,0) - - For setting low power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_LOW_POWER_POLICY, NULL,0) - - For setting always on power management policy use: sl_WlanPolicySet(SL_POLICY_PM , SL_ALWAYS_ON_POLICY, NULL,0) - - For setting Long Sleep Interval policy use: \n - _u16 PolicyBuff[4] = {0,0,800,0}; // PolicyBuff[2] is max sleep time in mSec \n - sl_WlanPolicySet(SL_POLICY_PM , SL_LONG_SLEEP_INTERVAL_POLICY, (_u8*)PolicyBuff,sizeof(PolicyBuff)); \n - - SL_POLICY_P2P defines p2p negotiation policy parameters for P2P role: - - To set intent negotiation value, set on of the following: - SL_P2P_ROLE_NEGOTIATE - intent 3 - SL_P2P_ROLE_GROUP_OWNER - intent 15 - SL_P2P_ROLE_CLIENT - intent 0 - - To set negotiation initiator value (initiator policy of first negotiation action frame), set on of the following: - SL_P2P_NEG_INITIATOR_ACTIVE - SL_P2P_NEG_INITIATOR_PASSIVE - SL_P2P_NEG_INITIATOR_RAND_BACKOFF - For example: \n - sl_WlanPolicySet(SL_POLICY_P2P, SL_P2P_POLICY(SL_P2P_ROLE_NEGOTIATE,SL_P2P_NEG_INITIATOR_RAND_BACKOFF),NULL,0) - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanPolicySet) -_i16 sl_WlanPolicySet(const _u8 Type , const _u8 Policy, _u8 *pVal,const _u8 ValLen); -#endif -/*! - \brief get policy values - - \param[in] Type SL_POLICY_CONNECTION, SL_POLICY_SCAN, SL_POLICY_PM,SL_POLICY_P2P \n - - \param[in] Policy argument may be set to any value \n - - \param[out] The returned values, depends on each policy type, will be stored in the allocated buffer pointed by pVal - with a maximum buffer length set by the calling function and pointed to by argument *pValLen - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanPolicySet - - \note belongs to \ref ext_api - - \warning The value pointed by the argument *pValLen should be set to a value different from 0 and - greater than the buffer length returned from the SL device. Otherwise, an error will be returned. - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanPolicyGet) -_i16 sl_WlanPolicyGet(const _u8 Type , _u8 Policy,_u8 *pVal,_u8 *pValLen); -#endif -/*! - \brief Gets the WLAN scan operation results - - Gets scan results , gets entry from scan result table - - \param[in] Index - Starting index identifier (range 0-19) for getting scan results - \param[in] Count - How many entries to fetch. Max is (20-"Index"). - \param[out] pEntries - pointer to an allocated Sl_WlanNetworkEntry_t. - the number of array items should match "Count" - sec_type: SL_SCAN_SEC_TYPE_OPEN, SL_SCAN_SEC_TYPE_WEP, SL_SCAN_SEC_TYPE_WPA or SL_SCAN_SEC_TYPE_WPA2 - - - \return Number of valid networks list items - - \sa - \note belongs to \ref ext_api - \warning This command do not initiate any active scanning action - \par Example: - \code An example of fetching max 10 results: - - Sl_WlanNetworkEntry_t netEntries[10]; - _i16 resultsCount = sl_WlanGetNetworkList(0,10,&netEntries[0]); - for(i=0; i< resultsCount; i++) - { - printf("%s\n",netEntries[i].ssid); - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_WlanGetNetworkList) -_i16 sl_WlanGetNetworkList(const _u8 Index,const _u8 Count, Sl_WlanNetworkEntry_t *pEntries); -#endif - -/*! - \brief Start collecting wlan RX statistics, for unlimited time. - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanRxStatStop sl_WlanRxStatGet - \note belongs to \ref ext_api - \warning - \par Example: - \code Getting wlan RX statistics: - - void RxStatCollectTwice() - { - SlGetRxStatResponse_t rxStat; - _i16 rawSocket; - _i8 DataFrame[200]; - struct SlTimeval_t timeval; - timeval.tv_sec = 0; // Seconds - timeval.tv_usec = 20000; // Microseconds. 10000 microseconds resolution - - sl_WlanRxStatStart(); // set statistics mode - - rawSocket = sl_Socket(SL_AF_RF, SL_SOCK_RAW, eChannel); - // set timeout - in case we have no activity for the specified channel - sl_SetSockOpt(rawSocket,SL_SOL_SOCKET,SL_SO_RCVTIMEO, &timeval, sizeof(timeval)); // Enable receive timeout - status = sl_Recv(rawSocket, DataFrame, sizeof(DataFrame), 0); - - Sleep(1000); // sleep for 1 sec - sl_WlanRxStatGet(&rxStat,0); // statistics has been cleared upon read - Sleep(1000); // sleep for 1 sec - sl_WlanRxStatGet(&rxStat,0); - - } - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStart) -_i16 sl_WlanRxStatStart(void); -#endif - - -/*! - \brief Stop collecting wlan RX statistic, (if previous called sl_WlanRxStatStart) - - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanRxStatStart sl_WlanRxStatGet - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStop) -_i16 sl_WlanRxStatStop(void); -#endif - - -/*! - \brief Get wlan RX statistics. upon calling this command, the statistics counters will be cleared. - - \param[in] Flags should be 0 ( not applicable right now, will be added the future ) - \param[in] pRxStat a pointer to SlGetRxStatResponse_t filled with Rx statistics results - \return On success, zero is returned. On error, -1 is returned - - \sa sl_WlanRxStatStart sl_WlanRxStatStop - \note belongs to \ref ext_api - \warning -*/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatGet) -_i16 sl_WlanRxStatGet(SlGetRxStatResponse_t *pRxStat,const _u32 Flags); -#endif - - -/*! - \brief Stop Smart Config procedure. Once Smart Config will be stopped, - Asynchronous event will be received - SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE. - - \param[in] none - \param[out] none - - \return 0 - if Stop Smart Config is about to be executed without errors. - - \sa sl_WlanSmartConfigStart - \note belongs to \ref ext_api - \warning - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStop) -_i16 sl_WlanSmartConfigStop(void); -#endif - -/*! - \brief Start Smart Config procedure - \par - The target of the procedure is to let the \n - device to gain the network parameters: SSID and Password (if network is secured) \n - and to connect to it once located in the network range. \n - An external application should be used on a device connected to any mobile network. \n - The external application will transmit over the air the network parameters in secured manner.\n - The Password may be decrypted using a Key. \n - The decryption method may be decided in the command or embedded in the Flash. \n - The procedure can be activated for 1-3 group ID in the range of BIT_0 - BIT_15 where the default group ID id 0 (BIT_0) \n - Once Smart Config has ended successfully, Asynchronous event will be received - \n - SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE. \n - The Event will hold the SSID and an extra field that might have been delivered as well (i.e. - device name) - - \param[in] groupIdBitmask - each bit represent a group ID that should be searched. - The Default group ID id BIT_0. 2 more group can be searched - in addition. The range is BIT_0 - BIT_15. - \param[in] chiper - 0: check in flash, 1 - AES, 0xFF - do not check in flash - \param[in] publicKeyLen - public key len (used for the default group ID - BIT_0) - \param[in] group1KeyLen - group ID1 length - \param[in] group2KeyLen - group ID2 length - \param[in] publicKey - public key (used for the default group ID - BIT_0) - \param[in] group1Key - group ID1 key - \param[in] group2Key - group ID2 key - - \param[out] none - - \return 0 - if Smart Config started successfully. - - \sa sl_WlanSmartConfigStop - \note belongs to \ref ext_api - \warning - \par - \code An example of starting smart Config on group ID's 0 + 1 + 2 - - sl_WlanSmartConfigStart(7, //group ID's (BIT_0 | BIT_1 | BIT_2) - 1, //decrypt key by AES method - 16, //decryption key length for group ID0 - 16, //decryption key length for group ID1 - 16, //decryption key length for group ID2 - "Key0Key0Key0Key0", //decryption key for group ID0 - "Key1Key1Key1Key1", //decryption key for group ID1 - "Key2Key2Key2Key2" //decryption key for group ID2 - ); - \endcode -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStart) -_i16 sl_WlanSmartConfigStart(const _u32 groupIdBitmask, - const _u8 cipher, - const _u8 publicKeyLen, - const _u8 group1KeyLen, - const _u8 group2KeyLen, - const _u8* publicKey, - const _u8* group1Key, - const _u8* group2Key); -#endif - - -/*! - \brief Wlan set mode - - Setting WLAN mode - - \param[in] mode - WLAN mode to start the CC31xx device. Possible options are: - - ROLE_STA - for WLAN station mode - - ROLE_AP - for WLAN AP mode - - ROLE_P2P -for WLAN P2P mode - \return 0 - if mode was set correctly - \sa sl_Start sl_Stop - \note belongs to \ref ext_api - \warning After setting the mode the system must be restarted for activating the new mode - \par Example: - \code - //Switch from any role to STA: - sl_WlanSetMode(ROLE_STA); - sl_Stop(0); - sl_Start(NULL,NULL,NULL); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSetMode) -_i16 sl_WlanSetMode(const _u8 mode); -#endif - - -/*! - \brief Internal function for setting WLAN configurations - - \return On success, zero is returned. On error one of the following error codes returned: - - CONF_ERROR (-1) - - CONF_NVMEM_ACCESS_FAILED (-2) - - CONF_OLD_FILE_VERSION (-3) - - CONF_ERROR_NO_SUCH_COUNTRY_CODE (-4) - - - \param[in] ConfigId - configuration id - - SL_WLAN_CFG_AP_ID - - SL_WLAN_CFG_GENERAL_PARAM_ID - - SL_WLAN_CFG_P2P_PARAM_ID - - \param[in] ConfigOpt - configurations option - - SL_WLAN_CFG_AP_ID - - WLAN_AP_OPT_SSID \n - Set SSID for AP mode. \n - This options takes _u8 buffer as parameter - - WLAN_AP_OPT_CHANNEL \n - Set channel for AP mode. \n - The channel is dependant on the country code which is set. i.e. for "US" the channel should be in the range of [1-11] \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_HIDDEN_SSID \n - Set Hidden SSID Mode for AP mode.Hidden options: \n - 0: disabled \n - 1: Send empty (length=0) SSID in beacon and ignore probe request for broadcast SSID \n - 2: Clear SSID (ASCII 0), but keep the original length (this may be required with some \n - clients that do not support empty SSID) and ignore probe requests for broadcast SSID \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_SECURITY_TYPE \n - Set Security type for AP mode. Security options are: - - Open security: SL_SEC_TYPE_OPEN - - WEP security: SL_SEC_TYPE_WEP - - WPA security: SL_SEC_TYPE_WPA_WPA2 \n - This option takes _u8 pointer as a parameter - - WLAN_AP_OPT_PASSWORD \n - Set Password for for AP mode (for WEP or for WPA): \n - Password - for WPA: 8 - 63 characters \n - for WEP: 5 / 13 characters (ascii) \n - This options takes _u8 buffer as parameter - - SL_WLAN_CFG_GENERAL_PARAM_ID - - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS \n - Set scan parameters. - This option uses slWlanScanParamCommand_t as parameter - - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE \n - Set Country Code for AP mode \n - This options takes _u8 2 bytes buffer as parameter - - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER \n - Set STA mode Tx power level \n - Number between 0-15, as dB offset from max power (0 will set MAX power) \n - This options takes _u8 as parameter - - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER - Set AP mode Tx power level \n - Number between 0-15, as dB offset from max power (0 will set MAX power) \n - This options takes _u8 as parameter - - WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT - Set Info Element for AP mode. \n - The Application can set up to MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED info elements per Role (AP / P2P GO). \n - To delete an info element use the relevant index and length = 0. \n - The Application can set up to MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED to the same role. \n - However, for AP - no more than INFO_ELEMENT_MAX_TOTAL_LENGTH_AP bytes can be stored for all info elements. \n - For P2P GO - no more than INFO_ELEMENT_MAX_TOTAL_LENGTH_P2P_GO bytes can be stored for all info elements. \n - This option takes sl_protocol_WlanSetInfoElement_t as parameter - - SL_WLAN_CFG_P2P_PARAM_ID - - WLAN_P2P_OPT_DEV_TYPE \n - Set P2P Device type.Maximum length of 17 characters. Device type is published under P2P I.E, \n - allows to make devices easier to recognize. \n - In case no device type is set, the default type is "1-0050F204-1" \n - This options takes _u8 buffer as parameter - - WLAN_P2P_OPT_CHANNEL_N_REGS \n - Set P2P Channels. \n - listen channel (either 1/6/11 for 2.4GHz) \n - listen regulatory class (81 for 2.4GHz) \n - oper channel (either 1/6/11 for 2.4GHz) \n - oper regulatory class (81 for 2.4GHz) \n - listen channel and regulatory class will determine the device listen channel during p2p find listen phase \n - oper channel and regulatory class will determine the operating channel preferred by this device (in case it is group owner this will be the operating channel) \n - channels should be one of the social channels (1/6/11). In case no listen/oper channel selected, a random 1/6/11 will be selected. - This option takes pointer to _u8[4] as parameter - - \param[in] ConfigLen - configurations len - - \param[in] pValues - configurations values - - \sa - \note - \warning - \par Examples: - \par - WLAN_AP_OPT_SSID: - \code - _u8 str[33]; - memset(str, 0, 33); - memcpy(str, ssid, len); // ssid string of 32 characters - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SSID, strlen(ssid), str); - \endcode - \par - WLAN_AP_OPT_CHANNEL: - \code - _u8 val = channel; - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, (_u8 *)&val); - \endcode - \par - WLAN_AP_OPT_HIDDEN_SSID: - \code - _u8 val = hidden; - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_HIDDEN_SSID, 1, (_u8 *)&val); - \endcode - \par - WLAN_AP_OPT_SECURITY_TYPE: - \code - _u8 val = SL_SEC_TYPE_WPA_WPA2; - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_SECURITY_TYPE, 1, (_u8 *)&val); - \endcode - \par - WLAN_AP_OPT_PASSWORD: - \code - _u8 str[65]; - _u16 len = strlen(password); - memset(str, 0, 65); - memcpy(str, password, len); - sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_PASSWORD, len, (_u8 *)str); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER: - \code - _u8 stapower=(_u8)power; - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_STA_TX_POWER,1,(_u8 *)&stapower); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS: - \code - slWlanScanParamCommand_t ScanParamConfig; - ScanParamConfig.G_Channels_mask = 0x01; // bit mask for channels:1 means channel 1 is enabled, 3 means channels 1 + 2 are enabled - ScanParamConfig.rssiThershold = -70; // only for RSSI level which is higher than -70 - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID ,WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS,sizeof(slWlanScanParamCommand_t),(_u8*)&ScanParamConfig); - \endcode - - \par - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE: - \code - _u8* str = (_u8 *) country; // string of 2 characters. i.e. - "US" - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, str); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER: - \code - _u8 appower=(_u8)power; - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_AP_TX_POWER,1,(_u8 *)&appower); - \endcode - \par - WLAN_P2P_OPT_DEV_TYPE: - \code - _u8 str[17]; - _u16 len = strlen(device_type); - memset(str, 0, 17); - memcpy(str, device_type, len); - sl_WlanSet(SL_WLAN_CFG_P2P_PARAM_ID, WLAN_P2P_OPT_DEV_TYPE, len, str); - \endcode - \par - WLAN_P2P_OPT_CHANNEL_N_REGS: - \code - _u8 str[4]; - str[0] = (_u8)11; // listen channel - str[1] = (_u8)81; // listen regulatory class - str[2] = (_u8)6; // oper channel - str[3] = (_u8)81; // oper regulatory class - sl_WlanSet(SL_WLAN_CFG_P2P_PARAM_ID, WLAN_P2P_OPT_CHANNEL_N_REGS, 4, str); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT: - \code - sl_protocol_WlanSetInfoElement_t infoele; - infoele.index = Index; // Index of the info element. range: 0 - MAX_PRIVATE_INFO_ELEMENTS_SUPPROTED - infoele.role = Role; // INFO_ELEMENT_AP_ROLE (0) or INFO_ELEMENT_P2P_GO_ROLE (1) - infoele.ie.id = Id; // Info element ID. if INFO_ELEMENT_DEFAULT_ID (0) is set, ID will be set to 221. - // Organization unique ID. If all 3 bytes are zero - it will be replaced with 08,00,28. - infoele.ie.oui[0] = Oui0; // Organization unique ID first Byte - infoele.ie.oui[1] = Oui1; // Organization unique ID second Byte - infoele.ie.oui[2] = Oui2; // Organization unique ID third Byte - infoele.ie.length = Len; // Length of the info element. must be smaller than 253 bytes - memset(infoele.ie.data, 0, INFO_ELEMENT_MAX_SIZE); - if ( Len <= INFO_ELEMENT_MAX_SIZE ) - { - memcpy(infoele.ie.data, IE, Len); // Info element. length of the info element is [0-252] - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT,sizeof(sl_protocol_WlanSetInfoElement_t),(_u8* ) &infoele); - } - sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,WLAN_GENERAL_PARAM_OPT_INFO_ELEMENT,sizeof(sl_protocol_WlanSetInfoElement_t),(_u8* ) &infoele); - \endcode - -*/ -#if _SL_INCLUDE_FUNC(sl_WlanSet) -_i16 sl_WlanSet(const _u16 ConfigId ,const _u16 ConfigOpt,const _u16 ConfigLen,const _u8 *pValues); -#endif - -/*! - \brief Internal function for getting WLAN configurations - - \return On success, zero is returned. On error, -1 is - returned - - \param[in] ConfigId - configuration id - - SL_WLAN_CFG_AP_ID - - SL_WLAN_CFG_GENERAL_PARAM_ID - - SL_WLAN_CFG_P2P_PARAM_ID - - \param[out] pConfigOpt - get configurations option - - SL_WLAN_CFG_AP_ID - - WLAN_AP_OPT_SSID \n - Get SSID for AP mode. \n - Get up to 32 characters of SSID \n - This options takes _u8 as parameter - - WLAN_AP_OPT_CHANNEL \n - Get channel for AP mode. \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_HIDDEN_SSID \n - Get Hidden SSID Mode for AP mode.Hidden options: \n - 0: disabled \n - 1: Send empty (length=0) SSID in beacon and ignore probe request for broadcast SSID \n - 2: Clear SSID (ASCII 0), but keep the original length (this may be required with some \n - clients that do not support empty SSID) and ignore probe requests for broadcast SSID \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_SECURITY_TYPE \n - Get Security type for AP mode. Security options are: - - Open security: SL_SEC_TYPE_OPEN - - WEP security: SL_SEC_TYPE_WEP - - WPA security: SL_SEC_TYPE_WPA_WPA2 \n - This option takes _u8 as a parameter - - WLAN_AP_OPT_PASSWORD \n - Get Password for for AP mode (for WEP or for WPA): \n - Returns password - string, fills up to 64 characters. \n - This options takes _u8 buffer as parameter - - SL_WLAN_CFG_GENERAL_PARAM_ID - - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS \n - Get scan parameters. - This option uses slWlanScanParamCommand_t as parameter - - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE \n - Get Country Code for AP mode \n - This options takes _u8 buffer as parameter - - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER \n - Get STA mode Tx power level \n - Number between 0-15, as dB offset from max power (0 indicates MAX power) \n - This options takes _u8 as parameter - - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER - Get AP mode Tx power level \n - Number between 0-15, as dB offset from max power (0 indicates MAX power) \n - This options takes _u8 as parameter - - SL_WLAN_CFG_P2P_PARAM_ID - - WLAN_P2P_OPT_CHANNEL_N_REGS \n - Get P2P Channels. \n - listen channel (either 1/6/11 for 2.4GHz) \n - listen regulatory class (81 for 2.4GHz) \n - oper channel (either 1/6/11 for 2.4GHz) \n - oper regulatory class (81 for 2.4GHz) \n - listen channel and regulatory class will determine the device listen channel during p2p find listen phase \n - oper channel and regulatory class will determine the operating channel preferred by this device (in case it is group owner this will be the operating channel) \n - channels should be one of the social channels (1/6/11). In case no listen/oper channel selected, a random 1/6/11 will be selected. \n - This option takes pointer to _u8[4] as parameter - - \param[out] pConfigLen - The length of the allocated memory as input, when the - function complete, the value of this parameter would be - the len that actually read from the device. - If the device return length that is longer from the input - value, the function will cut the end of the returned structure - and will return SL_ESMALLBUF. - - - \param[out] pValues - get configurations values - - \sa sl_WlanSet - - \note - - \warning - - \par Examples: - \par - WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS: - \code - slWlanScanParamCommand_t ScanParamConfig; - _u16 Option = WLAN_GENERAL_PARAM_OPT_SCAN_PARAMS; - _u16 OptionLen = sizeof(slWlanScanParamCommand_t); - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&ScanParamConfig); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_AP_TX_POWER: - \code - _i8 TXPower = 0; - _u16 Option = WLAN_GENERAL_PARAM_OPT_AP_TX_POWER; - _u16 OptionLen = sizeof(_i8); - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&TXPower); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_STA_TX_POWER: - \code - _i8 TXPower = 0; - _u16 Option = WLAN_GENERAL_PARAM_OPT_STA_TX_POWER; - _u16 OptionLen = sizeof(_i8); - - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID ,&Option,&OptionLen,(_u8 *)&TXPower); - \endcode - \par - WLAN_P2P_OPT_DEV_TYPE: - \code - _i8 device_type[18]; - _u16 len = 18; - _u16 config_opt = WLAN_P2P_OPT_DEV_TYPE; - sl_WlanGet(SL_WLAN_CFG_P2P_PARAM_ID, &config_opt , &len, (_u8* )device_type); - \endcode - \par - WLAN_AP_OPT_SSID: - \code - _i8 ssid[32]; - _u16 len = 32; - _u16 config_opt = WLAN_AP_OPT_SSID; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt , &len, (_u8* )ssid); - \endcode - \par - WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE: - \code - _i8 country[3]; - _u16 len = 3; - _u16 config_opt = WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE; - sl_WlanGet(SL_WLAN_CFG_GENERAL_PARAM_ID, &config_opt, &len, (_u8* )country); - \endcode - \par - WLAN_AP_OPT_CHANNEL: - \code - _i8 channel; - _u16 len = 1; - _u16 config_opt = WLAN_AP_OPT_CHANNEL; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&channel); - \endcode - \par - WLAN_AP_OPT_HIDDEN_SSID: - \code - _u8 hidden; - _u16 len = 1; - _u16 config_opt = WLAN_AP_OPT_HIDDEN_SSID; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&hidden); - \endcode - \par - WLAN_AP_OPT_SECURITY_TYPE: - \code - _u8 sec_type; - _u16 len = 1; - _u16 config_opt = WLAN_AP_OPT_SECURITY_TYPE; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )&sec_type); - \endcode - \par - WLAN_AP_OPT_PASSWORD: - \code - _u8 password[64]; - _u16 len = 64; - memset(password,0,64); - _u16 config_opt = WLAN_AP_OPT_PASSWORD; - sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt, &len, (_u8* )password); - - \endcode - \par - WLAN_P2P_OPT_CHANNEL_N_REGS: - \code - _u16 listen_channel,listen_reg,oper_channel,oper_reg; - _u16 len = 4; - _u16 config_opt = WLAN_P2P_OPT_CHANNEL_N_REGS; - _u8 channel_n_regs[4]; - sl_WlanGet(SL_WLAN_CFG_P2P_PARAM_ID, &config_opt, &len, (_u8* )channel_n_regs); - listen_channel = channel_n_regs[0]; - listen_reg = channel_n_regs[1]; - oper_channel = channel_n_regs[2]; - oper_reg = channel_n_regs[3]; - \endcode -*/ - -#if _SL_INCLUDE_FUNC(sl_WlanGet) -_i16 sl_WlanGet(const _u16 ConfigId, _u16 *pConfigOpt,_u16 *pConfigLen, _u8 *pValues); -#endif -/*! - - Close the Doxygen group. - @} - - */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __WLAN_H__ */ - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/wlan_rx_filters.h b/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/wlan_rx_filters.h deleted file mode 100644 index 8bd712f0..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/inc/wlan_rx_filters.h +++ /dev/null @@ -1,932 +0,0 @@ -/* - * wlan_rx_filters.h - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - -#ifndef RX_FILTERS_PREPROCESSOR_CLI_IF_H_ -#define RX_FILTERS_PREPROCESSOR_CLI_IF_H_ - - - -#ifdef __cplusplus -extern "C" { -#endif - - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -/*! - * \def SL_RX_FILTER_MAX_FILTERS - * The Max number of filters for 64 filters - */ -#define SL_RX_FILTER_MAX_FILTERS 64 - -/*! - * \def SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS - * The Max number of software filters - */ -#define SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS (32) -/*! - * \def SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS (2) -/*! - * \def SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS (2) -/*! - * \def SL_RX_FILTER_NUM_OF_FILTER_PAYLOAD_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_COMBINATION_TYPE_ARGS (2) -/*! - * \def SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH - * - */ -#define SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH (32) - - -/* List of possible error numbers */ -#define RXFL_OK (0) /* O.K */ -#define RXFL_OUTPUT_OR_INPUT_BUFFER_LENGTH_TOO_SMALL (76) /* ! The output buffer length is smaller than required for that operation */ -#define RXFL_DEPENDENT_FILTER_SOFTWARE_FILTER_NOT_FIT (75) /* Node filter can't be child of software filter and vice_versa */ -#define RXFL_DEPENDENCY_IS_NOT_PERSISTENT (74) /* Dependency filter is not persistent */ -#define RXFL_SYSTEM_STATE_NOT_SUPPORTED_FOR_THIS_FILTER (72) /* System state is not supported */ -#define RXFL_TRIGGER_USE_REG5_TO_REG8 (71) /* Only counters 5 - 8 are allowed, for Tigger */ -#define RXFL_TRIGGER_USE_REG1_TO_REG4 (70) /* Only counters 1 - 4 are allowed, for trigger */ -#define RXFL_ACTION_USE_REG5_TO_REG8 (69) /* Only counters 5 - 8 are allowed, for action */ -#define RXFL_ACTION_USE_REG1_TO_REG4 (68) /* Only counters 1 - 4 are allowed, for action */ -#define RXFL_FIELD_SUPPORT_ONLY_EQUAL_AND_NOTEQUAL (67) /* Rule compare function Id is out of range */ -#define RXFL_WRONG_MULTICAST_BROADCAST_ADDRESS (66) /* The address should be of type mutlicast or broadcast */ -#define RXFL_THE_FILTER_IS_NOT_OF_HEADER_TYPE (65) /* The filter should be of header type */ -#define RXFL_WRONG_COMPARE_FUNC_FOR_BROADCAST_ADDRESS (64) /* The compare funcion is not suitable for broadcast address */ -#define RXFL_WRONG_MULTICAST_ADDRESS (63) /* The address should be of muticast type */ -#define RXFL_DEPENDENT_FILTER_IS_NOT_PERSISTENT (62) /* The dependency filter is not persistent */ -#define RXFL_DEPENDENT_FILTER_IS_NOT_ENABLED (61) /* The dependency filter is not enabled */ -#define RXFL_FILTER_HAS_CHILDS (60) /* The filter has childs and can't be removed */ -#define RXFL_CHILD_IS_ENABLED (59) /* Can't disable filter while the child is enabled */ -#define RXFL_DEPENDENCY_IS_DISABLED (58) /* Can't enable filetr in case its depndency filter is disabled */ -#define RXFL_NUMBER_OF_CONNECTION_POINTS_EXCEEDED (52) /* Number of connection points exceeded */ -#define RXFL_DEPENDENT_FILTER_DEPENDENCY_ACTION_IS_DROP (51) /* The dependent filter has Drop action, thus the filter can't be created */ -#define RXFL_FILTER_DO_NOT_EXISTS (50) /* The filter doesn't exists */ -#define RXFL_DEPEDENCY_NOT_ON_THE_SAME_LAYER (49) /* The filter and its dependency must be on the same layer */ -#define RXFL_NUMBER_OF_ARGS_EXCEEDED (48) /* Number of arguments excceded */ -#define RXFL_ACTION_NO_REG_NUMBER (47) /* Action require counter number */ -#define RXFL_DEPENDENT_FILTER_LAYER_DO_NOT_FIT (46) /* the filter and its dependency should be from the same layer */ -#define RXFL_DEPENDENT_FILTER_SYSTEM_STATE_DO_NOT_FIT (45) /* The filter and its dependency system state don't fit */ -#define RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_2 (44) /* The parent filter don't exist */ -#define RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_1 (43) /* The parent filter is null */ -#define RXFL_RULE_HEADER_ACTION_TYPE_NOT_SUPPORTED (42) /* The action type is not supported */ -#define RXFL_RULE_HEADER_TRIGGER_COMPARE_FUNC_OUT_OF_RANGE (41) /* The Trigger comparision function is out of range */ -#define RXFL_RULE_HEADER_TRIGGER_OUT_OF_RANGE (40) /* The Trigger is out of range */ -#define RXFL_RULE_HEADER_COMPARE_FUNC_OUT_OF_RANGE (39) /* The rule compare function is out of range */ -#define RXFL_FRAME_TYPE_NOT_SUPPORTED (38) /* ASCII frame type string is illegal */ -#define RXFL_RULE_FIELD_ID_NOT_SUPPORTED (37) /* Rule field ID is out of range */ -#define RXFL_RULE_HEADER_FIELD_ID_ASCII_NOT_SUPPORTED (36) /* This ASCII field ID is not supported */ -#define RXFL_RULE_HEADER_NOT_SUPPORTED (35) /* The header rule is not supported on current release */ -#define RXFL_RULE_HEADER_OUT_OF_RANGE (34) /* The header rule is out of range */ -#define RXFL_RULE_HEADER_COMBINATION_OPERATOR_OUT_OF_RANGE (33) /* Combination function Id is out of ramge */ -#define RXFL_RULE_HEADER_FIELD_ID_OUT_OF_RANGE (32) /* rule field Id is out of range */ -#define RXFL_UPDATE_NOT_SUPPORTED (31) /* Update not supported */ -#define RXFL_NO_FILTERS_ARE_DEFINED (24) /* No filters are defined in the system */ -#define RXFL_NUMBER_OF_FILTER_EXCEEDED (23) /* Number of max filters excceded */ - - -/******************************************************************************/ -/* Type declarations */ -/******************************************************************************/ - -/*! - - - * \typedef SlrxFilterID_t - * Unique filter ID which is allocated by the system , negative number means error - */ -typedef _i8 SlrxFilterID_t; - - -/*! - * \typedef SlrxFilterCompareMask_t - * The mask is used for the rule comparison function - */ -typedef _u8 SlrxFilterCompareMask_t; - -/*! - * \typedef SlrxFilterIdMask_t - * Representation of filters Id as a bit field - * The bit field is used to declare which filters are involved - * in operation. Number of filter can be up to 128 filters. i.e. 128 bits are needed. - * On the current release, up to 64 filters can be defined. - */ -typedef _u8 SlrxFilterIdMask_t[128/8]; - -/*! - * \typedef SlrxFilterPrePreparedFilters_t - * Describes the supported software filter sets, - */ -typedef _u8 SlrxFilterPrePreparedFilters_t; -#define SL_ARP_AUTO_REPLY_PRE_PREPARED_FILTERS (0) -#define SL_MULTICASTSIPV4_DROP_PREPREPARED_FILTERS (1) -#define SL_MULTICASTSIPV6_DROP_PREPREPARED_FILTERS (2) -#define SL_MULTICASTSWIFI_DROP_PREPREPARED_FILTERS (3) - - - -/*! - * \typedef SlrxFilterPrePreparedFiltersMask_t - * Describes the supported software filter sets, - * each bit represents different software filter set - * The filter sets are defined at SlrxFilterPrePreparedFilters_t - */ -typedef _u8 SlrxFilterPrePreparedFiltersMask_t[SL_RX_FILTER_MAX_PRE_PREPARED_FILTERS_SETS/8]; - - -/*! \typedef SlrxFilterRegxPattern_t - * The struct contains the regular expression pattern which is used in case of payload rule. - * Not supported in the current release - */ -typedef struct SlrxFilterRegxPattern_t -{ - _u8 x[SL_RX_FILTER_LENGTH_OF_REGX_PATTERN_LENGTH]; -}SlrxFilterRegxPattern_t; - - -/*! \typedef SlrxFilterAsciiArg_t - * The buffer is used to provide container for ASCII argument, which may be used in case of HEADER rule. - * example for ASCII argument can be : IP = 256.0.67.1 - */ -typedef _u8 SlrxFilterAsciiArg_t; - - -/*! \typedef SlrxFilterBinaryArg_t - * The buffer provides container for binary argument, which may be used in case of HEADER rule - */ -typedef _u8 SlrxFilterBinaryArg_t ; - - -/*! \typedef SlrxFilterActionArg_t - * Provides container for the filter action argument. - * for example: in case action is to send automatic response , the argument is the template to be used for the automatic response. - * - * - */ -typedef _u8 SlrxFilterActionArg_t ; - - - -/*! \typedef SlrxFilterOffset_t - * The offset relative to the packet payload start location. - * Not supported on current release - */ -typedef _u32 SlrxFilterOffset_t; - - - -/*! \typedef SlrxFilterRuleType_t - * Enumerates the different filter types. - * On the current release only HEADER and COMBINATION are supported. - */ -typedef _u8 SlrxFilterRuleType_t; -/* possible values for SlrxFilterRuleType_t */ -#define HEADER (0) -#define COMBINATION (1) -#define EXACT_PATTERN (2) -#define LIKELIHOOD_PATTERN (3) -#define ALWAYS_TRUE (4) -#define NUM_OF_FILTER_TYPES (5) - - -/*! \typedef SlrxFilterFlags_t - * Bit field which sets the behaviour of the RX filter - * - */ - -#define RX_FILTER_BINARY (0x1) -#define RX_FILTER_PERSISTENT (0x8) -#define RX_FILTER_ENABLE (0x10) - -typedef union SlrxFilterFlags_t -{ - - /* struct - { */ - /*! - * The filter argument can be set as binary argument or ASCII arguments. - * When the bit is on the argument are binary. - */ - /* _u8 Binary: 1; */ - /*! - * - */ - /* _u8 AutoSort : 1; */ - /*! - * - */ - /* _u8 AutoFaultDetect : 1; */ - /*! - * When the bit is on it means the the node is enabled . - */ - /* _u8 Enabled : 1; */ - /* _u8 padding : 3; */ - /* - };*/ - - _u8 IntRepresentation; - -}SlrxFilterFlags_t; - -/*! \typedef SlrxFilterCompareFunction_t - * Used as comparison function for the header type arguments - * - */ -typedef _u8 SlrxFilterCompareFunction_t; -/* Possible values for SlrxFilterCompareFunction_t */ -#define COMPARE_FUNC_IN_BETWEEN (0) -#define COMPARE_FUNC_EQUAL (1) -#define COMPARE_FUNC_NOT_EQUAL_TO (2) -#define COMPARE_FUNC_NOT_IN_BETWEEN (3) -#define COMPARE_FUNC_NUM_OF_FILTER_COMPARE_FUNC (4) - -/*! \typedef SlrxFilterCompareFunction_t - * Used as comparison function for the header type arguments - * - */ -typedef _u8 SlrxTriggerCompareFunction_t; -/* Possible values for SlrxTriggerCompareFunction_t */ -#define TRIGGER_COMPARE_FUNC_EQUAL (0) -/* arg1 == protocolVal ,not supported in current release */ -#define TRIGGER_COMPARE_FUNC_NOT_EQUAL_TO (1) -/* arg1 == protocolVal */ -#define TRIGGER_COMPARE_FUNC_SMALLER_THAN (2) -/* arg1 == protocolVal */ -#define TRIGGER_COMPARE_FUNC_BIGGER_THAN (3) -/* definition */ -#define TRIGGER_COMPARE_FUNC_NUM_OF_FILTER_COMPARE_FUNC (4) - - -/*! \typedef SlrxFilterHdrField_t - * Provides list of possible header types which may be defined as part of the rule - * - */ -typedef _u8 SlrxFilterHdrField_t; -/* Possible values for SlrxFilterHdrField_t */ -#define NULL_FIELD_ID_TYPE (0) -/* 802.11 control\data\management */ -#define FRAME_TYPE_FIELD (1) -/* 802.11 beacon\probe\.. */ -#define FRAME_SUBTYPE_FIELD (2) - /* 802.11 bssid type */ -#define BSSID_FIELD (3) - /* */ -#define MAC_SRC_ADDRESS_FIELD (4) - /* */ -#define MAC_DST_ADDRESS_FIELD (5) -/* */ -#define FRAME_LENGTH_FIELD (6) -/* */ -#define PROTOCOL_TYPE_FIELD (7) - /* */ -#define IP_VERSION_FIELD (8) - /* TCP / UDP */ -#define IP_PROTOCOL_FIELD (9) - /* */ -#define IPV4_SRC_ADRRESS_FIELD (10) -/* */ -#define IPV4_DST_ADDRESS_FIELD (11) -/* */ -#define IPV6_SRC_ADRRESS_FIELD (12) -/* */ -#define IPV6_DST_ADDRESS_FIELD (13) - /* */ -#define SRC_PORT_FIELD (14) - /* */ -#define DST_PORT_FIELD (15) - /* Definition */ -#define NUM_OF_FIELD_NAME_FIELD (16) - -/*! \union SlrxFilterHeaderArg_t - * The structure holds the header ARGS which are used in case of HDR rule. - */ -/* -- 36 bytes */ -typedef union SlrxFilterHeaderArg_t -{ - /*----------------------------- Large size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * example : IPV6 16 bytes, 39 characters - * ipv6 Ascii address: 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 - */ - - SlrxFilterBinaryArg_t RxFilterDB16BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][16 ]; /* Binary Values for comparition */ - /*! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * example : IPV6 16 bytes, 39 characters - * ipv6 Ascii address: 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 - * Ascii format for ipV6 is not supported - */ - /*----------------------------- Medium size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * MAC address: 6 bytes, 17 chars - */ - SlrxFilterBinaryArg_t RxFilterDB6BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][6]; /* Binary Values for comparition */ - /*! - * ! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * IP address: 4 bytes, 15 chars - * 2 bytes are added for padding - */ - SlrxFilterAsciiArg_t RxFilterDB18BytesAsciiRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][18]; /* Ascii Values for comparison */ - /*----------------------------- Small size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * IP address: 4 bytes, 15 chars - * Port: 2 bytes, chars: 5 chars - */ - SlrxFilterBinaryArg_t RxFilterDB4BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][4]; /* Binary Values for comparison */ - /*! buffer for ASCII arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - * Port: 2 bytes, chars: 5 chars - */ - SlrxFilterAsciiArg_t RxFilterDB5BytesRuleAsciiArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][5]; /* Ascii Values for comparison */ - /*----------------------------- 1 byte size ---------------------------------*/ - /*! buffer for binary arguments, number of argument may be up to SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS - */ - SlrxFilterBinaryArg_t RxFilterDB1BytesRuleArgs[SL_RX_FILTER_NUM_OF_FILTER_HEADER_ARGS][1]; /* Binary Values for comparison */ -}SlrxFilterHeaderArg_t; - - - -/*! \typedef SlrxFilterRuleHeaderArgsAndMask_t - * Structure which defines the Header Args and mask - */ -/* -- 52 bytes */ -typedef struct SlrxFilterRuleHeaderArgsAndMask_t -{ - /*! Argument for the comparison function */ - /* -- 36 byte */ - SlrxFilterHeaderArg_t RuleHeaderArgs; - - /*! the mask is used in order to enable partial comparison, - * Use the 0xFFFFFFFF in case you don't want to use mask - */ - /* -- 16 bytes */ - SlrxFilterCompareMask_t RuleHeaderArgsMask[16]; - -}SlrxFilterRuleHeaderArgsAndMask_t; - -/*! \typedef SlrxFilterHeaderType_t - * Structure which defines the Header rule - * The header rule defines compare function on the protocol header - * For example destMacAddre is between ( 12:6::78:77, 12:6::78:90 ) - * - */ -/* -- 56 byte */ -typedef struct SlrxFilterHeaderType_t -{ - /*! see :: SlrxFilterRuleHeaderArgsAndMask_t */ - /* -- 52 bytes */ - SlrxFilterRuleHeaderArgsAndMask_t RuleHeaderArgsAndMask; - - /*! Packet HDR field which will be compared to the argument */ - /* -- 1 byte */ - SlrxFilterHdrField_t RuleHeaderfield; - - /* -- 1 byte */ - /*! type of the comparison function - * see :: SlrxFilterCompareFunction_t - */ - SlrxFilterCompareFunction_t RuleCompareFunc; - - /*! padding */ - /* -- 2 bytes */ - _u8 RulePadding[2]; - -}SlrxFilterHeaderType_t; - -/*! \typedef SlrxFilterPayloadType_t - * Structure which defines payload rule. - * Not supported on current release. - */ -/* -- 40 byte */ -typedef struct SlrxFilterPayloadType_t -{ - /*! Not supported on current release */ - /* -- 32 byte */ - SlrxFilterRegxPattern_t RegxPattern; - /*! Not supported on current release */ - /* -- 4 byte */ - SlrxFilterOffset_t LowerOffset; - /*! Not supported on current release */ - /* -- 4 byte */ - SlrxFilterOffset_t UpperOffset; -}SlrxFilterPayloadType_t; - -/*! \typedef SlrxFilterCombinationTypeOperator_t - * Enumerate the optional operators for the combination type - * filterID1 is located in the first arg , filterId2 is the second arg,see ::SlrxFilterCombinationType_t.CombinationFilterId - */ -typedef _u8 SlrxFilterCombinationTypeOperator_t; -/* Possible values for SlrxFilterCombinationTypeOperator_t */ -/*! !filterID1 */ -#define COMBINED_FUNC_NOT (0) -/*! filterID1 && filterID2 */ -#define COMBINED_FUNC_AND (1) -/*! filterID1 && filterID2 */ -#define COMBINED_FUNC_OR (2) - -/*! \typedef SlrxFilterCombinationType_t - * Defines the structure which define the combination type filter - * The combined filter enable to make operation on one or two filter, - * for example !filterId1 or and(filterId2,filterId3). - * - */ -/* -- 4 byte */ -typedef struct SlrxFilterCombinationType_t -{ - /* ! combination operator */ - /* -- 1 byte */ - SlrxFilterCombinationTypeOperator_t CombinationTypeOperator; - /* ! filterID, may be one or two depends on the combination operator type */ - /* -- 2 byte */ - SlrxFilterID_t CombinationFilterId[SL_RX_FILTER_NUM_OF_COMBINATION_TYPE_ARGS]; - /* ! Padding */ - /* -- 1 byte */ - _u8 Padding; -}SlrxFilterCombinationType_t; - - -/*! \typedef SlrxFilterRule_t - * Rule structure composed of behavioral flags and the filter rule definitions - * - */ -/* -- 56 byte */ -typedef union SlrxFilterRule_t -{ - /* ! Header type rule , see explanation on the ::SlrxFilterHeaderType_t structure */ - /* -- 56 byte */ - SlrxFilterHeaderType_t HeaderType; - /* ! Payload rule, not supported in current release */ - /* -- 40 byte */ - SlrxFilterPayloadType_t PayLoadHeaderType; /* future for exact pattern or like hood pattern */ - /* ! Combined type rule , see explanation in ::SlrxFilterCombinationType_t structure */ - /* -- 4 byte */ - SlrxFilterCombinationType_t CombinationType; -}SlrxFilterRule_t; - -/*! \typedef SlrxFilterTriggerRoles_t - * Bit field which represents the roleId possible values - * In the current release only Station/AP roles are supported. - */ -#define RX_FILTER_ROLE_AP (1) -#define RX_FILTER_ROLE_STA (2) -#define RX_FILTER_ROLE_PROMISCUOUS (4) -#define RX_FILTER_ROLE_NULL (0) - -typedef union SlrxFilterTriggerRoles_t -{ -/* struct */ -/* { */ -/* _u8 RoleAP :1; */ -/* _u8 RoleStation :1; */ - /* The filter is activated only in Promiscuous mode */ -/* _u8 PromiscuousMode :1; */ -/* _u8 RoleReserved :5; */ -/* }; */ - /* ! Bit fiels of the Filter role */ - _u8 IntRepresentation; - -}SlrxFilterTriggerRoles_t; - -/*! \typedef SlrxFilterTriggerConnectionStates_t - * Bit field representing the possible values of the When section of the rule - * - */ -#define RX_FILTER_CONNECTION_STATE_STA_CONNECTED (1) -#define RX_FILTER_CONNECTION_STATE_STA_NOT_CONNECTED (2) -#define RX_FILTER_CONNECTION_STATE_STA_HAS_IP (4) -#define RX_FILTER_CONNECTION_STATE_STA_HAS_NO_IP (8) - -typedef union SlrxFilterTriggerConnectionStates_t -{ -/* struct */ -/* { */ -/* _u8 RoleStationWiFiConnected :1; */ -/* _u8 RoleStationWiFiDisconneted:1; */ -/* _u8 RoleStationWiFiHasIp:1; */ -/* _u8 RoleStationWiFiHasNoIp:1; */ -/* _u8 RoleStationWiFiSocketOpened:1; */ -/* _u8 RoleStationWiFiSocketclosed:1; */ -/* }; */ -/* */ - /* ! */ - _u8 IntRepresentation; - -}SlrxFilterTriggerConnectionStates_t; - -/*! \typedef SlrxFilterDBTriggerArg_t - * Provides container for entering the filter 'when' argument. - * The current release support 'When rules' which has no arguments. - * For example : - * When connect to specific AP -- the AP bssid is the argument. - * - */ -typedef _u32 SlrxFilterDBTriggerArg_t; - - - -/*! \typedef SlrxFilterCounterId_t - * the counter ID we have 4 counters - */ -typedef _u8 SlrxFilterCounterId_t; -/* Possible values for SlrxFilterCounterId_t */ -#define NO_TRIGGER (0) -#define RX_FILTER_COUNTER1 (1) -#define RX_FILTER_COUNTER2 (2) -#define RX_FILTER_COUNTER3 (3) -#define RX_FILTER_COUNTER4 (4) -#define RX_FILTER_COUNTER5 (5) -#define RX_FILTER_COUNTER6 (6) -#define RX_FILTER_COUNTER7 (7) -#define RX_FILTER_COUNTER8 (8) -#define MAX_RX_FILTER_COUNTER (9) - - - -/*! \typedef SlrxFilterActionArgs_t - * Possible value for filter action args - * - */ - -typedef _u8 SlrxFilterActionArgs_t; -/* Possible values for SlrxFilterActionArgs_t */ -#define ACTION_ARG_REG_1_4 (0) - /* ! Can be use as counter */ -#define ACTION_ARG_TEMPLATE (1) - /* ! Can be use as counter */ -#define ACTION_ARG_EVENT (2) - -/* ! GPIO number */ -#define ACTION_ARG_GPIO (4) -/*! - * \def SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS - * - */ -#define SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS (5) - - - - -/*! \typedef SlrxFilterTrigger_t - * The filter trigger, determine when the filter is triggered, - * The filter is triggered in the following condition :\n - * 1. The filter parent is triggered\n - * 2. The requested connection type exists, i.e. wlan_connect\n - * 3. The filter role is the same as the system role\n - * - */ -/* -- 12 byte */ -typedef struct SlrxFilterTrigger_t -{ - /*! The parent filter ID, this is the way to build filter tree. */ - /* NULL value means tree root. - */ - /* -- 1 byte */ - SlrxFilterID_t ParentFilterID; - /* ! See ::SlrxFilterCounterId_t explanation */ - /* -- 1 byte */ - SlrxFilterCounterId_t Trigger; - /* ! See :: SlrxFilterTriggerConnectionStates_t */ - /* -- 1 byte */ - SlrxFilterTriggerConnectionStates_t TriggerArgConnectionState; - /* ! See ::SlrxFilterTriggerRoles_t */ - /* -- 1 byte */ - SlrxFilterTriggerRoles_t TriggerArgRoleStatus; - /* ! The Trigger arguments are in the same order as the Trigger bit field order. */ - /* -- 4 byte */ - SlrxFilterDBTriggerArg_t TriggerArg; - /** The compare function which will be operate for each bit that is turned on in the ::SlrxFilterTrigger_t.Trigger field, - * for example , in case the second bit in the Trigger function is on the second function in the list will be executed. - * - */ - /* -- 1 byte */ - SlrxTriggerCompareFunction_t TriggerCompareFunction; - - /* ! padding */ - /* -- 3 byte */ - _u8 Padding[3]; -} SlrxFilterTrigger_t; - -/*! \typedef SlrxFilterActionType_t - * The actions are executed only if the filter is matched,\n - * In case of false match the packet is transfered to the HOST. \n - * The action is composed of bit field structure, - * up to 2 actions can be defined per filter. - * - */ -#define RX_FILTER_ACTION_NULL (0x0) -#define RX_FILTER_ACTION_DROP (0x1) -#define RX_FILTER_ACTION_GPIO (0x2) -#define RX_FILTER_ACTION_ON_REG_INCREASE (0x4) -#define RX_FILTER_ACTION_ON_REG_DECREASE (0x8) -#define RX_FILTER_ACTION_ON_REG_RESET (0x10) -#define RX_FILTER_ACTION_SEND_TEMPLATE (0x20) /* unsupported */ -#define RX_FILTER_ACTION_EVENT_TO_HOST (0x40) /* unsupported */ - -typedef union SlrxFilterActionType_t -{ -/* struct */ -/* { */ - /* ! No action to execute the packet is dropped,drop is always on leaf. */ - /* ! If not dropped ,The packet is passed to the next filter or in case it is the last filter to the host */ -/* _u8 ActionDrop : 1; */ - /* ! Not Supported in the current release */ -/* _u8 ActionGpio : 1; */ - /*! action can increase counter registers. - * 1 = Increase - * 2 = decrease - * 3 = reset - */ -/* _u8 ActionOnREGIncrease : 1; */ -/* _u8 ActionOnREGDecrease : 1; */ -/* _u8 ActionOnREGReset : 1; */ - - /* ! Not Supported in the current release */ -/* _u8 ActionSendTemplate : 1; */ - /* ! Not Supported in the current release */ -/* _u8 ActionEventToHost: 1; */ -/* _u8 padding: 1; */ -/* }; */ - - _u8 IntRepresentation; - -}SlrxFilterActionType_t; - -/*! \typedef SlrxFilterAction_t - * Several actions can be defined,\n - * The action is executed in case the filter rule is matched. - */ -/* -- 8 byte */ -typedef struct SlrxFilterAction_t -{ - /* -- 1 byte */ - /* ! Determine which actions are supported */ - SlrxFilterActionType_t ActionType; - /* ! Buffer for the action arguments */ - /** - * location 0 - The counter to increase - * In case the action is of type "increase" the arg will contain the counter number, - * The counter number values are as in ::SlrxFilterCounterId_t.\n - * location 1 - The template arg.\n - * location 2 - The event arg.\n - * - */ - /* -- 5 byte */ - SlrxFilterActionArg_t ActionArg[SL_RX_FILTER_NUM_OF_BYTES_FOR_ACTIONS_ARGS]; - - /* ! Padding */ - /* - 2 Bytes */ - _u8 Padding[2]; - -} SlrxFilterAction_t; - - -/*! \struct _WlanRxFilterOperationCommandBuff_t - * The structure is used for the interface HOST NWP.\n - * The supported operation : \n - * ::ENABLE_DISABLE_RX_FILTER,\n - * ::REMOVE_RX_FILTER,\n - * - */ -/* 20 bytes */ -typedef struct _WlanRxFilterOperationCommandBuff_t -{ - /* -- 16 bytes */ - SlrxFilterIdMask_t FilterIdMask; - /* 4 bytes */ - _u8 Padding[4]; -}_WlanRxFilterOperationCommandBuff_t; - - - -/* -- 56 bytes */ -typedef struct _WlanRxFilterUpdateArgsCommandBuff_t -{ - /* -- 1 bytes */ - _u8 FilterId; - - /* -- 1 bytes */ - /* ! the args representation */ - _u8 BinaryRepresentation; - - /* -- 52 byte */ - SlrxFilterRuleHeaderArgsAndMask_t FilterRuleHeaderArgsAndMask; - - /* -- 2 bytes */ - _u8 Padding[2]; -}_WlanRxFilterUpdateArgsCommandBuff_t; - - -/*! \typedef _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t - * The structure is used for the interface HOST NWP.\n - * - */ -/* -- 16 bytes */ -typedef struct _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t -{ - - /* ! the filter set bit map */ - /* -- 16 bytes */ - SlrxFilterIdMask_t FilterIdMask; - -}_WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t; - - -/*! \struct _WlanRxFilterPrePreparedFiltersCommandBuff_t - * The function enables to perform operations on pre-prepared filters - * - */ -typedef struct _WlanRxFilterPrePreparedFiltersCommandBuff_t -{ - /* ! the filter set bit map */ - /* -- 4 bytes */ - SlrxFilterPrePreparedFiltersMask_t FilterPrePreparedFiltersMask; - -}_WlanRxFilterPrePreparedFiltersCommandBuff_t; - - -/*! \typedef sl_protocol_WlanRxFilterPrePreparedFiltersCommandResponseBuff_t - * - */ -/*-- 4 bytes */ -typedef struct _WlanRxFilterPrePreparedFiltersCommandResponseBuff_t -{ - /* -- 4 bytes */ - /* ! the filter set bit map */ - SlrxFilterPrePreparedFiltersMask_t FilterPrePreparedFiltersMask; - -}_WlanRxFilterPrePreparedFiltersCommandResponseBuff_t; - - - -typedef _u8 SLrxFilterOperation_t; -#define SL_ENABLE_DISABLE_RX_FILTER (0) -#define SL_REMOVE_RX_FILTER (1) -#define SL_STORE_RX_FILTERS (2) -#define SL_UPDATE_RX_FILTER_ARGS (3) -#define SL_FILTER_RETRIEVE_ENABLE_STATE (4) -#define SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE (5) -#define SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE (6) - - -/* Bit manipulation for 8 bit */ -#define ISBITSET8(x,i) ((x[i>>3] & (0x80>>(i&7)))!=0) /* < Is bit set, 8 bit unsigned numbers = x , location = i */ -#define SETBIT8(x,i) x[i>>3]|=(0x80>>(i&7)); /* < Set bit,8 bit unsigned numbers = x , location = i */ -#define CLEARBIT8(x,i) x[i>>3]&=(0x80>>(i&7))^0xFF; /* < Clear bit,8 bit unsigned numbers = x , location = i */ - - -/*********************************************************************************************/ -/* Function prototypes */ -/*********************************************************************************************/ - -/*! - - \addtogroup wlan - @{ - -*/ - - -/*! - \brief Adds new filter rule to the system - - \param[in] RuleType The rule type - \param[in] FilterFlags Flags which set the type of header rule Args and sets the persistent flag - \param[in] pRule Determine the filter rule logic - \param[in] pTrigger Determine when the rule is triggered also sets rule parent. - \param[in] pAction Sets the action to be executed in case the match functions pass - \param[out] pFilterId The filterId which was created - - \return On success, zero is returned. Otherwise error code is returned - */ -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterAdd) -SlrxFilterID_t sl_WlanRxFilterAdd( SlrxFilterRuleType_t RuleType, - SlrxFilterFlags_t FilterFlags, - const SlrxFilterRule_t* const Rule, - const SlrxFilterTrigger_t* const Trigger, - const SlrxFilterAction_t* const Action, - SlrxFilterID_t* pFilterId); - -#endif - - - - - -/*! - \brief Sets parameters to Rx filters - - \param[in] RxFilterOperation - possible operations : - - SL_ENABLE_DISABLE_RX_FILTER - Enables\disables filter in a filter list - - SL_REMOVE_RX_FILTER - Removes filter from memory ( to remove from flash call SL_STORE_RX_FILTERS after this command) - - SL_STORE_RX_FILTERS - Save the filters for persistent - - SL_UPDATE_RX_FILTER_ARGS - Update the arguments of existing filter - - SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE - Change the default creation of the pre-prepared filters - - \param[in] pInputBuffer options: - The buffer input is _WlanRxFilterOperationCommandBuff_t: - - SL_ENABLE_DISABLE_RX_FILTER - - SL_REMOVE_RX_FILTER - - SL_STORE_RX_FILTERS - The buffer input is _WlanRxFilterUpdateArgsCommandBuff_t: - - SL_UPDATE_RX_FILTER_ARGS - The buffer input is _WlanRxFilterPrePreparedFiltersCommandBuff_t: - - SL_FILTER_PRE_PREPARED_SET_CREATE_REMOVE_STATE - - \param[in] InputbufferLength The length in byte of the input buffer - - \return On success, zero is returned. Otherwise error code is returned - */ - -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterSet) -_i16 sl_WlanRxFilterSet( const SLrxFilterOperation_t RxFilterOperation, - const _u8* const pInputBuffer, - _u16 InputbufferLength); -#endif - -/*! - \brief Gets parameters of Rx filters - - \param[in] RxFilterOperation - possible operations : - - SL_FILTER_RETRIEVE_ENABLE_STATE - Retrieves the enable disable status - - SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE - Retrieves the pre-prepared filters creation status - - \param[in] pOutputBuffer - The buffer input is _WlanRxFilterRetrieveEnableStatusCommandResponseBuff_t: - - SL_FILTER_RETRIEVE_ENABLE_STATE - The buffer input is _WlanRxFilterPrePreparedFiltersCommandResponseBuff_t: - - SL_FILTER_PRE_PREPARED_RETRIEVE_CREATE_REMOVE_STATE - - \param[in] OutputbufferLength The length in byte of the output buffer - - \return On success, zero is returned. Otherwise error code is returned -*/ - -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterGet) -_i16 sl_WlanRxFilterGet(const SLrxFilterOperation_t RxFilterOperation, - _u8* pOutputBuffer, - _u16 OutputbufferLength); -#endif - - -/*! - - Close the Doxygen group. - @} - - */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* RX_FILTERS_PREPROCESSOR_CLI_IF_H_ */ - - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/device.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/device.c deleted file mode 100644 index 3d4028fb..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/device.c +++ /dev/null @@ -1,557 +0,0 @@ -/* -* device.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "flowcont.h" -#include "driver.h" - - -/*****************************************************************************/ -/* Internal functions */ -/*****************************************************************************/ - -const _i8 StartResponseLUT[8] = -{ - ROLE_UNKNOWN_ERR, - ROLE_STA, - ROLE_STA_ERR, - ROLE_AP, - ROLE_AP_ERR, - ROLE_P2P, - ROLE_P2P_ERR, - ROLE_UNKNOWN_ERR -}; - - - -_i16 _sl_GetStartResponseConvert(_u32 Status) -{ - return (_i16)StartResponseLUT[Status & 0x7]; -} - -/*****************************************************************************/ -/* API Functions */ -/*****************************************************************************/ - - - -/*****************************************************************************/ -/* sl_Task */ -/*****************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_Task) -void sl_Task(void) -{ -#ifdef _SlTaskEntry - _SlTaskEntry(); -#endif -} -#endif - -/*****************************************************************************/ -/* sl_Start */ -/*****************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_Start) -_i16 sl_Start(const void* pIfHdl, _i8* pDevName, const P_INIT_CALLBACK pInitCallBack) -{ - _i16 ObjIdx = MAX_CONCURRENT_ACTIONS; - InitComplete_t AsyncRsp; - - /* Perform any preprocessing before enable networking services */ - sl_DeviceEnablePreamble(); - - /* ControlBlock init */ - _SlDrvDriverCBInit(); - - /* open the interface: usually SPI or UART */ - if (NULL == pIfHdl) - { - g_pCB->FD = sl_IfOpen((void *)pDevName, 0); - } - else - { - g_pCB->FD = (_SlFd_t)pIfHdl; - } - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - if( g_pCB->FD >= (_SlFd_t)0) - { - sl_DeviceDisable(); - - sl_IfRegIntHdlr((SL_P_EVENT_HANDLER)_SlDrvRxIrqHandler, NULL); - - g_pCB->pInitCallback = pInitCallBack; - sl_DeviceEnable(); - - if (NULL == pInitCallBack) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - /* release Pool Object */ - _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex); - return _sl_GetStartResponseConvert(AsyncRsp.Status); - } - else - { - return SL_RET_CODE_OK; - } - } - return SL_BAD_INTERFACE; -} -#endif - -/*************************************************************************** -_sl_HandleAsync_InitComplete - handles init complete signalling to -a waiting object -****************************************************************************/ -void _sl_HandleAsync_InitComplete(void *pVoidBuf) -{ - InitComplete_t *pMsgArgs = (InitComplete_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - if(g_pCB->pInitCallback) - { - g_pCB->pInitCallback(_sl_GetStartResponseConvert(pMsgArgs->Status)); - } - else - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(InitComplete_t)); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - } - - _SlDrvProtectionObjUnLock(); - - if(g_pCB->pInitCallback) - { - _SlDrvReleasePoolObj(g_pCB->FunctionParams.AsyncExt.ActionIndex); - } - -} - -/*************************************************************************** -_sl_HandleAsync_Stop - handles stop signalling to -a waiting object -****************************************************************************/ -void _sl_HandleAsync_Stop(void *pVoidBuf) -{ - _BasicResponse_t *pMsgArgs = (_BasicResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - VERIFY_SOCKET_CB(NULL != g_pCB->StopCB.pAsyncRsp); - - _SlDrvProtectionObjLockWaitForever(); - - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_BasicResponse_t)); - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - - return; -} - - -/***************************************************************************** -sl_stop -******************************************************************************/ -typedef union -{ - _DevStopCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlStopMsg_u; - -const _SlCmdCtrl_t _SlStopCmdCtrl = -{ - SL_OPCODE_DEVICE_STOP_COMMAND, - sizeof(_DevStopCommand_t), - sizeof(_BasicResponse_t) -}; - -#if _SL_INCLUDE_FUNC(sl_Stop) -_i16 sl_Stop(const _u16 timeout) -{ - _i16 RetVal=0; - _SlStopMsg_u Msg; - _BasicResponse_t AsyncRsp; - _i8 ObjIdx = MAX_CONCURRENT_ACTIONS; - /* if timeout is 0 the shutdown is forced immediately */ - if( 0 == timeout ) - { - sl_IfRegIntHdlr(NULL, NULL); - sl_DeviceDisable(); - RetVal = sl_IfClose(g_pCB->FD); - - } - else - { - /* let the device make the shutdown using the defined timeout */ - Msg.Cmd.Timeout = timeout; - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8 *)&AsyncRsp, START_STOP_ID, SL_MAX_SOCKETS); - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlStopCmdCtrl, &Msg, NULL)); - - if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - Msg.Rsp.status = AsyncRsp.status; - RetVal = Msg.Rsp.status; - } - - _SlDrvReleasePoolObj(ObjIdx); - sl_IfRegIntHdlr(NULL, NULL); - sl_DeviceDisable(); - sl_IfClose(g_pCB->FD); - } - _SlDrvDriverCBDeinit(); - - return RetVal; -} -#endif - - -/***************************************************************************** -sl_EventMaskSet -*****************************************************************************/ -typedef union -{ - _DevMaskEventSetCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlEventMaskSetMsg_u; - - - - -#if _SL_INCLUDE_FUNC(sl_EventMaskSet) - -const _SlCmdCtrl_t _SlEventMaskSetCmdCtrl = -{ - SL_OPCODE_DEVICE_EVENTMASKSET, - sizeof(_DevMaskEventSetCommand_t), - sizeof(_BasicResponse_t) -}; - - -_i16 sl_EventMaskSet(const _u8 EventClass ,const _u32 Mask) -{ - _SlEventMaskSetMsg_u Msg; - - Msg.Cmd.group = EventClass; - Msg.Cmd.mask = Mask; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskSetCmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/****************************************************************************** -sl_EventMaskGet -******************************************************************************/ -typedef union -{ - _DevMaskEventGetCommand_t Cmd; - _DevMaskEventGetResponse_t Rsp; -}_SlEventMaskGetMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_EventMaskGet) - -const _SlCmdCtrl_t _SlEventMaskGetCmdCtrl = -{ - SL_OPCODE_DEVICE_EVENTMASKGET, - sizeof(_DevMaskEventGetCommand_t), - sizeof(_DevMaskEventGetResponse_t) -}; - - -_i16 sl_EventMaskGet(const _u8 EventClass,_u32 *pMask) -{ - _SlEventMaskGetMsg_u Msg; - - Msg.Cmd.group = EventClass; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlEventMaskGetCmdCtrl, &Msg, NULL)); - - *pMask = Msg.Rsp.mask; - return SL_RET_CODE_OK; -} -#endif - - - -/****************************************************************************** -sl_DevGet -******************************************************************************/ - -typedef union -{ - _DeviceSetGet_t Cmd; - _DeviceSetGet_t Rsp; -}_SlDeviceMsgGet_u; - - - -#if _SL_INCLUDE_FUNC(sl_DevGet) - -const _SlCmdCtrl_t _SlDeviceGetCmdCtrl = -{ - SL_OPCODE_DEVICE_DEVICEGET, - sizeof(_DeviceSetGet_t), - sizeof(_DeviceSetGet_t) -}; - -_i32 sl_DevGet(const _u8 DeviceGetId,_u8 *pOption,_u8 *pConfigLen, _u8 *pValues) -{ - _SlDeviceMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pConfigLen == 0) - { - return SL_EZEROLEN; - } - - if( pOption ) - { - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pConfigLen; - CmdExt.pRxPayload = (_u8 *)pValues; - - Msg.Cmd.DeviceSetId = DeviceGetId; - - Msg.Cmd.Option = (_u16)*pOption; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceGetCmdCtrl, &Msg, &CmdExt)); - - if( pOption ) - { - *pOption = (_u8)Msg.Rsp.Option; - } - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pConfigLen = (_u8)CmdExt.RxPayloadLen; - return SL_ESMALLBUF; - } - else - { - *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - return (_i16)Msg.Rsp.Status; - } - else - { - return -1; - } -} -#endif - -/****************************************************************************** -sl_DevSet -******************************************************************************/ -typedef union -{ - _DeviceSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlDeviceMsgSet_u; - - - -#if _SL_INCLUDE_FUNC(sl_DevSet) - -const _SlCmdCtrl_t _SlDeviceSetCmdCtrl = -{ - SL_OPCODE_DEVICE_DEVICESET, - sizeof(_DeviceSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i32 sl_DevSet(const _u8 DeviceSetId ,const _u8 Option,const _u8 ConfigLen,const _u8 *pValues) -{ - _SlDeviceMsgSet_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - - CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pValues; - - Msg.Cmd.DeviceSetId = DeviceSetId; - Msg.Cmd.ConfigLen = ConfigLen; - Msg.Cmd.Option = Option; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlDeviceSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/****************************************************************************** -_SlDrvDeviceEventHandler - handles internally device async events -******************************************************************************/ -void _SlDrvDeviceEventHandler(void* pArgs) -{ - _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)pArgs; - - switch(pHdr->GenHeader.Opcode) - { - case SL_OPCODE_DEVICE_INITCOMPLETE: - _sl_HandleAsync_InitComplete(pHdr); - break; - case SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE: - _sl_HandleAsync_Stop(pHdr); - break; - - - case SL_OPCODE_DEVICE_ABORT: - { -#if defined (sl_GeneralEvtHdlr) || defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) - SlDeviceEvent_t devHandler; - devHandler.Event = SL_DEVICE_ABORT_ERROR_EVENT; - devHandler.EventData.deviceReport.AbortType = *((_u32*)pArgs + 2); - devHandler.EventData.deviceReport.AbortData = *((_u32*)pArgs + 3); - _SlDrvHandleGeneralEvents(&devHandler); -#endif - } - break; - - case SL_OPCODE_DEVICE_DEVICEASYNCFATALERROR: -#if defined (sl_GeneralEvtHdlr) || defined(EXT_LIB_REGISTERED_GENERAL_EVENTS) - { - _BasicResponse_t *pMsgArgs = (_BasicResponse_t *)_SL_RESP_ARGS_START(pHdr); - SlDeviceEvent_t devHandler; - devHandler.Event = SL_DEVICE_FATAL_ERROR_EVENT; - devHandler.EventData.deviceEvent.status = pMsgArgs->status & 0xFF; - devHandler.EventData.deviceEvent.sender = (SlErrorSender_e)((pMsgArgs->status >> 8) & 0xFF); - _SlDrvHandleGeneralEvents(&devHandler); - } -#endif - break; - default: - SL_ERROR_TRACE2(MSG_306, "ASSERT: _SlDrvDeviceEventHandler : invalid opcode = 0x%x = %1", pHdr->GenHeader.Opcode, pHdr->GenHeader.Opcode); - } -} - - -/****************************************************************************** -sl_UartSetMode -******************************************************************************/ -#ifdef SL_IF_TYPE_UART -typedef union -{ - _DevUartSetModeCommand_t Cmd; - _DevUartSetModeResponse_t Rsp; -}_SlUartSetModeMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_UartSetMode) - - -const _SlCmdCtrl_t _SlUartSetModeCmdCtrl = -{ - SL_OPCODE_DEVICE_SETUARTMODECOMMAND, - sizeof(_DevUartSetModeCommand_t), - sizeof(_DevUartSetModeResponse_t) -}; - -_i16 sl_UartSetMode(const SlUartIfParams_t* pUartParams) -{ - _SlUartSetModeMsg_u Msg; - _u32 magicCode = 0xFFFFFFFF; - - Msg.Cmd.BaudRate = pUartParams->BaudRate; - Msg.Cmd.FlowControlEnable = pUartParams->FlowControlEnable; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlUartSetModeCmdCtrl, &Msg, NULL)); - - /* cmd response OK, we can continue with the handshake */ - if (SL_RET_CODE_OK == Msg.Rsp.status) - { - sl_IfMaskIntHdlr(); - - /* Close the comm port */ - sl_IfClose(g_pCB->FD); - - /* Re-open the comm port */ - sl_IfOpen((void * )pUartParams, UART_IF_OPEN_FLAG_RE_OPEN); - - sl_IfUnMaskIntHdlr(); - - /* send the magic code and wait for the response */ - sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4); - - magicCode = UART_SET_MODE_MAGIC_CODE; - sl_IfWrite(g_pCB->FD, (_u8* )&magicCode, 4); - - /* clear magic code */ - magicCode = 0; - - /* wait (blocking) till the magic code to be returned from device */ - sl_IfRead(g_pCB->FD, (_u8* )&magicCode, 4); - - /* check for the received magic code matching */ - if (UART_SET_MODE_MAGIC_CODE != magicCode) - { - _SL_ASSERT(0); - } - } - - return (_i16)Msg.Rsp.status; -} -#endif -#endif - - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/driver.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/driver.c deleted file mode 100644 index 817ff0ed..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/driver.c +++ /dev/null @@ -1,1843 +0,0 @@ -/* -* driver.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" -#include "flowcont.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ - -#define _SL_PENDING_RX_MSG(pDriverCB) (RxIrqCnt != (pDriverCB)->RxDoneCnt) - -/* 2 LSB of the N2H_SYNC_PATTERN are for sequence number -only in SPI interface -support backward sync pattern */ -#define N2H_SYNC_PATTERN_SEQ_NUM_BITS ((_u32)0x00000003) /* Bits 0..1 - use the 2 LBS for seq num */ -#define N2H_SYNC_PATTERN_SEQ_NUM_EXISTS ((_u32)0x00000004) /* Bit 2 - sign that sequence number exists in the sync pattern */ -#define N2H_SYNC_PATTERN_MASK ((_u32)0xFFFFFFF8) /* Bits 3..31 - constant SYNC PATTERN */ -#define N2H_SYNC_SPI_BUGS_MASK ((_u32)0x7FFF7F7F) /* Bits 7,15,31 - ignore the SPI (8,16,32 bites bus) error bits */ -#define BUF_SYNC_SPIM(pBuf) ((*(_u32 *)(pBuf)) & N2H_SYNC_SPI_BUGS_MASK) - -_u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID); -#define N2H_SYNC_SPIM (N2H_SYNC_PATTERN & N2H_SYNC_SPI_BUGS_MASK) -#define N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum) ((N2H_SYNC_SPIM & N2H_SYNC_PATTERN_MASK) | N2H_SYNC_PATTERN_SEQ_NUM_EXISTS | ((TxSeqNum) & (N2H_SYNC_PATTERN_SEQ_NUM_BITS))) -#define MATCH_WOUT_SEQ_NUM(pBuf) ( BUF_SYNC_SPIM(pBuf) == N2H_SYNC_SPIM ) -#define MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ( BUF_SYNC_SPIM(pBuf) == (N2H_SYNC_SPIM_WITH_SEQ(TxSeqNum)) ) -#define N2H_SYNC_PATTERN_MATCH(pBuf, TxSeqNum) \ - ( \ - ( (*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WITH_SEQ_NUM(pBuf, TxSeqNum) ) ) || \ - ( !(*((_u32 *)pBuf) & N2H_SYNC_PATTERN_SEQ_NUM_EXISTS) && ( MATCH_WOUT_SEQ_NUM(pBuf ) ) ) \ - ) - -#define OPCODE(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Opcode) -#define RSP_PAYLOAD_LEN(_ptr) (((_SlResponseHeader_t *)(_ptr))->GenHeader.Len - _SL_RESP_SPEC_HDR_SIZE) -#define SD(_ptr) (((_SocketAddrResponse_u *)(_ptr))->IpV4.sd) -/* Actual size of Recv/Recvfrom response data */ -#define ACT_DATA_SIZE(_ptr) (((_SocketAddrResponse_u *)(_ptr))->IpV4.statusOrLen) - - - - -/* General Events handling*/ -#if defined (EXT_LIB_REGISTERED_GENERAL_EVENTS) - -typedef _SlEventPropogationStatus_e (*general_callback) (SlDeviceEvent_t *); - -static const general_callback general_callbacks[] = -{ -#ifdef SlExtLib1GeneralEventHandler - SlExtLib1GeneralEventHandler, -#endif - -#ifdef SlExtLib2GeneralEventHandler - SlExtLib2GeneralEventHandler, -#endif - -#ifdef SlExtLib3GeneralEventHandler - SlExtLib3GeneralEventHandler, -#endif - -#ifdef SlExtLib4GeneralEventHandler - SlExtLib4GeneralEventHandler, -#endif - -#ifdef SlExtLib5GeneralEventHandler - SlExtLib5GeneralEventHandler, -#endif -}; - -#undef _SlDrvHandleGeneralEvents - -/******************************************************************** - _SlDrvHandleGeneralEvents - Iterates through all the general(device) event handlers which are - registered by the external libs/user application. -*********************************************************************/ -void _SlDrvHandleGeneralEvents(SlDeviceEvent_t *slGeneralEvent) -{ - _u8 i; - - /* Iterate over all the extenal libs handlers */ - for ( i = 0 ; i < sizeof(general_callbacks)/sizeof(general_callbacks[0]) ; i++ ) - { - if (EVENT_PROPAGATION_BLOCK == general_callbacks[i](slGeneralEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_GeneralEvtHdlr - sl_GeneralEvtHdlr(slGeneralEvent); -#endif - -} -#endif - - - -/* WLAN Events handling*/ - -#if defined (EXT_LIB_REGISTERED_WLAN_EVENTS) - -typedef _SlEventPropogationStatus_e (*wlan_callback) (SlWlanEvent_t *); - -static wlan_callback wlan_callbacks[] = -{ -#ifdef SlExtLib1WlanEventHandler - SlExtLib1WlanEventHandler, -#endif - -#ifdef SlExtLib2WlanEventHandler - SlExtLib2WlanEventHandler, -#endif - -#ifdef SlExtLib3WlanEventHandler - SlExtLib3WlanEventHandler, -#endif - -#ifdef SlExtLib4WlanEventHandler - SlExtLib4WlanEventHandler, -#endif - -#ifdef SlExtLib5WlanEventHandler - SlExtLib5WlanEventHandler, -#endif -}; - -#undef _SlDrvHandleWlanEvents - -/*********************************************************** - _SlDrvHandleWlanEvents - Iterates through all the wlan event handlers which are - registered by the external libs/user application. -************************************************************/ -void _SlDrvHandleWlanEvents(SlWlanEvent_t *slWlanEvent) -{ - _u8 i; - - /* Iterate over all the extenal libs handlers */ - for ( i = 0 ; i < sizeof(wlan_callbacks)/sizeof(wlan_callbacks[0]) ; i++ ) - { - if ( EVENT_PROPAGATION_BLOCK == wlan_callbacks[i](slWlanEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_WlanEvtHdlr - sl_WlanEvtHdlr(slWlanEvent); -#endif - -} -#endif - - -/* NetApp Events handling */ -#if defined (EXT_LIB_REGISTERED_NETAPP_EVENTS) - -typedef _SlEventPropogationStatus_e (*netApp_callback) (SlNetAppEvent_t *); - -static const netApp_callback netApp_callbacks[] = -{ -#ifdef SlExtLib1NetAppEventHandler - SlExtLib1NetAppEventHandler, -#endif - -#ifdef SlExtLib2NetAppEventHandler - SlExtLib2NetAppEventHandler, -#endif - -#ifdef SlExtLib3NetAppEventHandler - SlExtLib3NetAppEventHandler, -#endif - -#ifdef SlExtLib4NetAppEventHandler - SlExtLib4NetAppEventHandler, -#endif - -#ifdef SlExtLib5NetAppEventHandler - SlExtLib5NetAppEventHandler, -#endif -}; - -#undef _SlDrvHandleNetAppEvents - -/************************************************************ - _SlDrvHandleNetAppEvents - Iterates through all the net app event handlers which are - registered by the external libs/user application. -************************************************************/ -void _SlDrvHandleNetAppEvents(SlNetAppEvent_t *slNetAppEvent) -{ - _u8 i; - - /* Iterate over all the extenal libs handlers */ - for ( i = 0 ; i < sizeof(netApp_callbacks)/sizeof(netApp_callbacks[0]) ; i++ ) - { - if (EVENT_PROPAGATION_BLOCK == netApp_callbacks[i](slNetAppEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_NetAppEvtHdlr - sl_NetAppEvtHdlr(slNetAppEvent); -#endif - -} -#endif - - -/* Http Server Events handling */ -#if defined (EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) - -typedef _SlEventPropogationStatus_e (*httpServer_callback) (SlHttpServerEvent_t*, SlHttpServerResponse_t*); - -static const httpServer_callback httpServer_callbacks[] = -{ -#ifdef SlExtLib1HttpServerEventHandler - SlExtLib1HttpServerEventHandler, -#endif - -#ifdef SlExtLib2HttpServerEventHandler - SlExtLib2HttpServerEventHandler, -#endif - -#ifdef SlExtLib3HttpServerEventHandler - SlExtLib3HttpServerEventHandler, -#endif - -#ifdef SlExtLib4HttpServerEventHandler - SlExtLib4HttpServerEventHandler, -#endif - -#ifdef SlExtLib5HttpServerEventHandler - SlExtLib5HttpServerEventHandler, -#endif -}; - -#undef _SlDrvHandleHttpServerEvents - -/******************************************************************* - _SlDrvHandleHttpServerEvents - Iterates through all the http server event handlers which are - registered by the external libs/user application. -********************************************************************/ -void _SlDrvHandleHttpServerEvents(SlHttpServerEvent_t *slHttpServerEvent, SlHttpServerResponse_t *slHttpServerResponse) -{ - _u8 i; - - /* Iterate over all the external libs handlers */ - for ( i = 0 ; i < sizeof(httpServer_callbacks)/sizeof(httpServer_callbacks[0]) ; i++ ) - { - if ( EVENT_PROPAGATION_BLOCK == httpServer_callbacks[i](slHttpServerEvent, slHttpServerResponse) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_HttpServerCallback - sl_HttpServerCallback(slHttpServerEvent, slHttpServerResponse); -#endif - -} -#endif - - -/* Socket Events */ -#if defined (EXT_LIB_REGISTERED_SOCK_EVENTS) - -typedef _SlEventPropogationStatus_e (*sock_callback) (SlSockEvent_t *); - -static const sock_callback sock_callbacks[] = -{ -#ifdef SlExtLib1SockEventHandler - SlExtLib1SockEventHandler, -#endif - -#ifdef SlExtLib2SockEventHandler - SlExtLib2SockEventHandler, -#endif - -#ifdef SlExtLib3SockEventHandler - SlExtLib3SockEventHandler, -#endif - -#ifdef SlExtLib4SockEventHandler - SlExtLib4SockEventHandler, -#endif - -#ifdef SlExtLib5SockEventHandler - SlExtLib5SockEventHandler, -#endif -}; - -/************************************************************* - _SlDrvHandleSockEvents - Iterates through all the socket event handlers which are - registered by the external libs/user application. -**************************************************************/ -void _SlDrvHandleSockEvents(SlSockEvent_t *slSockEvent) -{ - _u8 i; - - /* Iterate over all the external libs handlers */ - for ( i = 0 ; i < sizeof(sock_callbacks)/sizeof(sock_callbacks[0]) ; i++ ) - { - if ( EVENT_PROPAGATION_BLOCK == sock_callbacks[i](slSockEvent) ) - { - /* exit immediately and do not call the user specific handler as well */ - return; - } - } - -/* At last call the Application specific handler if registered */ -#ifdef sl_SockEvtHdlr - sl_SockEvtHdlr(slSockEvent); -#endif - -} - -#endif - - -#if (SL_MEMORY_MGMT != SL_MEMORY_MGMT_DYNAMIC) -typedef struct -{ - _u32 Align; - _SlDriverCb_t DriverCB; - _u8 AsyncRespBuf[SL_ASYNC_MAX_MSG_LEN]; -}_SlStatMem_t; - -_SlStatMem_t g_StatMem; -#endif - -_u8 _SlDrvProtectAsyncRespSetting(_u8 *pAsyncRsp, _u8 ActionID, _u8 SocketID) -{ - _u8 ObjIdx; - - - /* Use Obj to issue the command, if not available try later */ - ObjIdx = _SlDrvWaitForPoolObj(ActionID, SocketID); - - if (MAX_CONCURRENT_ACTIONS != ObjIdx) - { - _SlDrvProtectionObjLockWaitForever(); - g_pCB->ObjPool[ObjIdx].pRespArgs = pAsyncRsp; - _SlDrvProtectionObjUnLock(); - } - - return ObjIdx; -} - - -/*****************************************************************************/ -/* Variables */ -/*****************************************************************************/ -const _SlSyncPattern_t g_H2NSyncPattern = H2N_SYNC_PATTERN; -const _SlSyncPattern_t g_H2NCnysPattern = H2N_CNYS_PATTERN; -_volatile _u8 RxIrqCnt; - -#ifndef SL_TINY_EXT -const _SlActionLookup_t _SlActionLookupTable[] = -{ - {ACCEPT_ID, SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_Accept}, - {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect}, - {SELECT_ID, SL_OPCODE_SOCKET_SELECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Select}, - {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName}, - {GETHOSYBYSERVICE_ID, SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByService}, - {PING_ID, SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE, (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse}, - {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop} -}; -#else -const _SlActionLookup_t _SlActionLookupTable[] = -{ - {CONNECT_ID, SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Connect}, - {GETHOSYBYNAME_ID, SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_DnsGetHostByName}, - {START_STOP_ID, SL_OPCODE_DEVICE_STOP_ASYNC_RESPONSE,(_SlSpawnEntryFunc_t)_sl_HandleAsync_Stop} -}; -#endif - - - -typedef struct -{ - _u16 opcode; - _u8 event; -} OpcodeKeyVal_t; - -/* The table translates opcode to user's event type */ -const OpcodeKeyVal_t OpcodeTranslateTable[] = -{ -{SL_OPCODE_WLAN_SMART_CONFIG_START_ASYNC_RESPONSE, SL_WLAN_SMART_CONFIG_COMPLETE_EVENT}, -{SL_OPCODE_WLAN_SMART_CONFIG_STOP_ASYNC_RESPONSE,SL_WLAN_SMART_CONFIG_STOP_EVENT}, -{SL_OPCODE_WLAN_STA_CONNECTED, SL_WLAN_STA_CONNECTED_EVENT}, -{SL_OPCODE_WLAN_STA_DISCONNECTED,SL_WLAN_STA_DISCONNECTED_EVENT}, -{SL_OPCODE_WLAN_P2P_DEV_FOUND,SL_WLAN_P2P_DEV_FOUND_EVENT}, -{SL_OPCODE_WLAN_P2P_NEG_REQ_RECEIVED, SL_WLAN_P2P_NEG_REQ_RECEIVED_EVENT}, -{SL_OPCODE_WLAN_CONNECTION_FAILED, SL_WLAN_CONNECTION_FAILED_EVENT}, -{SL_OPCODE_WLAN_WLANASYNCCONNECTEDRESPONSE, SL_WLAN_CONNECT_EVENT}, -{SL_OPCODE_WLAN_WLANASYNCDISCONNECTEDRESPONSE, SL_WLAN_DISCONNECT_EVENT}, -{SL_OPCODE_NETAPP_IPACQUIRED, SL_NETAPP_IPV4_IPACQUIRED_EVENT}, -{SL_OPCODE_NETAPP_IPACQUIRED_V6, SL_NETAPP_IPV6_IPACQUIRED_EVENT}, -{SL_OPCODE_NETAPP_IP_LEASED, SL_NETAPP_IP_LEASED_EVENT}, -{SL_OPCODE_NETAPP_IP_RELEASED, SL_NETAPP_IP_RELEASED_EVENT}, -{SL_OPCODE_SOCKET_TXFAILEDASYNCRESPONSE, SL_SOCKET_TX_FAILED_EVENT}, -{SL_OPCODE_SOCKET_SOCKETASYNCEVENT, SL_SOCKET_ASYNC_EVENT} -}; - - - -_SlDriverCb_t* g_pCB = NULL; -P_SL_DEV_PING_CALLBACK pPingCallBackFunc = NULL; -_u8 gFirstCmdMode = 0; - -/*****************************************************************************/ -/* Function prototypes */ -/*****************************************************************************/ -_SlReturnVal_t _SlDrvMsgRead(void); -_SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff); -_SlReturnVal_t _SlDrvMsgReadCmdCtx(void); -_SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue); -void _SlDrvClassifyRxMsg(_SlOpcode_t Opcode ); -_SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize); -void _SlDrvShiftDWord(_u8 *pBuf); -void _SlDrvDriverCBInit(void); -void _SlAsyncEventGenericHandler(void); -_u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID); -void _SlDrvReleasePoolObj(_u8 pObj); -void _SlRemoveFromList(_u8* ListIndex, _u8 ItemIndex); -_SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd); - - -/*****************************************************************************/ -/* Internal functions */ -/*****************************************************************************/ - - -/***************************************************************************** -_SlDrvDriverCBInit - init Driver Control Block -*****************************************************************************/ - -void _SlDrvDriverCBInit(void) -{ - _u8 Idx =0; - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - g_pCB = sl_Malloc(sizeof(_SlDriverCb_t)); -#else - g_pCB = &(g_StatMem.DriverCB); -#endif - MALLOC_OK_CHECK(g_pCB); - - - _SlDrvMemZero(g_pCB, sizeof(_SlDriverCb_t)); - RxIrqCnt = 0; - OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->CmdSyncObj, "CmdSyncObj") ); - sl_SyncObjClear(&g_pCB->CmdSyncObj); - - OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->GlobalLockObj, "GlobalLockObj") ); - OSI_RET_OK_CHECK( sl_LockObjCreate(&g_pCB->ProtectionLockObj, "ProtectionLockObj") ); - - /* Init Drv object */ - _SlDrvMemZero(&g_pCB->ObjPool[0], MAX_CONCURRENT_ACTIONS*sizeof(_SlPoolObj_t)); - - /* place all Obj in the free list*/ - g_pCB->FreePoolIdx = 0; - - for (Idx = 0 ; Idx < MAX_CONCURRENT_ACTIONS ; Idx++) - { - g_pCB->ObjPool[Idx].NextIndex = Idx + 1; - g_pCB->ObjPool[Idx].AdditionalData = SL_MAX_SOCKETS; - - OSI_RET_OK_CHECK( sl_SyncObjCreate(&g_pCB->ObjPool[Idx].SyncObj, "SyncObj")); - sl_SyncObjClear(&g_pCB->ObjPool[Idx].SyncObj); - } - - g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS; - g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS; - - /* Flow control init */ - g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN; - OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj")); - OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj")); - - gFirstCmdMode = 0; - -} - -/***************************************************************************** -_SlDrvDriverCBDeinit - De init Driver Control Block -*****************************************************************************/ -void _SlDrvDriverCBDeinit() -{ - _u8 Idx =0; - - /* Flow control de-init */ - g_pCB->FlowContCB.TxPoolCnt = 0; - OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj)); - OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj)); - - OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->CmdSyncObj) ); - OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->GlobalLockObj) ); - OSI_RET_OK_CHECK( sl_LockObjDelete(&g_pCB->ProtectionLockObj) ); - - #ifndef SL_TINY_EXT - for (Idx = 0; Idx < MAX_CONCURRENT_ACTIONS; Idx++) - #endif - { - OSI_RET_OK_CHECK( sl_SyncObjDelete(&g_pCB->ObjPool[Idx].SyncObj) ); - } - - g_pCB->FreePoolIdx = 0; - g_pCB->PendingPoolIdx = MAX_CONCURRENT_ACTIONS; - g_pCB->ActivePoolIdx = MAX_CONCURRENT_ACTIONS; - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - sl_Free(g_pCB); -#else - g_pCB = NULL; -#endif - - - g_pCB = NULL; -} - -/***************************************************************************** -_SlDrvRxIrqHandler - Interrupt handler -*****************************************************************************/ -void _SlDrvRxIrqHandler(void *pValue) -{ - sl_IfMaskIntHdlr(); - - RxIrqCnt++; - - if (TRUE == g_pCB->IsCmdRespWaited) - { - OSI_RET_OK_CHECK( sl_SyncObjSignalFromIRQ(&g_pCB->CmdSyncObj) ); - } - else - { - sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0); - } -} - -/***************************************************************************** -_SlDrvCmdOp -*****************************************************************************/ -_SlReturnVal_t _SlDrvCmdOp( - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal; - - - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); - - g_pCB->IsCmdRespWaited = TRUE; - - SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdOp: call _SlDrvMsgWrite"); - - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); - - if(SL_OS_RET_CODE_OK == RetVal) - { - -#ifndef SL_IF_TYPE_UART - /* Waiting for SPI to stabilize after first command */ - if( 0 == gFirstCmdMode ) - { - volatile _u32 CountVal = 0; - gFirstCmdMode = 1; - CountVal = CPU_FREQ_IN_MHZ*USEC_DELAY; - while( CountVal-- ); - } -#endif - /* wait for respond */ - RetVal = _SlDrvMsgReadCmdCtx(); /* will free global lock */ - SL_TRACE0(DBG_MSG, MSG_314, "_SlDrvCmdOp: exited _SlDrvMsgReadCmdCtx"); - } - else - { - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - } - - return RetVal; -} - - - -/***************************************************************************** -_SlDrvDataReadOp -*****************************************************************************/ -_SlReturnVal_t _SlDrvDataReadOp( - _SlSd_t Sd, - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - _SlArgsData_t pArgsData; - - /* Validate input arguments */ - VERIFY_PROTOCOL(NULL != pCmdExt->pRxPayload); - - /* If zero bytes is requested, return error. */ - /* This allows us not to fill remote socket's IP address in return arguments */ - VERIFY_PROTOCOL(0 != pCmdExt->RxPayloadLen); - - /* Validate socket */ - if((Sd & BSD_SOCKET_ID_MASK) >= SL_MAX_SOCKETS) - { - return SL_EBADF; - } - - /*Use Obj to issue the command, if not available try later*/ - ObjIdx = (_u8)_SlDrvWaitForPoolObj(RECV_ID, Sd & BSD_SOCKET_ID_MASK); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - _SlDrvProtectionObjLockWaitForever(); - - pArgsData.pData = pCmdExt->pRxPayload; - pArgsData.pArgs = (_u8 *)pTxRxDescBuff; - g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&pArgsData; - - _SlDrvProtectionObjUnLock(); - - - /* Do Flow Control check/update for DataWrite operation */ - _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj); - - - /* Clear SyncObj for the case it was signalled before TxPoolCnt */ - /* dropped below '1' (last Data buffer was taken) */ - /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */ - sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj); - - if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN) - { - - /* If TxPoolCnt was increased by other thread at this moment, - TxSyncObj won't wait here */ - _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj); - - } - - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); - - - VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN); - g_pCB->FlowContCB.TxPoolCnt--; - - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, (_u8 *)pTxRxDescBuff); - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - - if(SL_OS_RET_CODE_OK == RetVal) - { - /* Wait for response message. Will be signaled by _SlDrvMsgRead. */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - } - - _SlDrvReleasePoolObj(ObjIdx); - return RetVal; -} - -/* ******************************************************************************/ -/* _SlDrvDataWriteOp */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvDataWriteOp( - _SlSd_t Sd, - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal = SL_EAGAIN; /* initiated as SL_EAGAIN for the non blocking mode */ - while( 1 ) - { - /* Do Flow Control check/update for DataWrite operation */ - _SlDrvObjLockWaitForever(&g_pCB->FlowContCB.TxLockObj); - - /* Clear SyncObj for the case it was signalled before TxPoolCnt */ - /* dropped below '1' (last Data buffer was taken) */ - /* OSI_RET_OK_CHECK( sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj) ); */ - sl_SyncObjClear(&g_pCB->FlowContCB.TxSyncObj); - - /* we have indication that the last send has failed - socket is no longer valid for operations */ - if(g_pCB->SocketTXFailure & (1<<(Sd & BSD_SOCKET_ID_MASK))) - { - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - return SL_SOC_ERROR; - } - if(g_pCB->FlowContCB.TxPoolCnt <= FLOW_CONT_MIN + 1) - { - /* we have indication that this socket is set as blocking and we try to */ - /* unblock it - return an error */ - if( g_pCB->SocketNonBlocking & (1<< (Sd & BSD_SOCKET_ID_MASK))) - { - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - return RetVal; - } - /* If TxPoolCnt was increased by other thread at this moment, */ - /* TxSyncObj won't wait here */ - _SlDrvSyncObjWaitForever(&g_pCB->FlowContCB.TxSyncObj); - } - if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 ) - { - break; - } - else - { - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - } - } - - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); - - - VERIFY_PROTOCOL(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN + 1 ); - g_pCB->FlowContCB.TxPoolCnt--; - - _SlDrvObjUnLock(&g_pCB->FlowContCB.TxLockObj); - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - return RetVal; -} - -/* ******************************************************************************/ -/* _SlDrvMsgWrite */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgWrite(_SlCmdCtrl_t *pCmdCtrl,_SlCmdExt_t *pCmdExt, _u8 *pTxRxDescBuff) -{ - _u8 sendRxPayload = FALSE; - VERIFY_PROTOCOL(NULL != pCmdCtrl); - - g_pCB->FunctionParams.pCmdCtrl = pCmdCtrl; - g_pCB->FunctionParams.pTxRxDescBuff = pTxRxDescBuff; - g_pCB->FunctionParams.pCmdExt = pCmdExt; - - g_pCB->TempProtocolHeader.Opcode = pCmdCtrl->Opcode; - g_pCB->TempProtocolHeader.Len = _SL_PROTOCOL_CALC_LEN(pCmdCtrl, pCmdExt); - - if (pCmdExt && pCmdExt->RxPayloadLen < 0 && pCmdExt->TxPayloadLen) - { - pCmdExt->RxPayloadLen = pCmdExt->RxPayloadLen * (-1); /* change sign */ - sendRxPayload = TRUE; - g_pCB->TempProtocolHeader.Len = g_pCB->TempProtocolHeader.Len + pCmdExt->RxPayloadLen; - } - -#ifdef SL_START_WRITE_STAT - sl_IfStartWriteSequence(g_pCB->FD); -#endif - -#ifdef SL_IF_TYPE_UART - /* Write long sync pattern */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Long, 2*SYNC_PATTERN_LEN); -#else - /* Write short sync pattern */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NSyncPattern.Short, SYNC_PATTERN_LEN); -#endif - - /* Header */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_pCB->TempProtocolHeader, _SL_CMD_HDR_SIZE); - - /* Descriptors */ - if (pTxRxDescBuff && pCmdCtrl->TxDescLen > 0) - { - NWP_IF_WRITE_CHECK(g_pCB->FD, pTxRxDescBuff, - _SL_PROTOCOL_ALIGN_SIZE(pCmdCtrl->TxDescLen)); - } - - /* A special mode where Rx payload and Rx length are used as Tx as well */ - /* This mode requires no Rx payload on the response and currently used by fs_Close and sl_Send on */ - /* transceiver mode */ - if (sendRxPayload == TRUE ) - { - NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pRxPayload, - _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->RxPayloadLen)); - } - - /* Payload */ - if (pCmdExt && pCmdExt->TxPayloadLen > 0) - { - /* If the message has payload, it is mandatory that the message's arguments are protocol aligned. */ - /* Otherwise the aligning of arguments will create a gap between arguments and payload. */ - VERIFY_PROTOCOL(_SL_IS_PROTOCOL_ALIGNED_SIZE(pCmdCtrl->TxDescLen)); - - NWP_IF_WRITE_CHECK(g_pCB->FD, pCmdExt->pTxPayload, - _SL_PROTOCOL_ALIGN_SIZE(pCmdExt->TxPayloadLen)); - } - - - _SL_DBG_CNT_INC(MsgCnt.Write); - -#ifdef SL_START_WRITE_STAT - sl_IfEndWriteSequence(g_pCB->FD); -#endif - - return SL_OS_RET_CODE_OK; -} - -/* ******************************************************************************/ -/* _SlDrvMsgRead */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgRead(void) -{ - /* alignment for small memory models */ - union - { - _u8 TempBuf[_SL_RESP_HDR_SIZE]; - _u32 DummyBuf[2]; - } uBuf; - _u8 TailBuffer[4]; - _u16 LengthToCopy; - _u16 AlignedLengthRecv; - _u8 AlignSize; - _u8 *pAsyncBuf = NULL; - _u16 OpCode; - _u16 RespPayloadLen; - _u8 sd = SL_MAX_SOCKETS; - _SlRxMsgClass_e RxMsgClass; - - - /* save params in global CB */ - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler= NULL; - - - VERIFY_RET_OK(_SlDrvRxHdrRead((_u8*)(uBuf.TempBuf), &AlignSize)); - - OpCode = OPCODE(uBuf.TempBuf); - RespPayloadLen = RSP_PAYLOAD_LEN(uBuf.TempBuf); - - - /* 'Init Compelete' message bears no valid FlowControl info */ - if(SL_OPCODE_DEVICE_INITCOMPLETE != OpCode) - { - g_pCB->FlowContCB.TxPoolCnt = ((_SlResponseHeader_t *)uBuf.TempBuf)->TxPoolCnt; - g_pCB->SocketNonBlocking = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketNonBlocking; - g_pCB->SocketTXFailure = ((_SlResponseHeader_t *)uBuf.TempBuf)->SocketTXFailure; - - if(g_pCB->FlowContCB.TxPoolCnt > FLOW_CONT_MIN) - { - _SlDrvSyncObjSignal(&g_pCB->FlowContCB.TxSyncObj); - } - } - - /* Find the RX messaage class and set its async event handler */ - _SlDrvClassifyRxMsg(OpCode); - - RxMsgClass = g_pCB->FunctionParams.AsyncExt.RxMsgClass; - - - switch(RxMsgClass) - { - case ASYNC_EVT_CLASS: - - VERIFY_PROTOCOL(NULL == pAsyncBuf); - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = sl_Malloc(SL_ASYNC_MAX_MSG_LEN); -#else - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = g_StatMem.AsyncRespBuf; -#endif - /* set the local pointer to the allocated one */ - pAsyncBuf = g_pCB->FunctionParams.AsyncExt.pAsyncBuf; - - /* clear the async buffer */ - _SlDrvMemZero(pAsyncBuf, SL_ASYNC_MAX_MSG_LEN); - - MALLOC_OK_CHECK(pAsyncBuf); - - sl_Memcpy(pAsyncBuf, uBuf.TempBuf, _SL_RESP_HDR_SIZE); - if (_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) <= SL_ASYNC_MAX_PAYLOAD_LEN) - { - AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen); - } - else - { - AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(SL_ASYNC_MAX_PAYLOAD_LEN); - } - if (RespPayloadLen > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD, - pAsyncBuf + _SL_RESP_HDR_SIZE, - AlignedLengthRecv); - } - /* In case ASYNC RX buffer length is smaller then the received data length, dump the rest */ - if ((_SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) > SL_ASYNC_MAX_PAYLOAD_LEN)) - { - AlignedLengthRecv = _SL_PROTOCOL_ALIGN_SIZE(RespPayloadLen) - SL_ASYNC_MAX_PAYLOAD_LEN; - while (AlignedLengthRecv > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); - AlignedLengthRecv = AlignedLengthRecv - 4; - } - } - - _SlDrvProtectionObjLockWaitForever(); - - if ( -#ifndef SL_TINY_EXT - (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE == OpCode) || - (SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE_V6 == OpCode) || -#endif - (SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE == OpCode) - ) - { - /* go over the active list if exist to find obj waiting for this Async event */ - sd = ((((_SocketResponse_t *)(pAsyncBuf + _SL_RESP_HDR_SIZE))->sd) & BSD_SOCKET_ID_MASK); - } - _SlFindAndSetActiveObj(OpCode, sd); - - _SlDrvProtectionObjUnLock(); - - break; - case RECV_RESP_CLASS: - { - _u8 ExpArgSize; /* Expected size of Recv/Recvfrom arguments */ - - switch(OpCode) - { - case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE: - ExpArgSize = RECVFROM_IPV4_ARGS_SIZE; - break; -#ifndef SL_TINY_EXT - case SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6: - ExpArgSize = RECVFROM_IPV6_ARGS_SIZE; - break; -#endif - default: - /* SL_OPCODE_SOCKET_RECVASYNCRESPONSE: */ - ExpArgSize = RECV_ARGS_SIZE; - } - - /* Read first 4 bytes of Recv/Recvfrom response to get SocketId and actual */ - /* response data length */ - NWP_IF_READ_CHECK(g_pCB->FD, &uBuf.TempBuf[4], RECV_ARGS_SIZE); - - /* Validate Socket ID and Received Length value. */ - VERIFY_PROTOCOL((SD(&uBuf.TempBuf[4])& BSD_SOCKET_ID_MASK) < SL_MAX_SOCKETS); - - _SlDrvProtectionObjLockWaitForever(); - - /* go over the active list if exist to find obj waiting for this Async event */ - VERIFY_RET_OK(_SlFindAndSetActiveObj(OpCode,SD(&uBuf.TempBuf[4]) & BSD_SOCKET_ID_MASK)); - - /* Verify data is waited on this socket. The pArgs should have been set by _SlDrvDataReadOp(). */ - VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData))->pArgs); - - sl_Memcpy( ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs, &uBuf.TempBuf[4], RECV_ARGS_SIZE); - - if(ExpArgSize > RECV_ARGS_SIZE) - { - NWP_IF_READ_CHECK(g_pCB->FD, - ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pArgs + RECV_ARGS_SIZE, - ExpArgSize - RECV_ARGS_SIZE); - } - - /* Here g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pData contains requested(expected) Recv/Recvfrom DataSize. */ - /* Overwrite requested DataSize with actual one. */ - /* If error is received, this information will be read from arguments. */ - if(ACT_DATA_SIZE(&uBuf.TempBuf[4]) > 0) - { - VERIFY_SOCKET_CB(NULL != ((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData); - - /* Read 4 bytes aligned from interface */ - /* therefore check the requested length and read only */ - /* 4 bytes aligned data. The rest unaligned (if any) will be read */ - /* and copied to a TailBuffer */ - LengthToCopy = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (3); - AlignedLengthRecv = ACT_DATA_SIZE(&uBuf.TempBuf[4]) & (~3); - if( AlignedLengthRecv >= 4) - { - NWP_IF_READ_CHECK(g_pCB->FD,((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData,AlignedLengthRecv ); - } - /* copy the unaligned part, if any */ - if( LengthToCopy > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); - /* copy TailBuffer unaligned part (1/2/3 bytes) */ - sl_Memcpy(((_SlArgsData_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->pData + AlignedLengthRecv,TailBuffer,LengthToCopy); - } - } - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - } - break; - - case CMD_RESP_CLASS: - - /* Some commands pass a maximum arguments size. */ - /* In this case Driver will send extra dummy patterns to NWP if */ - /* the response message is smaller than maximum. */ - /* When RxDescLen is not exact, using RxPayloadLen is forbidden! */ - /* If such case cannot be avoided - parse message here to detect */ - /* arguments/payload border. */ - NWP_IF_READ_CHECK(g_pCB->FD, - g_pCB->FunctionParams.pTxRxDescBuff, - _SL_PROTOCOL_ALIGN_SIZE(g_pCB->FunctionParams.pCmdCtrl->RxDescLen)); - - if((NULL != g_pCB->FunctionParams.pCmdExt) && (0 != g_pCB->FunctionParams.pCmdExt->RxPayloadLen)) - { - /* Actual size of command's response payload: - */ - _i16 ActDataSize = RSP_PAYLOAD_LEN(uBuf.TempBuf) - g_pCB->FunctionParams.pCmdCtrl->RxDescLen; - - g_pCB->FunctionParams.pCmdExt->ActualRxPayloadLen = ActDataSize; - - /* Check that the space prepared by user for the response data is sufficient. */ - if(ActDataSize <= 0) - { - g_pCB->FunctionParams.pCmdExt->RxPayloadLen = 0; - } - else - { - /* In case the user supplied Rx buffer length which is smaller then the received data length, copy according to user length */ - if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) - { - LengthToCopy = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (3); - AlignedLengthRecv = g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3); - } - else - { - LengthToCopy = ActDataSize & (3); - AlignedLengthRecv = ActDataSize & (~3); - } - /* Read 4 bytes aligned from interface */ - /* therefore check the requested length and read only */ - /* 4 bytes aligned data. The rest unaligned (if any) will be read */ - /* and copied to a TailBuffer */ - - if( AlignedLengthRecv >= 4) - { - NWP_IF_READ_CHECK(g_pCB->FD, - g_pCB->FunctionParams.pCmdExt->pRxPayload, - AlignedLengthRecv ); - - } - /* copy the unaligned part, if any */ - if( LengthToCopy > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer,4); - /* copy TailBuffer unaligned part (1/2/3 bytes) */ - sl_Memcpy(g_pCB->FunctionParams.pCmdExt->pRxPayload + AlignedLengthRecv, - TailBuffer, - LengthToCopy); - ActDataSize = ActDataSize-4; - } - /* In case the user supplied Rx buffer length which is smaller then the received data length, dump the rest */ - if (ActDataSize > g_pCB->FunctionParams.pCmdExt->RxPayloadLen) - { - /* calculate the rest of the data size to dump */ - AlignedLengthRecv = ActDataSize - (g_pCB->FunctionParams.pCmdExt->RxPayloadLen & (~3)); - while( AlignedLengthRecv > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD,TailBuffer, 4 ); - AlignedLengthRecv = AlignedLengthRecv - 4; - } - } - } - } - break; - - default: - /* DUMMY_MSG_CLASS: Flow control message has no payload. */ - break; - } - - if(AlignSize > 0) - { - NWP_IF_READ_CHECK(g_pCB->FD, uBuf.TempBuf, AlignSize); - } - - _SL_DBG_CNT_INC(MsgCnt.Read); - - /* Unmask Interrupt call */ - sl_IfUnMaskIntHdlr(); - - return SL_OS_RET_CODE_OK; -} - - -/* ******************************************************************************/ -/* _SlAsyncEventGenericHandler */ -/* ******************************************************************************/ -void _SlAsyncEventGenericHandler(void) -{ - _u32 SlAsyncEvent = 0; - _u8 OpcodeFound = FALSE; - _u8 i; - - _u32* pEventLocation = NULL; /* This pointer will override the async buffer with the translated event type */ - _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)g_pCB->FunctionParams.AsyncExt.pAsyncBuf; - - - /* if no async event registered nothing to do..*/ - if (g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler == NULL) - return; - - /* Iterate through all the opcode in the table */ - for (i=0; i< (sizeof(OpcodeTranslateTable) / sizeof(OpcodeKeyVal_t)); i++) - { - if (OpcodeTranslateTable[i].opcode == pHdr->GenHeader.Opcode) - { - SlAsyncEvent = OpcodeTranslateTable[i].event; - OpcodeFound = TRUE; - break; - } - } - - /* No Async event found in the table */ - if (OpcodeFound == FALSE) - { - /* This case handles all the async events handlers of the DEVICE & SOCK Silos which are handled internally. - For these cases we send the async even buffer as is */ - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); - } - else - { - /* calculate the event type location to be filled in the async buffer */ - pEventLocation = (_u32*)(g_pCB->FunctionParams.AsyncExt.pAsyncBuf + sizeof (_SlResponseHeader_t) - sizeof(SlAsyncEvent) ); - - /* Override the async buffer (before the data starts ) with our event type */ - *pEventLocation = SlAsyncEvent; - - /* call the event handler registered by the user with our async buffer which now holds - the User's event type and its related data */ - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler(pEventLocation); - } - - -} - - -/* ******************************************************************************/ -/* _SlDrvMsgReadCmdCtx */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgReadCmdCtx(void) -{ - - /* after command response is received and isCmdRespWaited */ - /* flag is set FALSE, it is necessary to read out all */ - /* Async messages in Commands context, because ssiDma_IsrHandleSignalFromSlave */ - /* could have dispatched some Async messages to g_NwpIf.CmdSyncObj */ - /* after command response but before this response has been processed */ - /* by spi_singleRead and isCmdRespWaited was set FALSE. */ - while (TRUE == g_pCB->IsCmdRespWaited) - { - if(_SL_PENDING_RX_MSG(g_pCB)) - { - VERIFY_RET_OK(_SlDrvMsgRead()); - g_pCB->RxDoneCnt++; - - if (CMD_RESP_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) - { - g_pCB->IsCmdRespWaited = FALSE; - - /* In case CmdResp has been read without waiting on CmdSyncObj - that */ - /* Sync object. That to prevent old signal to be processed. */ - sl_SyncObjClear(&g_pCB->CmdSyncObj); - } - else if (ASYNC_EVT_CLASS == g_pCB->FunctionParams.AsyncExt.RxMsgClass) - { - /* If Async event has been read in CmdResp context, check whether */ - /* there is a handler for this event. If there is, spawn specific */ - /* handler. Otherwise free the event's buffer. */ - /* This way there will be no "dry shots" from CmdResp context to */ - /* temporary context, i.e less waste of CPU and faster buffer */ - /* release. */ - _SlAsyncEventGenericHandler(); - - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); -#else - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; -#endif - } - } - else - { - /* CmdSyncObj will be signaled by IRQ */ - _SlDrvSyncObjWaitForever(&g_pCB->CmdSyncObj); - } - } - - /* If there are more pending Rx Msgs after CmdResp is received, */ - /* that means that these are Async, Dummy or Read Data Msgs. */ - /* Spawn _SlDrvMsgReadSpawnCtx to trigger reading these messages from */ - /* Temporary context. */ - /* sl_Spawn is activated, using a different context */ - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - if(_SL_PENDING_RX_MSG(g_pCB)) - { - sl_Spawn((_SlSpawnEntryFunc_t)_SlDrvMsgReadSpawnCtx, NULL, 0); - } - - return SL_OS_RET_CODE_OK; -} - -/* ******************************************************************************/ -/* _SlDrvMsgReadSpawnCtx */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvMsgReadSpawnCtx(void *pValue) -{ -#ifdef SL_POLLING_MODE_USED - _i16 retCode = OSI_OK; - /* for polling based systems */ - do - { - retCode = sl_LockObjLock(&g_pCB->GlobalLockObj, 0); - if ( OSI_OK != retCode ) - { - if (TRUE == g_pCB->IsCmdRespWaited) - { - _SlDrvSyncObjSignal(&g_pCB->CmdSyncObj); - return SL_RET_CODE_OK; - } - } - - } - while (OSI_OK != retCode); - -#else - _SlDrvObjLockWaitForever(&g_pCB->GlobalLockObj); -#endif - - - /* Messages might have been read by CmdResp context. Therefore after */ - /* getting LockObj, check again where the Pending Rx Msg is still present. */ - if(FALSE == (_SL_PENDING_RX_MSG(g_pCB))) - { - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - return SL_RET_CODE_OK; - } - - VERIFY_RET_OK(_SlDrvMsgRead()); - - g_pCB->RxDoneCnt++; - - switch(g_pCB->FunctionParams.AsyncExt.RxMsgClass) - { - case ASYNC_EVT_CLASS: - /* If got here and protected by LockObj a message is waiting */ - /* to be read */ - VERIFY_PROTOCOL(NULL != g_pCB->FunctionParams.AsyncExt.pAsyncBuf); - - _SlAsyncEventGenericHandler(); - -#if (SL_MEMORY_MGMT == SL_MEMORY_MGMT_DYNAMIC) - sl_Free(g_pCB->FunctionParams.AsyncExt.pAsyncBuf); -#else - g_pCB->FunctionParams.AsyncExt.pAsyncBuf = NULL; -#endif - break; - case DUMMY_MSG_CLASS: - case RECV_RESP_CLASS: - /* These types are legal in this context. Do nothing */ - break; - case CMD_RESP_CLASS: - /* Command response is illegal in this context. */ - /* No 'break' here: Assert! */ - default: - VERIFY_PROTOCOL(0); - } - - _SlDrvObjUnLock(&g_pCB->GlobalLockObj); - - return(SL_RET_CODE_OK); -} - - - -/* - -#define SL_OPCODE_SILO_DEVICE ( 0x0 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_WLAN ( 0x1 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_SOCKET ( 0x2 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETAPP ( 0x3 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NVMEM ( 0x4 << SL_OPCODE_SILO_OFFSET ) -#define SL_OPCODE_SILO_NETCFG ( 0x5 << SL_OPCODE_SILO_OFFSET ) - - -*/ - -/* The Lookup table below holds the event handlers to be called according to the incoming - RX message SILO type */ -const _SlSpawnEntryFunc_t RxMsgClassLUT[] = { - (_SlSpawnEntryFunc_t)_SlDrvDeviceEventHandler, /* SL_OPCODE_SILO_DEVICE */ -#if defined(sl_WlanEvtHdlr) || defined(EXT_LIB_REGISTERED_WLAN_EVENTS) - (_SlSpawnEntryFunc_t)_SlDrvHandleWlanEvents, /* SL_OPCODE_SILO_WLAN */ -#else - NULL, -#endif -#if defined (sl_SockEvtHdlr) || defined(EXT_LIB_REGISTERED_SOCK_EVENTS) - (_SlSpawnEntryFunc_t)_SlDrvHandleSockEvents, /* SL_OPCODE_SILO_SOCKET */ -#else - NULL, -#endif - -#if defined(sl_NetAppEvtHdlr) || defined(EXT_LIB_REGISTERED_NETAPP_EVENTS) - (_SlSpawnEntryFunc_t)_SlDrvHandleNetAppEvents, /* SL_OPCODE_SILO_NETAPP */ -#else - NULL, -#endif - NULL, /* SL_OPCODE_SILO_NVMEM */ - NULL, /* SL_OPCODE_SILO_NETCFG */ - NULL, - NULL -}; - - -/* ******************************************************************************/ -/* _SlDrvClassifyRxMsg */ -/* ******************************************************************************/ -void _SlDrvClassifyRxMsg( - _SlOpcode_t Opcode) -{ - _SlSpawnEntryFunc_t AsyncEvtHandler = NULL; - _SlRxMsgClass_e RxMsgClass = CMD_RESP_CLASS; - _u8 Silo; - - - if (0 == (SL_OPCODE_SYNC & Opcode)) - { /* Async event has received */ - - if (SL_OPCODE_DEVICE_DEVICEASYNCDUMMY == Opcode) - { - RxMsgClass = DUMMY_MSG_CLASS; - } - else if ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) -#ifndef SL_TINY_EXT - || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) -#endif - ) - { - RxMsgClass = RECV_RESP_CLASS; - } - else - { - /* This is Async Event class message */ - RxMsgClass = ASYNC_EVT_CLASS; - - /* Despite the fact that 4 bits are allocated in the SILO field, we actually have only 6 SILOs - So we can use the 8 options of SILO in look up table */ - Silo = ((Opcode >> SL_OPCODE_SILO_OFFSET) & 0x7); - - VERIFY_PROTOCOL(Silo < (sizeof(RxMsgClassLUT)/sizeof(_SlSpawnEntryFunc_t))); - - /* Set the async event hander according to the LUT */ - AsyncEvtHandler = RxMsgClassLUT[Silo]; - - if ((SL_OPCODE_NETAPP_HTTPGETTOKENVALUE == Opcode) || (SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE == Opcode)) - { - AsyncEvtHandler = _SlDrvNetAppEventHandler; - } -#ifndef SL_TINY_EXT - else if (SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE == Opcode) - { - AsyncEvtHandler = (_SlSpawnEntryFunc_t)_sl_HandleAsync_PingResponse; - } -#endif - } - } - - g_pCB->FunctionParams.AsyncExt.RxMsgClass = RxMsgClass; - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = AsyncEvtHandler; - -} - - -/* ******************************************************************************/ -/* _SlDrvRxHdrRead */ -/* ******************************************************************************/ -_SlReturnVal_t _SlDrvRxHdrRead(_u8 *pBuf, _u8 *pAlignSize) -{ - _u32 SyncCnt = 0; - _u8 ShiftIdx; - -#ifndef SL_IF_TYPE_UART - /* 1. Write CNYS pattern to NWP when working in SPI mode only */ - NWP_IF_WRITE_CHECK(g_pCB->FD, (_u8 *)&g_H2NCnysPattern.Short, SYNC_PATTERN_LEN); -#endif - - /* 2. Read 4 bytes (protocol aligned) */ - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4); - _SL_DBG_SYNC_LOG(SyncCnt,pBuf); - - /* Wait for SYNC_PATTERN_LEN from the device */ - while ( ! N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) - { - /* 3. Debug limit of scan */ - VERIFY_PROTOCOL(SyncCnt < SL_SYNC_SCAN_THRESHOLD); - - /* 4. Read next 4 bytes to Low 4 bytes of buffer */ - if(0 == (SyncCnt % (_u32)SYNC_PATTERN_LEN)) - { - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[4], 4); - _SL_DBG_SYNC_LOG(SyncCnt,pBuf); - } - - /* 5. Shift Buffer Up for checking if the sync is shifted */ - for(ShiftIdx = 0; ShiftIdx< 7; ShiftIdx++) - { - pBuf[ShiftIdx] = pBuf[ShiftIdx+1]; - } - pBuf[7] = 0; - - SyncCnt++; - } - - /* 5. Sync pattern found. If needed, complete number of read bytes to multiple of 4 (protocol align) */ - SyncCnt %= SYNC_PATTERN_LEN; - - if(SyncCnt > 0) - { - *(_u32 *)&pBuf[0] = *(_u32 *)&pBuf[4]; - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN - SyncCnt], (_u16)SyncCnt); - } - else - { - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], 4); - } - - /* 6. Scan for Double pattern. */ - while ( N2H_SYNC_PATTERN_MATCH(pBuf, g_pCB->TxSeqNum) ) - { - _SL_DBG_CNT_INC(Work.DoubleSyncPattern); - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[0], SYNC_PATTERN_LEN); - } - g_pCB->TxSeqNum++; - - /* 7. Here we've read Generic Header (4 bytes). Read the Resp Specific header (4 more bytes). */ - NWP_IF_READ_CHECK(g_pCB->FD, &pBuf[SYNC_PATTERN_LEN], _SL_RESP_SPEC_HDR_SIZE); - - /* 8. Here we've read the entire Resp Header. */ - /* Return number bytes needed to be sent after read for NWP Rx 4-byte alignment (protocol alignment) */ - *pAlignSize = (_u8)((SyncCnt > 0) ? (SYNC_PATTERN_LEN - SyncCnt) : 0); - - return SL_RET_CODE_OK; -} - -/* ***************************************************************************** */ -/* _SlDrvBasicCmd */ -/* ***************************************************************************** */ -typedef union -{ - _BasicResponse_t Rsp; -}_SlBasicCmdMsg_u; - - -#ifndef SL_TINY_EXT -_i16 _SlDrvBasicCmd(_SlOpcode_t Opcode) -{ - _SlBasicCmdMsg_u Msg = {{0, 0}}; - _SlCmdCtrl_t CmdCtrl; - - CmdCtrl.Opcode = Opcode; - CmdCtrl.TxDescLen = 0; - CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} - -/***************************************************************************** - _SlDrvCmdSend - Send SL command without waiting for command response - This function is unprotected and the caller should make - sure global lock is active -*****************************************************************************/ -_SlReturnVal_t _SlDrvCmdSend( - _SlCmdCtrl_t *pCmdCtrl , - void *pTxRxDescBuff , - _SlCmdExt_t *pCmdExt) -{ - _SlReturnVal_t RetVal; - _u8 IsCmdRespWaitedOriginalVal; - - _SlFunctionParams_t originalFuncParms; - - /* save the current RespWait flag before clearing it */ - IsCmdRespWaitedOriginalVal = g_pCB->IsCmdRespWaited; - - /* save the current command parameters */ - sl_Memcpy(&originalFuncParms, &g_pCB->FunctionParams, sizeof(_SlFunctionParams_t)); - - g_pCB->IsCmdRespWaited = FALSE; - - SL_TRACE0(DBG_MSG, MSG_312, "_SlDrvCmdSend: call _SlDrvMsgWrite"); - - /* send the message */ - RetVal = _SlDrvMsgWrite(pCmdCtrl, pCmdExt, pTxRxDescBuff); - - /* restore the original RespWait flag */ - g_pCB->IsCmdRespWaited = IsCmdRespWaitedOriginalVal; - - /* restore the original command parameters */ - sl_Memcpy(&g_pCB->FunctionParams, &originalFuncParms, sizeof(_SlFunctionParams_t)); - - return RetVal; - - -} -#endif - -/* ***************************************************************************** */ -/* _SlDrvWaitForPoolObj */ -/* ***************************************************************************** */ -_u8 _SlDrvWaitForPoolObj(_u8 ActionID, _u8 SocketID) -{ - _u8 CurrObjIndex = MAX_CONCURRENT_ACTIONS; - - /* Get free object */ - _SlDrvProtectionObjLockWaitForever(); - if (MAX_CONCURRENT_ACTIONS > g_pCB->FreePoolIdx) - { - /* save the current obj index */ - CurrObjIndex = g_pCB->FreePoolIdx; - /* set the new free index */ -#ifndef SL_TINY_EXT - if (MAX_CONCURRENT_ACTIONS > g_pCB->ObjPool[CurrObjIndex].NextIndex) - { - g_pCB->FreePoolIdx = g_pCB->ObjPool[CurrObjIndex].NextIndex; - } - else -#endif - { - /* No further free actions available */ - g_pCB->FreePoolIdx = MAX_CONCURRENT_ACTIONS; - } - } - else - { - _SlDrvProtectionObjUnLock(); - return CurrObjIndex; - } - g_pCB->ObjPool[CurrObjIndex].ActionID = (_u8)ActionID; - if (SL_MAX_SOCKETS > SocketID) - { - g_pCB->ObjPool[CurrObjIndex].AdditionalData = SocketID; - } -#ifndef SL_TINY_EXT - /*In case this action is socket related, SocketID bit will be on - In case SocketID is set to SL_MAX_SOCKETS, the socket is not relevant to the action. In that case ActionID bit will be on */ - while ( ( (SL_MAX_SOCKETS > SocketID) && (g_pCB->ActiveActionsBitmap & (1<ActiveActionsBitmap & (1<ObjPool[CurrObjIndex].NextIndex = g_pCB->PendingPoolIdx; - g_pCB->PendingPoolIdx = CurrObjIndex; - _SlDrvProtectionObjUnLock(); - - /* wait for action to be free */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[CurrObjIndex].SyncObj); - - /* set params and move to active (remove from pending list at _SlDrvReleasePoolObj) */ - _SlDrvProtectionObjLockWaitForever(); - } -#endif - /* mark as active. Set socket as active if action is on socket, otherwise mark action as active */ - if (SL_MAX_SOCKETS > SocketID) - { - g_pCB->ActiveActionsBitmap |= (1<ActiveActionsBitmap |= (1<ObjPool[CurrObjIndex].NextIndex = g_pCB->ActivePoolIdx; - g_pCB->ActivePoolIdx = CurrObjIndex; - /* unlock */ - _SlDrvProtectionObjUnLock(); - return CurrObjIndex; -} - -/* ******************************************************************************/ -/* _SlDrvReleasePoolObj */ -/* ******************************************************************************/ -void _SlDrvReleasePoolObj(_u8 ObjIdx) -{ -#ifndef SL_TINY_EXT - _u8 PendingIndex; -#endif - - _SlDrvProtectionObjLockWaitForever(); - - /* In Tiny mode, there is only one object pool so no pending actions are available */ -#ifndef SL_TINY_EXT - /* go over the pending list and release other pending action if needed */ - PendingIndex = g_pCB->PendingPoolIdx; - - while(MAX_CONCURRENT_ACTIONS > PendingIndex) - { - /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */ - if ( (g_pCB->ObjPool[PendingIndex].ActionID == g_pCB->ObjPool[ObjIdx].ActionID) && - ( (SL_MAX_SOCKETS == (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK)) || - ((SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)) && ( (g_pCB->ObjPool[PendingIndex].AdditionalData & BSD_SOCKET_ID_MASK) == (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK) ))) ) - { - /* remove from pending list */ - _SlRemoveFromList(&g_pCB->PendingPoolIdx, PendingIndex); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[PendingIndex].SyncObj); - break; - } - PendingIndex = g_pCB->ObjPool[PendingIndex].NextIndex; - } -#endif - - if (SL_MAX_SOCKETS > (g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)) - { - /* unset socketID */ - g_pCB->ActiveActionsBitmap &= ~(1<<(g_pCB->ObjPool[ObjIdx].AdditionalData & BSD_SOCKET_ID_MASK)); - } - else - { - /* unset actionID */ - g_pCB->ActiveActionsBitmap &= ~(1<ObjPool[ObjIdx].ActionID); - } - - /* delete old data */ - g_pCB->ObjPool[ObjIdx].pRespArgs = NULL; - g_pCB->ObjPool[ObjIdx].ActionID = 0; - g_pCB->ObjPool[ObjIdx].AdditionalData = SL_MAX_SOCKETS; - - /* remove from active list */ - _SlRemoveFromList(&g_pCB->ActivePoolIdx, ObjIdx); - /* move to free list */ - g_pCB->ObjPool[ObjIdx].NextIndex = g_pCB->FreePoolIdx; - g_pCB->FreePoolIdx = ObjIdx; - _SlDrvProtectionObjUnLock(); -} - - -/* ******************************************************************************/ -/* _SlRemoveFromList */ -/* ******************************************************************************/ -void _SlRemoveFromList(_u8 *ListIndex, _u8 ItemIndex) -{ -#ifndef SL_TINY_EXT - _u8 Idx; -#endif - - if (MAX_CONCURRENT_ACTIONS == g_pCB->ObjPool[*ListIndex].NextIndex) - { - *ListIndex = MAX_CONCURRENT_ACTIONS; - } - /* As MAX_CONCURRENT_ACTIONS is equal to 1 in Tiny mode */ -#ifndef SL_TINY_EXT - /* need to remove the first item in the list and therefore update the global which holds this index */ - else if (*ListIndex == ItemIndex) - { - *ListIndex = g_pCB->ObjPool[ItemIndex].NextIndex; - } - else - { - Idx = *ListIndex; - - while(MAX_CONCURRENT_ACTIONS > Idx) - { - /* remove from list */ - if (g_pCB->ObjPool[Idx].NextIndex == ItemIndex) - { - g_pCB->ObjPool[Idx].NextIndex = g_pCB->ObjPool[ItemIndex].NextIndex; - break; - } - - Idx = g_pCB->ObjPool[Idx].NextIndex; - } - } -#endif -} - - -/* ******************************************************************************/ -/* _SlFindAndSetActiveObj */ -/* ******************************************************************************/ -_SlReturnVal_t _SlFindAndSetActiveObj(_SlOpcode_t Opcode, _u8 Sd) -{ - _u8 ActiveIndex; - - ActiveIndex = g_pCB->ActivePoolIdx; - /* go over the active list if exist to find obj waiting for this Async event */ -#ifndef SL_TINY_EXT - while (MAX_CONCURRENT_ACTIONS > ActiveIndex) -#else - /* Only one Active action is availabe in tiny mode, so we can replace the loop with if condition */ - if (MAX_CONCURRENT_ACTIONS > ActiveIndex) -#endif - { - /* unset the Ipv4\IPv6 bit in the opcode if family bit was set */ - if (g_pCB->ObjPool[ActiveIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) - { - Opcode &= ~SL_OPCODE_IPV6; - } - - if ((g_pCB->ObjPool[ActiveIndex].ActionID == RECV_ID) && (Sd == g_pCB->ObjPool[ActiveIndex].AdditionalData) && - ( (SL_OPCODE_SOCKET_RECVASYNCRESPONSE == Opcode) || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE == Opcode) -#ifndef SL_TINY_EXT - || (SL_OPCODE_SOCKET_RECVFROMASYNCRESPONSE_V6 == Opcode) -#endif - ) - - ) - { - g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex; - return SL_RET_CODE_OK; - } - /* In case this action is socket related, SocketID is in use, otherwise will be set to SL_MAX_SOCKETS */ - if ( (_SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].ActionAsyncOpcode == Opcode) && - ( ((Sd == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK) ) && (SL_MAX_SOCKETS > Sd)) || (SL_MAX_SOCKETS == (g_pCB->ObjPool[ActiveIndex].AdditionalData & BSD_SOCKET_ID_MASK)) ) ) - { - /* set handler */ - g_pCB->FunctionParams.AsyncExt.AsyncEvtHandler = _SlActionLookupTable[ g_pCB->ObjPool[ActiveIndex].ActionID - MAX_SOCKET_ENUM_IDX].AsyncEventHandler; - g_pCB->FunctionParams.AsyncExt.ActionIndex = ActiveIndex; - return SL_RET_CODE_OK; - } - ActiveIndex = g_pCB->ObjPool[ActiveIndex].NextIndex; - } - - return SL_RET_CODE_SELF_ERROR; - - - -} - - -/* Wrappers for the object functions */ - -void _SlDrvSyncObjWaitForever(_SlSyncObj_t *pSyncObj) -{ - OSI_RET_OK_CHECK(sl_SyncObjWait(pSyncObj, SL_OS_WAIT_FOREVER)); -} - -void _SlDrvSyncObjSignal(_SlSyncObj_t *pSyncObj) -{ - OSI_RET_OK_CHECK(sl_SyncObjSignal(pSyncObj)); -} - -void _SlDrvObjLockWaitForever(_SlLockObj_t *pLockObj) -{ - OSI_RET_OK_CHECK(sl_LockObjLock(pLockObj, SL_OS_WAIT_FOREVER)); -} - -void _SlDrvProtectionObjLockWaitForever() -{ - OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER)); - -} - -void _SlDrvObjUnLock(_SlLockObj_t *pLockObj) -{ - OSI_RET_OK_CHECK(sl_LockObjUnlock(pLockObj)); - -} - -void _SlDrvProtectionObjUnLock() -{ - OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj)); -} - - -void _SlDrvMemZero(void* Addr, _u16 size) -{ - sl_Memset(Addr, 0, size); -} - - -void _SlDrvResetCmdExt(_SlCmdExt_t* pCmdExt) -{ - _SlDrvMemZero(pCmdExt, sizeof (_SlCmdExt_t)); -} - - - - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/flowcont.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/flowcont.c deleted file mode 100644 index 889241ea..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/flowcont.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * flowcont.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" -#include "flowcont.h" - - -/*****************************************************************************/ -/* _SlDrvFlowContInit */ -/*****************************************************************************/ -void _SlDrvFlowContInit(void) -{ - g_pCB->FlowContCB.TxPoolCnt = FLOW_CONT_MIN; - - OSI_RET_OK_CHECK(sl_LockObjCreate(&g_pCB->FlowContCB.TxLockObj, "TxLockObj")); - - OSI_RET_OK_CHECK(sl_SyncObjCreate(&g_pCB->FlowContCB.TxSyncObj, "TxSyncObj")); -} - -/*****************************************************************************/ -/* _SlDrvFlowContDeinit */ -/*****************************************************************************/ -void _SlDrvFlowContDeinit(void) -{ - g_pCB->FlowContCB.TxPoolCnt = 0; - - OSI_RET_OK_CHECK(sl_LockObjDelete(&g_pCB->FlowContCB.TxLockObj)); - - OSI_RET_OK_CHECK(sl_SyncObjDelete(&g_pCB->FlowContCB.TxSyncObj)); -} - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/fs.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/fs.c deleted file mode 100644 index cc2e9987..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/fs.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * fs.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define sl_min(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX_NVMEM_CHUNK_SIZE 1460 - -/*****************************************************************************/ -/* Internal functions */ -/*****************************************************************************/ - -/*****************************************************************************/ -/* _sl_Strlen */ -/*****************************************************************************/ -_u16 _sl_Strlen(const _u8 *buffer) -{ - _u16 len = 0; - if( buffer != NULL ) - { - while(*buffer++) len++; - } - return len; -} - -/*****************************************************************************/ -/* _sl_GetCreateFsMode */ -/*****************************************************************************/ -_u32 _sl_GetCreateFsMode(_u32 maxSizeInBytes,_u32 accessFlags) -{ - _u32 granIdx = 0; - _u32 granNum = 0; - _u32 granTable[_FS_MAX_MODE_SIZE_GRAN] = {256,1024,4096,16384,65536}; - for(granIdx= _FS_MODE_SIZE_GRAN_256B ;granIdx< _FS_MAX_MODE_SIZE_GRAN;granIdx++) - { - if( granTable[granIdx]*255 >= maxSizeInBytes ) - break; - } - granNum = maxSizeInBytes/granTable[granIdx]; - if( maxSizeInBytes % granTable[granIdx] != 0 ) - granNum++; - - return _FS_MODE(_FS_MODE_OPEN_WRITE_CREATE_IF_NOT_EXIST, granIdx, granNum, accessFlags); -} - -/*****************************************************************************/ -/* API functions */ -/*****************************************************************************/ - -/*****************************************************************************/ -/* sl_FsOpen */ -/*****************************************************************************/ -typedef union -{ - _FsOpenCommand_t Cmd; - _FsOpenResponse_t Rsp; -}_SlFsOpenMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsOpen) - -const _SlCmdCtrl_t _SlFsOpenCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEOPEN, - sizeof(_FsOpenCommand_t), - sizeof(_FsOpenResponse_t) -}; - -_i32 sl_FsOpen(const _u8 *pFileName,const _u32 AccessModeAndMaxSize, _u32 *pToken,_i32 *pFileHandle) -{ - _SlReturnVal_t RetVal; - _SlFsOpenMsg_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8*)pFileName; - CmdExt.pRxPayload = NULL; - - Msg.Cmd.Mode = AccessModeAndMaxSize; - - if(pToken != NULL) - { - Msg.Cmd.Token = *pToken; - } - else - { - Msg.Cmd.Token = 0; - } - - RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsOpenCmdCtrl, &Msg, &CmdExt); - *pFileHandle = Msg.Rsp.FileHandle; - if (pToken != NULL) - { - *pToken = Msg.Rsp.Token; - } - - /* in case of an error, return the erros file handler as an error code */ - if( *pFileHandle < 0 ) - { - return *pFileHandle; - } - return (_i32)RetVal; -} -#endif - -/*****************************************************************************/ -/* sl_FsClose */ -/*****************************************************************************/ -typedef union -{ - _FsCloseCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlFsCloseMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsClose) - -const _SlCmdCtrl_t _SlFsCloseCmdCtrl = -{ - SL_OPCODE_NVMEM_FILECLOSE, - sizeof(_FsCloseCommand_t), - sizeof(_FsCloseResponse_t) -}; - -_i16 sl_FsClose(const _i32 FileHdl, const _u8* pCeritificateFileName,const _u8* pSignature ,const _u32 SignatureLen) -{ - _SlFsCloseMsg_u Msg = {{0, 0}}; - _SlCmdExt_t ExtCtrl; - - Msg.Cmd.FileHandle = FileHdl; - if( pCeritificateFileName != NULL ) - { - Msg.Cmd.CertificFileNameLength = (_sl_Strlen(pCeritificateFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - } - Msg.Cmd.SignatureLen = SignatureLen; - - ExtCtrl.TxPayloadLen = ((SignatureLen+3) & (~3)); /* align */ - ExtCtrl.pTxPayload = (_u8*)pSignature; - ExtCtrl.RxPayloadLen = (_i16)Msg.Cmd.CertificFileNameLength; - ExtCtrl.pRxPayload = (_u8*)pCeritificateFileName; /* Add signature */ - - if(ExtCtrl.pRxPayload != NULL && ExtCtrl.RxPayloadLen != 0) - { - ExtCtrl.RxPayloadLen = ExtCtrl.RxPayloadLen * (-1); - } - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsCloseCmdCtrl, &Msg, &ExtCtrl)); - - return (_i16)((_i16)Msg.Rsp.status); -} -#endif - - -/*****************************************************************************/ -/* sl_FsRead */ -/*****************************************************************************/ -typedef union -{ - _FsReadCommand_t Cmd; - _FsReadResponse_t Rsp; -}_SlFsReadMsg_u; - -#if _SL_INCLUDE_FUNC(sl_FsRead) - - -const _SlCmdCtrl_t _SlFsReadCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEREADCOMMAND, - sizeof(_FsReadCommand_t), - sizeof(_FsReadResponse_t) -}; - -_i32 sl_FsRead(const _i32 FileHdl,_u32 Offset, _u8* pData,_u32 Len) -{ - _SlFsReadMsg_u Msg; - _SlCmdExt_t ExtCtrl; - _u16 ChunkLen; - _SlReturnVal_t RetVal =0; - _i32 RetCount = 0; - - ExtCtrl.TxPayloadLen = 0; - ExtCtrl.pTxPayload = NULL; - - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.RxPayloadLen = ChunkLen; - ExtCtrl.pRxPayload = (_u8 *)(pData); - Msg.Cmd.Offset = Offset; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - do - { - RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsReadCmdCtrl, &Msg, &ExtCtrl); - if(SL_OS_RET_CODE_OK == RetVal) - { - if( Msg.Rsp.status < 0) - { - if( RetCount > 0) - { - return RetCount; - } - else - { - return Msg.Rsp.status; - } - } - RetCount += (_i32)Msg.Rsp.status; - Len -= ChunkLen; - Offset += ChunkLen; - Msg.Cmd.Offset = Offset; - ExtCtrl.pRxPayload += ChunkLen; - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.RxPayloadLen = ChunkLen; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - } - else - { - return RetVal; - } - }while(ChunkLen > 0); - - return (_i32)RetCount; -} -#endif - -/*****************************************************************************/ -/* sl_FsWrite */ -/*****************************************************************************/ -typedef union -{ - _FsWriteCommand_t Cmd; - _FsWriteResponse_t Rsp; -}_SlFsWriteMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsWrite) - -const _SlCmdCtrl_t _SlFsWriteCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEWRITECOMMAND, - sizeof(_FsWriteCommand_t), - sizeof(_FsWriteResponse_t) -}; - -_i32 sl_FsWrite(const _i32 FileHdl,_u32 Offset, _u8* pData,_u32 Len) -{ - _SlFsWriteMsg_u Msg; - _SlCmdExt_t ExtCtrl; - _u16 ChunkLen; - _SlReturnVal_t RetVal; - _i32 RetCount = 0; - - ExtCtrl.RxPayloadLen = 0; - ExtCtrl.pRxPayload = NULL; - - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.TxPayloadLen = ChunkLen; - ExtCtrl.pTxPayload = (_u8 *)(pData); - Msg.Cmd.Offset = Offset; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - - do - { - - RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsWriteCmdCtrl, &Msg, &ExtCtrl); - if(SL_OS_RET_CODE_OK == RetVal) - { - if( Msg.Rsp.status < 0) - { - if( RetCount > 0) - { - return RetCount; - } - else - { - return Msg.Rsp.status; - } - } - - RetCount += (_i32)Msg.Rsp.status; - Len -= ChunkLen; - Offset += ChunkLen; - Msg.Cmd.Offset = Offset; - ExtCtrl.pTxPayload += ChunkLen; - ChunkLen = (_u16)sl_min(MAX_NVMEM_CHUNK_SIZE,Len); - ExtCtrl.TxPayloadLen = ChunkLen; - Msg.Cmd.Len = ChunkLen; - Msg.Cmd.FileHandle = FileHdl; - } - else - { - return RetVal; - } - }while(ChunkLen > 0); - - return (_i32)RetCount; -} -#endif - -/*****************************************************************************/ -/* sl_FsGetInfo */ -/*****************************************************************************/ -typedef union -{ - _FsGetInfoCommand_t Cmd; - _FsGetInfoResponse_t Rsp; -}_SlFsGetInfoMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsGetInfo) - - -const _SlCmdCtrl_t _SlFsGetInfoCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEGETINFOCOMMAND, - sizeof(_FsGetInfoCommand_t), - sizeof(_FsGetInfoResponse_t) -}; - -_i16 sl_FsGetInfo(const _u8 *pFileName,const _u32 Token,SlFsFileInfo_t* pFsFileInfo) -{ - _SlFsGetInfoMsg_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8*)pFileName; - CmdExt.pRxPayload = NULL; - Msg.Cmd.Token = Token; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsGetInfoCmdCtrl, &Msg, &CmdExt)); - - pFsFileInfo->flags = Msg.Rsp.flags; - pFsFileInfo->FileLen = Msg.Rsp.FileLen; - pFsFileInfo->AllocatedLen = Msg.Rsp.AllocatedLen; - pFsFileInfo->Token[0] = Msg.Rsp.Token[0]; - pFsFileInfo->Token[1] = Msg.Rsp.Token[1]; - pFsFileInfo->Token[2] = Msg.Rsp.Token[2]; - pFsFileInfo->Token[3] = Msg.Rsp.Token[3]; - return (_i16)((_i16)Msg.Rsp.Status); -} -#endif - -/*****************************************************************************/ -/* sl_FsDel */ -/*****************************************************************************/ -typedef union -{ - _FsDeleteCommand_t Cmd; - _FsDeleteResponse_t Rsp; -}_SlFsDeleteMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_FsDel) - -const _SlCmdCtrl_t _SlFsDeleteCmdCtrl = -{ - SL_OPCODE_NVMEM_FILEDELCOMMAND, - sizeof(_FsDeleteCommand_t), - sizeof(_FsDeleteResponse_t) -}; - -_i16 sl_FsDel(const _u8 *pFileName,const _u32 Token) -{ - _SlFsDeleteMsg_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (_sl_Strlen(pFileName)+4) & (~3); /* add 4: 1 for NULL and the 3 for align */ - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8*)pFileName; - CmdExt.pRxPayload = NULL; - Msg.Cmd.Token = Token; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlFsDeleteCmdCtrl, &Msg, &CmdExt)); - - return (_i16)((_i16)Msg.Rsp.status); -} -#endif diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/netapp.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/netapp.c deleted file mode 100644 index 11bcdefa..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/netapp.c +++ /dev/null @@ -1,1304 +0,0 @@ -/* - * netapp.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT ((_u32)0x1 << 31) - -#ifdef SL_TINY -#define NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH 63 -#else -#define NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH 255 -#endif - - -/*****************************************************************************/ -/* Functions prototypes */ -/*****************************************************************************/ -void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf); - -#ifndef SL_TINY_EXT -void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf); -void _sl_HandleAsync_PingResponse(void *pVoidBuf); -#endif - -void CopyPingResultsToReport(_PingReportResponse_t *pResults,SlPingReport_t *pReport); -_i16 sl_NetAppMDNSRegisterUnregisterService(const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - const _u32 Options); - -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) -_u16 _sl_NetAppSendTokenValue(slHttpServerData_t * Token); -#endif -typedef union -{ - _NetAppStartStopCommand_t Cmd; - _NetAppStartStopResponse_t Rsp; -}_SlNetAppStartStopMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppStart) - -const _SlCmdCtrl_t _SlNetAppStartCtrl = -{ - SL_OPCODE_NETAPP_START_COMMAND, - sizeof(_NetAppStartStopCommand_t), - sizeof(_NetAppStartStopResponse_t) -}; - -_i16 sl_NetAppStart(const _u32 AppBitMap) -{ - _SlNetAppStartStopMsg_u Msg; - Msg.Cmd.appId = AppBitMap; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppStartCtrl, &Msg, NULL)); - - return Msg.Rsp.status; -} -#endif - -/***************************************************************************** - sl_NetAppStop -*****************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_NetAppStop) - - -const _SlCmdCtrl_t _SlNetAppStopCtrl = -{ - SL_OPCODE_NETAPP_STOP_COMMAND, - sizeof(_NetAppStartStopCommand_t), - sizeof(_NetAppStartStopResponse_t) -}; - - - -_i16 sl_NetAppStop(const _u32 AppBitMap) -{ - _SlNetAppStartStopMsg_u Msg; - Msg.Cmd.appId = AppBitMap; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppStopCtrl, &Msg, NULL)); - - return Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_NetAppGetServiceList */ -/******************************************************************************/ -typedef struct -{ - _u8 IndexOffest; - _u8 MaxServiceCount; - _u8 Flags; - _i8 Padding; -}NetappGetServiceListCMD_t; - -typedef union -{ - NetappGetServiceListCMD_t Cmd; - _BasicResponse_t Rsp; -}_SlNetappGetServiceListMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppGetServiceList) - -const _SlCmdCtrl_t _SlGetServiceListeCtrl = -{ - SL_OPCODE_NETAPP_NETAPP_MDNS_LOOKUP_SERVICE, - sizeof(NetappGetServiceListCMD_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_NetAppGetServiceList(const _u8 IndexOffest, - const _u8 MaxServiceCount, - const _u8 Flags, - _i8 *pBuffer, - const _u32 RxBufferLength - ) -{ - - _i32 retVal= 0; - _SlNetappGetServiceListMsg_u Msg; - _SlCmdExt_t CmdExt; - _u16 ServiceSize = 0; - _u16 BufferSize = 0; - - /* - Calculate RX pBuffer size - WARNING: - if this size is BufferSize than 1480 error should be returned because there - is no place in the RX packet. - */ - switch(Flags) - { - case SL_NET_APP_FULL_SERVICE_WITH_TEXT_IPV4_TYPE: - ServiceSize = sizeof(SlNetAppGetFullServiceWithTextIpv4List_t); - break; - - case SL_NET_APP_FULL_SERVICE_IPV4_TYPE: - ServiceSize = sizeof(SlNetAppGetFullServiceIpv4List_t); - break; - - case SL_NET_APP_SHORT_SERVICE_IPV4_TYPE: - ServiceSize = sizeof(SlNetAppGetShortServiceIpv4List_t); - break; - - default: - ServiceSize = sizeof(_BasicResponse_t); - break; - } - - - - BufferSize = MaxServiceCount * ServiceSize; - - /*Check the size of the requested services is smaller than size of the user buffer. - If not an error is returned in order to avoid overwriting memory. */ - if(RxBufferLength <= BufferSize) - { - return SL_ERROR_NETAPP_RX_BUFFER_LENGTH_ERROR; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = BufferSize; - CmdExt.pRxPayload = (_u8 *)pBuffer; - - Msg.Cmd.IndexOffest = IndexOffest; - Msg.Cmd.MaxServiceCount = MaxServiceCount; - Msg.Cmd.Flags = Flags; - Msg.Cmd.Padding = 0; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetServiceListeCtrl, &Msg, &CmdExt)); - retVal = Msg.Rsp.status; - - return (_i16)retVal; -} - -#endif - -/*****************************************************************************/ -/* sl_mDNSRegisterService */ -/*****************************************************************************/ -/* - * The below struct depicts the constant parameters of the command/API RegisterService. - * - 1. ServiceLen - The length of the service should be smaller than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - 2. TextLen - The length of the text should be smaller than NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - 3. port - The port on this target host. - 4. TTL - The TTL of the service - 5. Options - bitwise parameters: - bit 0 - is unique (means if the service needs to be unique) - bit 31 - for internal use if the service should be added or deleted (set means ADD). - bit 1-30 for future. - - NOTE: - - 1. There are another variable parameter is this API which is the service name and the text. - 2. According to now there is no warning and Async event to user on if the service is a unique. -* - */ - - -typedef struct -{ - _u8 ServiceNameLen; - _u8 TextLen; - _u16 Port; - _u32 TTL; - _u32 Options; -}NetappMdnsSetService_t; - -typedef union -{ - NetappMdnsSetService_t Cmd; - _BasicResponse_t Rsp; -}_SlNetappMdnsRegisterServiceMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterUnregisterService) - -const _SlCmdCtrl_t _SlRegisterServiceCtrl = -{ - SL_OPCODE_NETAPP_MDNSREGISTERSERVICE, - sizeof(NetappMdnsSetService_t), - sizeof(_BasicResponse_t) -}; - -/****************************************************************************** - - sl_NetAppMDNSRegisterService - - CALLER user from its host - - - DESCRIPTION: - Add/delete service - The function manipulates the command that register the service and call - to the NWP in order to add/delete the service to/from the mDNS package and to/from the DB. - - This register service is a service offered by the application. - This unregister service is a service offered by the application before. - - The service name should be full service name according to RFC - of the DNS-SD - means the value in name field in SRV answer. - - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - If the option is_unique is set, mDNS probes the service name to make sure - it is unique before starting to announce the service on the network. - Instance is the instance portion of the service name. - - - - - PARAMETERS: - - The command is from constant parameters and variables parameters. - - Constant parameters are: - - ServiceLen - The length of the service. - TextLen - The length of the service should be smaller than 64. - port - The port on this target host. - TTL - The TTL of the service - Options - bitwise parameters: - bit 0 - is unique (means if the service needs to be unique) - bit 31 - for internal use if the service should be added or deleted (set means ADD). - bit 1-30 for future. - - The variables parameters are: - - Service name(full service name) - The service name. - Example for service name: - 1. PC1._ipp._tcp.local - 2. PC2_server._ftp._tcp.local - - Text - The description of the service. - should be as mentioned in the RFC - (according to type of the service IPP,FTP...) - - NOTE - pay attention - - 1. Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - If it is - An error is returned. - - 2. According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) - - - - RETURNS: Status - the immediate response of the command status. - 0 means success. - - - -******************************************************************************/ -_i16 sl_NetAppMDNSRegisterUnregisterService( const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - const _u32 Options) - -{ - _SlNetappMdnsRegisterServiceMsg_u Msg; - _SlCmdExt_t CmdExt ; - _i8 ServiceNameAndTextBuffer[NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH]; - _i8 *TextPtr; - - /* - - NOTE - pay attention - - 1. Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - If it is - An error is returned. - - 2. According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) - - - */ - - /*build the attribute part of the command. - It contains the constant parameters of the command*/ - - Msg.Cmd.ServiceNameLen = ServiceNameLen; - Msg.Cmd.Options = Options; - Msg.Cmd.Port = Port; - Msg.Cmd.TextLen = TextLen; - Msg.Cmd.TTL = TTL; - - /*Build the payload part of the command - Copy the service name and text to one buffer. - NOTE - pay attention - The size of the service length + the text length should be smaller than 255, - Until the simplelink drive supports to variable length through SPI command. */ - if(TextLen + ServiceNameLen > (NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH - 1 )) /*-1 is for giving a place to set null termination at the end of the text*/ - { - return -1; - } - - _SlDrvMemZero(ServiceNameAndTextBuffer, NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH); - - - /*Copy the service name*/ - sl_Memcpy(ServiceNameAndTextBuffer, - pServiceName, - ServiceNameLen); - - if(TextLen > 0 ) - { - - TextPtr = &ServiceNameAndTextBuffer[ServiceNameLen]; - /*Copy the text just after the service name*/ - sl_Memcpy(TextPtr, - pText, - TextLen); - - - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (TextLen + ServiceNameLen); - CmdExt.pTxPayload = (_u8 *)ServiceNameAndTextBuffer; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRegisterServiceCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; - - -} -#endif - -/**********************************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSRegisterService) - -_i16 sl_NetAppMDNSRegisterService( const _i8* pServiceName, - const _u8 ServiceNameLen, - const _i8* pText, - const _u8 TextLen, - const _u16 Port, - const _u32 TTL, - _u32 Options) - -{ - - /* - - NOTE - pay attention - - 1. Temporary - there is an allocation on stack of internal buffer. - Its size is NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - It means that the sum of the text length and service name length cannot be bigger than - NETAPP_MDNS_MAX_SERVICE_NAME_AND_TEXT_LENGTH. - If it is - An error is returned. - - 2. According to now from certain constraints the variables parameters are set in the - attribute part (contain constant parameters) - - */ - - /*Set the add service bit in the options parameter. - In order not use different opcodes for the register service and unregister service - bit 31 in option is taken for this purpose. if it is set it means in NWP that the service should be added - if it is cleared it means that the service should be deleted and there is only meaning to pServiceName - and ServiceNameLen values. */ - Options |= NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT; - - return sl_NetAppMDNSRegisterUnregisterService( pServiceName, - ServiceNameLen, - pText, - TextLen, - Port, - TTL, - Options); - - -} -#endif -/**********************************************************************************************/ - - - -/**********************************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_NetAppMDNSUnRegisterService) - -_i16 sl_NetAppMDNSUnRegisterService( const _i8* pServiceName, - const _u8 ServiceNameLen) - - -{ - _u32 Options = 0; - - /* - - NOTE - pay attention - - The size of the service length should be smaller than 255, - Until the simplelink drive supports to variable length through SPI command. - - - */ - - /*Clear the add service bit in the options parameter. - In order not use different opcodes for the register service and unregister service - bit 31 in option is taken for this purpose. if it is set it means in NWP that the service should be added - if it is cleared it means that the service should be deleted and there is only meaning to pServiceName - and ServiceNameLen values.*/ - - Options &= (~NETAPP_MDNS_OPTIONS_ADD_SERVICE_BIT); - - return sl_NetAppMDNSRegisterUnregisterService( pServiceName, - ServiceNameLen, - NULL, - 0, - 0, - 0, - Options); - - -} -#endif -/**********************************************************************************************/ - - - -/*****************************************************************************/ -/* sl_DnsGetHostByService */ -/*****************************************************************************/ -/* - * The below struct depicts the constant parameters of the command/API sl_DnsGetHostByService. - * - 1. ServiceLen - The length of the service should be smaller than 255. - 2. AddrLen - TIPv4 or IPv6 (SL_AF_INET , SL_AF_INET6). -* - */ - -typedef struct -{ - _u8 ServiceLen; - _u8 AddrLen; - _u16 Padding; -}_GetHostByServiceCommand_t; - - - -/* - * The below structure depict the constant parameters that are returned in the Async event answer - * according to command/API sl_DnsGetHostByService for IPv4 and IPv6. - * - 1Status - The status of the response. - 2.Address - Contains the IP address of the service. - 3.Port - Contains the port of the service. - 4.TextLen - Contains the max length of the text that the user wants to get. - it means that if the test of service is bigger that its value than - the text is cut to inout_TextLen value. - Output: Contain the length of the text that is returned. Can be full text or part - of the text (see above). - -* - */ -typedef struct -{ - _u16 Status; - _u16 TextLen; - _u32 Port; - _u32 Address; -}_GetHostByServiceIPv4AsyncResponse_t; - - -typedef struct -{ - _u16 Status; - _u16 TextLen; - _u32 Port; - _u32 Address[4]; -}_GetHostByServiceIPv6AsyncResponse_t; - - -typedef union -{ - _GetHostByServiceIPv4AsyncResponse_t IpV4; - _GetHostByServiceIPv6AsyncResponse_t IpV6; -}_GetHostByServiceAsyncResponseAttribute_u; - -/* - * The below struct contains pointers to the output parameters that the user gives - * - */ -typedef struct -{ - _i16 Status; - _u32 *out_pAddr; - _u32 *out_pPort; - _u16 *inout_TextLen; /* in: max len , out: actual len */ - _i8 *out_pText; -}_GetHostByServiceAsyncResponse_t; - - -typedef union -{ - _GetHostByServiceCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlGetHostByServiceMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByService) - -const _SlCmdCtrl_t _SlGetHostByServiceCtrl = -{ - SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICE, - sizeof(_GetHostByServiceCommand_t), - sizeof(_BasicResponse_t) -}; - -/******************************************************************************/ - -_i32 sl_NetAppDnsGetHostByService(_i8 *pServiceName, /* string containing all (or only part): name + subtype + service */ - const _u8 ServiceLen, - const _u8 Family, /* 4-IPv4 , 16-IPv6 */ - _u32 pAddr[], - _u32 *pPort, - _u16 *pTextLen, /* in: max len , out: actual len */ - _i8 *pText - ) -{ - _SlGetHostByServiceMsg_u Msg; - _SlCmdExt_t CmdExt ; - _GetHostByServiceAsyncResponse_t AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - -/* - Note: - 1. The return's attributes are belonged to first service that is found. - It can be other services with the same service name will response to - the query. The results of these responses are saved in the peer cache of the NWP, and - should be read by another API. - - 2. Text length can be 120 bytes only - not more - It is because of constraints in the NWP on the buffer that is allocated for the Async event. - - 3.The API waits to Async event by blocking. It means that the API is finished only after an Async event - is sent by the NWP. - - 4.No rolling option!!! - only PTR type is sent. - - -*/ - /*build the attribute part of the command. - It contains the constant parameters of the command */ - - Msg.Cmd.ServiceLen = ServiceLen; - Msg.Cmd.AddrLen = Family; - - /*Build the payload part of the command - Copy the service name and text to one buffer.*/ - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = ServiceLen; - CmdExt.pTxPayload = (_u8 *)pServiceName; - - /*set pointers to the output parameters (the returned parameters). - This pointers are belonged to local struct that is set to global Async response parameter. - It is done in order not to run more than one sl_DnsGetHostByService at the same time. - The API should be run only if global parameter is pointed to NULL. */ - AsyncRsp.out_pText = pText; - AsyncRsp.inout_TextLen = (_u16* )pTextLen; - AsyncRsp.out_pPort = pPort; - AsyncRsp.out_pAddr = (_u32 *)pAddr; - - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, GETHOSYBYSERVICE_ID, SL_MAX_SOCKETS); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - - if (SL_AF_INET6 == Family) - { - g_pCB->ObjPool[ObjIdx].AdditionalData |= SL_NETAPP_FAMILY_MASK; - } - /* Send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetHostByServiceCtrl, &Msg, &CmdExt)); - - - - /* If the immediate reponse is O.K. than wait for aSYNC event response. */ - if(SL_RET_CODE_OK == Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - /* If we are - it means that Async event was sent. - The results are copied in the Async handle return functions */ - - Msg.Rsp.status = AsyncRsp.Status; - } - - _SlDrvReleasePoolObj(ObjIdx); - return Msg.Rsp.status; -} -#endif - -/******************************************************************************/ - -/****************************************************************************** - _sl_HandleAsync_DnsGetHostByService - - CALLER NWP - Async event on sl_DnsGetHostByService with IPv4 Family - - - DESCRIPTION: - - Async event on sl_DnsGetHostByService command with IPv4 Family. - Return service attributes like IP address, port and text according to service name. - The user sets a service name Full/Part (see example below), and should get the: - 1. IP of the service - 2. The port of service. - 3. The text of service. - - Hence it can make a connection to the specific service and use it. - It is similar to get host by name method. - - It is done by a single shot query with PTR type on the service name. - - - - Note: - 1. The return's attributes are belonged to first service that is found. - It can be other services with the same service name will response to - the query. The results of these responses are saved in the peer cache of the NWP, and - should be read by another API. - - - PARAMETERS: - - pVoidBuf - is point to opcode of the event. - it contains the outputs that are given to the user - - outputs description: - - 1.out_pAddr[] - output: Contain the IP address of the service. - 2.out_pPort - output: Contain the port of the service. - 3.inout_TextLen - Input: Contain the max length of the text that the user wants to get. - it means that if the test of service is bigger that its value than - the text is cut to inout_TextLen value. - Output: Contain the length of the text that is returned. Can be full text or part - of the text (see above). - - 4.out_pText - Contain the text of the service (full or part see above- inout_TextLen description). - - * - - - RETURNS: success or fail. - - - - - -******************************************************************************/ -#ifndef SL_TINY_EXT -void _sl_HandleAsync_DnsGetHostByService(void *pVoidBuf) -{ - - _GetHostByServiceAsyncResponse_t* Res; - _u16 TextLen; - _u16 UserTextLen; - - - /*pVoidBuf - is point to opcode of the event.*/ - - /*set pMsgArgs to point to the attribute of the event.*/ - _GetHostByServiceIPv4AsyncResponse_t *pMsgArgs = (_GetHostByServiceIPv4AsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - /*IPv6*/ - if(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) - { - return; - } - /*IPv4*/ - else - { - /************************************************************************************************* - - 1. Copy the attribute part of the evnt to the attribute part of the response - sl_Memcpy(g_pCB->GetHostByServiceCB.pAsyncRsp, pMsgArgs, sizeof(_GetHostByServiceIPv4AsyncResponse_t)); - - set to TextLen the text length of the service.*/ - TextLen = pMsgArgs->TextLen; - - /*Res pointed to mDNS global object struct */ - Res = (_GetHostByServiceAsyncResponse_t*)g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs; - - - - /*It is 4 bytes so we avoid from memcpy*/ - Res->out_pAddr[0] = pMsgArgs->Address; - Res->out_pPort[0] = pMsgArgs->Port; - Res->Status = pMsgArgs->Status; - - /*set to TextLen the text length of the user (input fromthe user).*/ - UserTextLen = Res->inout_TextLen[0]; - - /*Cut the service text if the user requested for smaller text.*/ - UserTextLen = (TextLen <= UserTextLen) ? TextLen : UserTextLen; - Res->inout_TextLen[0] = UserTextLen ; - - /************************************************************************************************** - - 2. Copy the payload part of the evnt (the text) to the payload part of the response - the lenght of the copy is according to the text length in the attribute part. */ - - - sl_Memcpy(Res->out_pText , - (_i8 *)(& pMsgArgs[1]) , /* & pMsgArgs[1] -> 1st byte after the fixed header = 1st byte of variable text.*/ - UserTextLen ); - - - /**************************************************************************************************/ - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - return; - } -} - -/*****************************************************************************/ -/* _sl_HandleAsync_DnsGetHostByAddr */ -/*****************************************************************************/ -void _sl_HandleAsync_DnsGetHostByAddr(void *pVoidBuf) -{ - SL_TRACE0(DBG_MSG, MSG_303, "STUB: _sl_HandleAsync_DnsGetHostByAddr not implemented yet!"); - return; -} -#endif - -/*****************************************************************************/ -/* sl_DnsGetHostByName */ -/*****************************************************************************/ -typedef union -{ - _GetHostByNameIPv4AsyncResponse_t IpV4; - _GetHostByNameIPv6AsyncResponse_t IpV6; -}_GetHostByNameAsyncResponse_u; - -typedef union -{ - _GetHostByNameCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlGetHostByNameMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppDnsGetHostByName) -const _SlCmdCtrl_t _SlGetHostByNameCtrl = -{ - SL_OPCODE_NETAPP_DNSGETHOSTBYNAME, - sizeof(_GetHostByNameCommand_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_NetAppDnsGetHostByName(_i8 * hostname,const _u16 usNameLen, _u32* out_ip_addr,const _u8 family) -{ - _SlGetHostByNameMsg_u Msg; - _SlCmdExt_t ExtCtrl; - _GetHostByNameAsyncResponse_u AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - - _SlDrvResetCmdExt(&ExtCtrl); - ExtCtrl.TxPayloadLen = usNameLen; - ExtCtrl.pTxPayload = (_u8 *)hostname; - - Msg.Cmd.Len = usNameLen; - Msg.Cmd.family = family; - - /*Use Obj to issue the command, if not available try later */ - ObjIdx = (_u8)_SlDrvWaitForPoolObj(GETHOSYBYNAME_ID,SL_MAX_SOCKETS); - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - _SlDrvProtectionObjLockWaitForever(); - - g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&AsyncRsp; - /*set bit to indicate IPv6 address is expected */ - if (SL_AF_INET6 == family) - { - g_pCB->ObjPool[ObjIdx].AdditionalData |= SL_NETAPP_FAMILY_MASK; - } - - _SlDrvProtectionObjUnLock(); - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetHostByNameCtrl, &Msg, &ExtCtrl)); - - if(SL_RET_CODE_OK == Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - Msg.Rsp.status = AsyncRsp.IpV4.status; - - if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) - { - sl_Memcpy((_i8 *)out_ip_addr, - (_i8 *)&AsyncRsp.IpV4.ip0, - (SL_AF_INET == family) ? SL_IPV4_ADDRESS_SIZE : SL_IPV6_ADDRESS_SIZE); - } - } - _SlDrvReleasePoolObj(ObjIdx); - return Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* _sl_HandleAsync_DnsGetHostByName */ -/******************************************************************************/ -void _sl_HandleAsync_DnsGetHostByName(void *pVoidBuf) -{ - _GetHostByNameIPv4AsyncResponse_t *pMsgArgs = (_GetHostByNameIPv4AsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - /*IPv6 */ - if(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].AdditionalData & SL_NETAPP_FAMILY_MASK) - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_GetHostByNameIPv6AsyncResponse_t)); - } - /*IPv4 */ - else - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_GetHostByNameIPv4AsyncResponse_t)); - } - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - return; -} - - -#ifndef SL_TINY_EXT -void CopyPingResultsToReport(_PingReportResponse_t *pResults,SlPingReport_t *pReport) -{ - pReport->PacketsSent = pResults->numSendsPings; - pReport->PacketsReceived = pResults->numSuccsessPings; - pReport->MinRoundTime = pResults->rttMin; - pReport->MaxRoundTime = pResults->rttMax; - pReport->AvgRoundTime = pResults->rttAvg; - pReport->TestTime = pResults->testTime; -} - -/*****************************************************************************/ -/* _sl_HandleAsync_PingResponse */ -/*****************************************************************************/ -void _sl_HandleAsync_PingResponse(void *pVoidBuf) -{ - _PingReportResponse_t *pMsgArgs = (_PingReportResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - SlPingReport_t pingReport; - - if(pPingCallBackFunc) - { - CopyPingResultsToReport(pMsgArgs,&pingReport); - pPingCallBackFunc(&pingReport); - } - else - { - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_SOCKET_CB(NULL != g_pCB->PingCB.PingAsync.pAsyncRsp); - - if (NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs) - { - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_PingReportResponse_t)); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - } - _SlDrvProtectionObjUnLock(); - } - return; -} -#endif - -/*****************************************************************************/ -/* sl_PingStart */ -/*****************************************************************************/ -typedef union -{ - _PingStartCommand_t Cmd; - _PingReportResponse_t Rsp; -}_SlPingStartMsg_u; - - -typedef enum -{ - CMD_PING_TEST_RUNNING = 0, - CMD_PING_TEST_STOPPED -}_SlPingStatus_e; - - -#if _SL_INCLUDE_FUNC(sl_NetAppPingStart) -_i16 sl_NetAppPingStart(const SlPingStartCommand_t* pPingParams,const _u8 family,SlPingReport_t *pReport,const P_SL_DEV_PING_CALLBACK pPingCallback) -{ - _SlCmdCtrl_t CmdCtrl = {0, sizeof(_PingStartCommand_t), sizeof(_BasicResponse_t)}; - _SlPingStartMsg_u Msg; - _PingReportResponse_t PingRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - if( 0 == pPingParams->Ip ) - {/* stop any ongoing ping */ - return _SlDrvBasicCmd(SL_OPCODE_NETAPP_PINGSTOP); - } - - if(SL_AF_INET == family) - { - CmdCtrl.Opcode = SL_OPCODE_NETAPP_PINGSTART; - sl_Memcpy(&Msg.Cmd.ip0, &pPingParams->Ip, SL_IPV4_ADDRESS_SIZE); - } - else - { - CmdCtrl.Opcode = SL_OPCODE_NETAPP_PINGSTART_V6; - sl_Memcpy(&Msg.Cmd.ip0, &pPingParams->Ip, SL_IPV6_ADDRESS_SIZE); - } - - Msg.Cmd.pingIntervalTime = pPingParams->PingIntervalTime; - Msg.Cmd.PingSize = pPingParams->PingSize; - Msg.Cmd.pingRequestTimeout = pPingParams->PingRequestTimeout; - Msg.Cmd.totalNumberOfAttempts = pPingParams->TotalNumberOfAttempts; - Msg.Cmd.flags = pPingParams->Flags; - - - if( pPingCallback ) - { - pPingCallBackFunc = pPingCallback; - } - else - { - /*Use Obj to issue the command, if not available try later */ - ObjIdx = (_u8)_SlDrvWaitForPoolObj(PING_ID,SL_MAX_SOCKETS); - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - OSI_RET_OK_CHECK(sl_LockObjLock(&g_pCB->ProtectionLockObj, SL_OS_WAIT_FOREVER)); - /* async response handler for non callback mode */ - g_pCB->ObjPool[ObjIdx].pRespArgs = (_u8 *)&PingRsp; - pPingCallBackFunc = NULL; - OSI_RET_OK_CHECK(sl_LockObjUnlock(&g_pCB->ProtectionLockObj)); - } - - - VERIFY_RET_OK(_SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); - /*send the command*/ - if(CMD_PING_TEST_RUNNING == (_i16)Msg.Rsp.status || CMD_PING_TEST_STOPPED == (_i16)Msg.Rsp.status ) - { - /* block waiting for results if no callback function is used */ - if( NULL == pPingCallback ) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - if( SL_OS_RET_CODE_OK == (_i16)PingRsp.status ) - { - CopyPingResultsToReport(&PingRsp,pReport); - } - _SlDrvReleasePoolObj(ObjIdx); - } - } - else - { /* ping failure, no async response */ - if( NULL == pPingCallback ) - { - _SlDrvReleasePoolObj(ObjIdx); - } - } - - return Msg.Rsp.status; -} -#endif - -/*****************************************************************************/ -/* sl_NetAppSet */ -/*****************************************************************************/ -typedef union -{ - _NetAppSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlNetAppMsgSet_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppSet) - -const _SlCmdCtrl_t _SlNetAppSetCmdCtrl = -{ - SL_OPCODE_NETAPP_NETAPPSET, - sizeof(_NetAppSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i32 sl_NetAppSet(const _u8 AppId ,const _u8 Option,const _u8 OptionLen,const _u8 *pOptionValue) -{ - _SlNetAppMsgSet_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (OptionLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pOptionValue; - - - Msg.Cmd.AppId = AppId; - Msg.Cmd.ConfigLen = OptionLen; - Msg.Cmd.ConfigOpt = Option; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/*****************************************************************************/ -/* sl_NetAppSendTokenValue */ -/*****************************************************************************/ -typedef union -{ - sl_NetAppHttpServerSendToken_t Cmd; - _BasicResponse_t Rsp; -}_SlNetAppMsgSendTokenValue_u; - - - -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) -const _SlCmdCtrl_t _SlNetAppSendTokenValueCmdCtrl = -{ - SL_OPCODE_NETAPP_HTTPSENDTOKENVALUE, - sizeof(sl_NetAppHttpServerSendToken_t), - sizeof(_BasicResponse_t) -}; - -_u16 _sl_NetAppSendTokenValue(slHttpServerData_t * Token_value) -{ - _SlNetAppMsgSendTokenValue_u Msg; - _SlCmdExt_t CmdExt; - - CmdExt.TxPayloadLen = (Token_value->value_len+3) & (~3); - CmdExt.RxPayloadLen = 0; - CmdExt.pTxPayload = (_u8 *) Token_value->token_value; - CmdExt.pRxPayload = NULL; - - Msg.Cmd.token_value_len = Token_value->value_len; - Msg.Cmd.token_name_len = Token_value->name_len; - sl_Memcpy(&Msg.Cmd.token_name[0], Token_value->token_name, Token_value->name_len); - - - VERIFY_RET_OK(_SlDrvCmdSend((_SlCmdCtrl_t *)&_SlNetAppSendTokenValueCmdCtrl, &Msg, &CmdExt)); - - return Msg.Rsp.status; -} -#endif - - -/*****************************************************************************/ -/* sl_NetAppGet */ -/*****************************************************************************/ -typedef union -{ - _NetAppSetGet_t Cmd; - _NetAppSetGet_t Rsp; -}_SlNetAppMsgGet_u; - - -#if _SL_INCLUDE_FUNC(sl_NetAppGet) -const _SlCmdCtrl_t _SlNetAppGetCmdCtrl = -{ - SL_OPCODE_NETAPP_NETAPPGET, - sizeof(_NetAppSetGet_t), - sizeof(_NetAppSetGet_t) -}; - -_i32 sl_NetAppGet(const _u8 AppId,const _u8 Option,_u8 *pOptionLen, _u8 *pOptionValue) -{ - _SlNetAppMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pOptionLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pOptionLen; - CmdExt.pRxPayload = (_u8 *)pOptionValue; - - Msg.Cmd.AppId = AppId; - Msg.Cmd.ConfigOpt = Option; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetAppGetCmdCtrl, &Msg, &CmdExt)); - - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pOptionLen = (_u8)CmdExt.RxPayloadLen; - return SL_ESMALLBUF; - } - else - { - *pOptionLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - return (_i16)Msg.Rsp.Status; -} -#endif - - -/*****************************************************************************/ -/* _SlDrvNetAppEventHandler */ -/*****************************************************************************/ -void _SlDrvNetAppEventHandler(void* pArgs) -{ - _SlResponseHeader_t *pHdr = (_SlResponseHeader_t *)pArgs; -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) - SlHttpServerEvent_t httpServerEvent; - SlHttpServerResponse_t httpServerResponse; -#endif - - switch(pHdr->GenHeader.Opcode) - { - case SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE: - case SL_OPCODE_NETAPP_DNSGETHOSTBYNAMEASYNCRESPONSE_V6: - _sl_HandleAsync_DnsGetHostByName(pArgs); - break; -#ifndef SL_TINY_EXT - case SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE: - case SL_OPCODE_NETAPP_MDNSGETHOSTBYSERVICEASYNCRESPONSE_V6: - _sl_HandleAsync_DnsGetHostByService(pArgs); - break; - case SL_OPCODE_NETAPP_PINGREPORTREQUESTRESPONSE: - _sl_HandleAsync_PingResponse(pArgs); - break; -#endif - -#if defined(sl_HttpServerCallback) || defined(EXT_LIB_REGISTERED_HTTP_SERVER_EVENTS) - case SL_OPCODE_NETAPP_HTTPGETTOKENVALUE: - { - _u8 *pTokenName; - slHttpServerData_t Token_value; - sl_NetAppHttpServerGetToken_t *httpGetToken = (sl_NetAppHttpServerGetToken_t *)_SL_RESP_ARGS_START(pHdr); - pTokenName = (_u8 *)((sl_NetAppHttpServerGetToken_t *)httpGetToken + 1); - - httpServerResponse.Response = SL_NETAPP_HTTPSETTOKENVALUE; - httpServerResponse.ResponseData.token_value.len = MAX_TOKEN_VALUE_LEN; - - /* Reuse the async buffer for getting the token value response from the user */ - httpServerResponse.ResponseData.token_value.data = (_u8 *)_SL_RESP_ARGS_START(pHdr) + MAX_TOKEN_NAME_LEN; - - httpServerEvent.Event = SL_NETAPP_HTTPGETTOKENVALUE_EVENT; - httpServerEvent.EventData.httpTokenName.len = httpGetToken->token_name_len; - httpServerEvent.EventData.httpTokenName.data = pTokenName; - - Token_value.token_name = pTokenName; - - _SlDrvHandleHttpServerEvents (&httpServerEvent, &httpServerResponse); - - Token_value.value_len = httpServerResponse.ResponseData.token_value.len; - Token_value.name_len = httpServerEvent.EventData.httpTokenName.len; - Token_value.token_value = httpServerResponse.ResponseData.token_value.data; - - - _sl_NetAppSendTokenValue(&Token_value); - } - break; - - case SL_OPCODE_NETAPP_HTTPPOSTTOKENVALUE: - { - _u8 *pPostParams; - - sl_NetAppHttpServerPostToken_t *httpPostTokenArgs = (sl_NetAppHttpServerPostToken_t *)_SL_RESP_ARGS_START(pHdr); - pPostParams = (_u8 *)((sl_NetAppHttpServerPostToken_t *)httpPostTokenArgs + 1); - - httpServerEvent.Event = SL_NETAPP_HTTPPOSTTOKENVALUE_EVENT; - - httpServerEvent.EventData.httpPostData.action.len = httpPostTokenArgs->post_action_len; - httpServerEvent.EventData.httpPostData.action.data = pPostParams; - pPostParams+=httpPostTokenArgs->post_action_len; - - httpServerEvent.EventData.httpPostData.token_name.len = httpPostTokenArgs->token_name_len; - httpServerEvent.EventData.httpPostData.token_name.data = pPostParams; - pPostParams+=httpPostTokenArgs->token_name_len; - - httpServerEvent.EventData.httpPostData.token_value.len = httpPostTokenArgs->token_value_len; - httpServerEvent.EventData.httpPostData.token_value.data = pPostParams; - - httpServerResponse.Response = SL_NETAPP_RESPONSE_NONE; - - _SlDrvHandleHttpServerEvents (&httpServerEvent, &httpServerResponse); - - } - break; -#endif - - - default: - SL_ERROR_TRACE2(MSG_305, "ASSERT: _SlDrvNetAppEventHandler : invalid opcode = 0x%x = %1", pHdr->GenHeader.Opcode, pHdr->GenHeader.Opcode); - VERIFY_PROTOCOL(0); - } -} - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/netcfg.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/netcfg.c deleted file mode 100644 index 3674e072..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/netcfg.c +++ /dev/null @@ -1,150 +0,0 @@ -/* -* netcfg.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* sl_NetCfgSet */ -/*****************************************************************************/ -typedef union -{ - _NetCfgSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlNetCfgMsgSet_u; - -#if _SL_INCLUDE_FUNC(sl_NetCfgSet) - -const _SlCmdCtrl_t _SlNetCfgSetCmdCtrl = -{ - SL_OPCODE_DEVICE_NETCFG_SET_COMMAND, - sizeof(_NetCfgSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i32 sl_NetCfgSet(const _u8 ConfigId ,const _u8 ConfigOpt,const _u8 ConfigLen,const _u8 *pValues) -{ - _SlNetCfgMsgSet_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pValues; - - - Msg.Cmd.ConfigId = ConfigId; - Msg.Cmd.ConfigLen = ConfigLen; - Msg.Cmd.ConfigOpt = ConfigOpt; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetCfgSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/*****************************************************************************/ -/* sl_NetCfgGet */ -/*****************************************************************************/ -typedef union -{ - _NetCfgSetGet_t Cmd; - _NetCfgSetGet_t Rsp; -}_SlNetCfgMsgGet_u; - -#if _SL_INCLUDE_FUNC(sl_NetCfgGet) - -const _SlCmdCtrl_t _SlNetCfgGetCmdCtrl = -{ - SL_OPCODE_DEVICE_NETCFG_GET_COMMAND, - sizeof(_NetCfgSetGet_t), - sizeof(_NetCfgSetGet_t) -}; - -_i32 sl_NetCfgGet(const _u8 ConfigId, _u8 *pConfigOpt,_u8 *pConfigLen, _u8 *pValues) -{ - _SlNetCfgMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pConfigLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pConfigLen; - CmdExt.pRxPayload = (_u8 *)pValues; - Msg.Cmd.ConfigLen = *pConfigLen; - Msg.Cmd.ConfigId = ConfigId; - - if( pConfigOpt ) - { - Msg.Cmd.ConfigOpt = (_u16)*pConfigOpt; - } - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlNetCfgGetCmdCtrl, &Msg, &CmdExt)); - - if( pConfigOpt ) - { - *pConfigOpt = (_u8)Msg.Rsp.ConfigOpt; - } - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pConfigLen = (_u8)CmdExt.RxPayloadLen; - if( SL_MAC_ADDRESS_GET == ConfigId ) - { - return SL_RET_CODE_OK; /* sp fix */ - } - else - { - return SL_ESMALLBUF; - } - } - else - { - *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - return (_i16)Msg.Rsp.Status; -} -#endif - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/nonos.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/nonos.c deleted file mode 100644 index a20e8957..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/nonos.c +++ /dev/null @@ -1,171 +0,0 @@ -/* -* nonos.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -#ifndef SL_PLATFORM_MULTI_THREADED - -#include "nonos.h" - -#ifndef SL_TINY_EXT -#define NONOS_MAX_SPAWN_ENTRIES 5 -#else -#define NONOS_MAX_SPAWN_ENTRIES 1 -#endif - - -typedef struct -{ - _SlSpawnEntryFunc_t pEntry; - void* pValue; -}_SlNonOsSpawnEntry_t; - -typedef struct -{ - _SlNonOsSpawnEntry_t SpawnEntries[NONOS_MAX_SPAWN_ENTRIES]; -}_SlNonOsCB_t; - -_SlNonOsCB_t g__SlNonOsCB; - - -_SlNonOsRetVal_t _SlNonOsSemSet(_SlNonOsSemObj_t* pSemObj , _SlNonOsSemObj_t Value) -{ - *pSemObj = Value; - return NONOS_RET_OK; -} - -_SlNonOsRetVal_t _SlNonOsSemGet(_SlNonOsSemObj_t* pSyncObj, _SlNonOsSemObj_t WaitValue, _SlNonOsSemObj_t SetValue, _SlNonOsTime_t Timeout) -{ -#ifdef _SlSyncWaitLoopCallback - _SlNonOsTime_t timeOutRequest = Timeout; -#endif - while (Timeout>0) - { - if (WaitValue == *pSyncObj) - { - *pSyncObj = SetValue; - break; - } - if (Timeout != NONOS_WAIT_FOREVER) - { - Timeout--; - } - _SlNonOsMainLoopTask(); -#ifdef _SlSyncWaitLoopCallback - if( (__NON_OS_SYNC_OBJ_SIGNAL_VALUE == WaitValue) && (timeOutRequest != NONOS_NO_WAIT) ) - { - if (WaitValue == *pSyncObj) - { - *pSyncObj = SetValue; - break; - } - _SlSyncWaitLoopCallback(); - } -#endif - } - - if (0 == Timeout) - { - return NONOS_RET_ERR; - } - else - { - return NONOS_RET_OK; - } -} - - -_SlNonOsRetVal_t _SlNonOsSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags) -{ - _i8 i = 0; - -#ifndef SL_TINY_EXT - for (i=0 ; ipEntry) - { - pE->pValue = pValue; - pE->pEntry = pEntry; -#ifndef SL_TINY_EXT - break; -#endif - } - } - - - return NONOS_RET_OK; -} - - -_SlNonOsRetVal_t _SlNonOsMainLoopTask(void) -{ - _i8 i=0; - - -#ifndef SL_TINY_EXT - for (i=0 ; ipEntry; - - if (NULL != pF) - { - if(RxIrqCnt != (g_pCB)->RxDoneCnt) - { - pF(0); /* (pValue) */ - } - - pE->pEntry = NULL; - pE->pValue = NULL; - } - } - - return NONOS_RET_OK; -} - - -#endif /*(SL_PLATFORM != SL_PLATFORM_NON_OS)*/ diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/socket.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/socket.c deleted file mode 100644 index 8ef9e097..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/socket.c +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * socket.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - - -void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u *pCmd); -void _sl_HandleAsync_Connect(void *pVoidBuf); - -#ifndef SL_TINY_EXT -void _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen); -void _sl_HandleAsync_Accept(void *pVoidBuf); -void _sl_HandleAsync_Select(void *pVoidBuf); -#endif -_u16 _sl_TruncatePayloadByProtocol(const _i16 pSd, const _u16 length); - -/*******************************************************************************/ -/* Functions */ -/*******************************************************************************/ - - - /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */ - /* is possible as _i32 as these parameters are in the same offset and size for these */ - /* three families. */ -#define SL_SOCKET_PAYLOAD_BASE (1350) - -const _u8 _SlPayloadByProtocolLUT[16] = -{ - (1472 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4 */ - (1460 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4 */ - (1452 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6 */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6 */ - (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV4_SECURE */ - (1386 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV4_SECURE */ - (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_UDP_IPV6_SECURE */ - (1396 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_TCP_IPV6_SECURE */ - (1476 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER */ - (1514 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_PACKET */ - (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP4 */ - (1480 - SL_SOCKET_PAYLOAD_BASE), /* SL_SOCKET_PAYLOAD_TYPE_RAW_IP6 */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ - (1440 - SL_SOCKET_PAYLOAD_BASE), /* Default */ - (1440 - SL_SOCKET_PAYLOAD_BASE) /* Default */ -}; - - - -/* ******************************************************************************/ -/* _sl_BuildAddress */ -/* ******************************************************************************/ -void _sl_BuildAddress(const SlSockAddr_t *addr, _SocketAddrCommand_u *pCmd) -{ - - /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 - is possible as long as these parameters are in the same offset and size for these - three families. */ - pCmd->IpV4.FamilyAndFlags = (addr->sa_family << 4) & 0xF0; - pCmd->IpV4.port = ((SlSockAddrIn_t *)addr)->sin_port; - - if(SL_AF_INET == addr->sa_family) - { - pCmd->IpV4.address = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr; - } - else if (SL_AF_INET6_EUI_48 == addr->sa_family ) - { - sl_Memcpy( pCmd->IpV6EUI48.address,((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, 6); - } -#ifdef SL_SUPPORT_IPV6 - else - { - sl_Memcpy(pCmd->IpV6.address, ((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, 16 ); - } -#endif -} - - -/***************************************************************************** - _sl_TruncatePayloadByProtocol -*****************************************************************************/ -_u16 _sl_TruncatePayloadByProtocol(const _i16 sd, const _u16 length) -{ - unsigned int maxLength; - - - maxLength = SL_SOCKET_PAYLOAD_BASE + _SlPayloadByProtocolLUT[((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) >> 4)]; - - - - if( length > maxLength ) - { - return maxLength; - } - else - { - return length; - } -} - -/*******************************************************************************/ -/* _sl_ParseAddress */ -/*******************************************************************************/ - -#ifndef SL_TINY_EXT -void _sl_ParseAddress(_SocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen) -{ - /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */ - /* is possible as long as these parameters are in the same offset and size for these */ - /* three families. */ - addr->sa_family = pRsp->IpV4.family; - ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.port; - - *addrlen = (SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t); - - if(SL_AF_INET == addr->sa_family) - { - ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = pRsp->IpV4.address; - } - else if (SL_AF_INET6_EUI_48 == addr->sa_family ) - { - sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, pRsp->IpV6EUI48.address, 6); - } -#ifdef SL_SUPPORT_IPV6 - else - { - sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.address, 16); - } -#endif -} - -#endif - -/*******************************************************************************/ -/* sl_Socket */ -/*******************************************************************************/ -typedef union -{ - _u32 Dummy; - _SocketCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSockSocketMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_Socket) - -const _SlCmdCtrl_t _SlSockSocketCmdCtrl = -{ - SL_OPCODE_SOCKET_SOCKET, - sizeof(_SocketCommand_t), - sizeof(_SocketResponse_t) -}; - -_i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol) -{ - _SlSockSocketMsg_u Msg; - - Msg.Cmd.Domain = (_u8)Domain; - Msg.Cmd.Type = (_u8)Type; - Msg.Cmd.Protocol = (_u8)Protocol; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL)); - - if( Msg.Rsp.statusOrLen < 0 ) - { - return( Msg.Rsp.statusOrLen ); - } - else - { - return (_i16)((_u8)Msg.Rsp.sd); -} -} -#endif - -/*******************************************************************************/ -/* sl_Close */ -/*******************************************************************************/ -typedef union -{ - _CloseCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSockCloseMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_Close) - -const _SlCmdCtrl_t _SlSockCloseCmdCtrl = -{ - SL_OPCODE_SOCKET_CLOSE, - sizeof(_CloseCommand_t), - sizeof(_SocketResponse_t) -}; - -_i16 sl_Close(_i16 sd) -{ - _SlSockCloseMsg_u Msg; - - Msg.Cmd.sd = (_u8)sd; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL)); - - return Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_Bind */ -/*******************************************************************************/ -typedef union -{ - _SocketAddrCommand_u Cmd; - _SocketResponse_t Rsp; -}_SlSockBindMsg_u; - -#if _SL_INCLUDE_FUNC(sl_Bind) -_i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen) -{ - _SlSockBindMsg_u Msg; - _SlCmdCtrl_t CmdCtrl = {0, 0, sizeof(_SocketResponse_t)}; - - switch(addr->sa_family) - { - case SL_AF_INET : - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); - break; -#ifndef SL_TINY_EXT - case SL_AF_INET6_EUI_48: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); - break; - -#ifdef SL_SUPPORT_IPV6 - case AF_INET6: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); - break; -#endif -#endif - - - case SL_AF_RF : - default: - return SL_RET_CODE_INVALID_INPUT; - } - - Msg.Cmd.IpV4.lenOrPadding = 0; - Msg.Cmd.IpV4.sd = (_u8)sd; - - _sl_BuildAddress(addr, &Msg.Cmd); - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); - - return Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_Sendto */ -/*******************************************************************************/ -typedef union -{ - _SocketAddrCommand_u Cmd; - /* no response for 'sendto' commands*/ -}_SlSendtoMsg_u; - -#if _SL_INCLUDE_FUNC(sl_SendTo) -_i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen) -{ - _SlSendtoMsg_u Msg; - _SlCmdCtrl_t CmdCtrl = {0, 0, 0}; - _SlCmdExt_t CmdExt; - _u16 ChunkLen; - _i16 RetVal; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (_u16)Len; - CmdExt.pTxPayload = (_u8 *)pBuf; - - switch(to->sa_family) - { - case SL_AF_INET: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); - break; -#ifndef SL_TINY_EXT - case SL_AF_INET6_EUI_48: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); - break; -#ifdef SL_SUPPORT_IPV6 - case AF_INET6: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); - break; -#endif -#endif - case SL_AF_RF: - default: - return SL_RET_CODE_INVALID_INPUT; - } - - ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len); - Msg.Cmd.IpV4.lenOrPadding = ChunkLen; - CmdExt.TxPayloadLen = ChunkLen; - - Msg.Cmd.IpV4.sd = (_u8)sd; - - _sl_BuildAddress(to, &Msg.Cmd); - - Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F; - - do - { - RetVal = _SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt); - - if(SL_OS_RET_CODE_OK == RetVal) - { - CmdExt.pTxPayload += ChunkLen; - ChunkLen = (_u16)((_u8 *)pBuf + Len - CmdExt.pTxPayload); - ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen); - CmdExt.TxPayloadLen = ChunkLen; - Msg.Cmd.IpV4.lenOrPadding = ChunkLen; - } - else - { - return RetVal; - } - }while(ChunkLen > 0); - - return (_i16)Len; -} -#endif - -/*******************************************************************************/ -/* sl_Recvfrom */ -/*******************************************************************************/ -typedef union -{ - _sendRecvCommand_t Cmd; - _SocketAddrResponse_u Rsp; -}_SlRecvfromMsg_u; - -const _SlCmdCtrl_t _SlRecvfomCmdCtrl = -{ - SL_OPCODE_SOCKET_RECVFROM, - sizeof(_sendRecvCommand_t), - sizeof(_SocketAddrResponse_u) -}; - - - -#if _SL_INCLUDE_FUNC(sl_RecvFrom) -_i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen) -{ - _SlRecvfromMsg_u Msg; - _SlCmdExt_t CmdExt; - _i16 RetVal; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = Len; - CmdExt.pRxPayload = (_u8 *)buf; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.StatusOrLen = Len; - /* no size truncation in recv path */ - CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen; - - - Msg.Cmd.FamilyAndFlags = flags & 0x0F; - - - if(sizeof(SlSockAddrIn_t) == *fromlen) - { - Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4); - } - else if (sizeof(SlSockAddrIn6_t) == *fromlen) - { - Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4); - } - else - { - return SL_RET_CODE_INVALID_INPUT; - } - - RetVal = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt); - if( RetVal != SL_OS_RET_CODE_OK ) - { - return RetVal; - } - - RetVal = Msg.Rsp.IpV4.statusOrLen; - - if(RetVal >= 0) - { - VERIFY_PROTOCOL(sd == Msg.Rsp.IpV4.sd); -#if 0 - _sl_ParseAddress(&Msg.Rsp, from, fromlen); -#else - from->sa_family = Msg.Rsp.IpV4.family; - if(SL_AF_INET == from->sa_family) - { - ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.port; - ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.address; - *fromlen = sizeof(SlSockAddrIn_t); - } - else if (SL_AF_INET6_EUI_48 == from->sa_family ) - { - ((SlSockAddrIn6_t *)from)->sin6_port = Msg.Rsp.IpV6EUI48.port; - sl_Memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u8, Msg.Rsp.IpV6EUI48.address, 6); - } -#ifdef SL_SUPPORT_IPV6 - else if(AF_INET6 == from->sa_family) - { - VERIFY_PROTOCOL(*fromlen >= sizeof(sockaddr_in6)); - - ((sockaddr_in6 *)from)->sin6_port = Msg.Rsp.IpV6.port; - sl_Memcpy(((sockaddr_in6 *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.address, 16); - *fromlen = sizeof(sockaddr_in6); - } -#endif -#endif - } - - return (_i16)RetVal; -} -#endif - -/*******************************************************************************/ -/* sl_Connect */ -/*******************************************************************************/ -typedef union -{ - _SocketAddrCommand_u Cmd; - _SocketResponse_t Rsp; -}_SlSockConnectMsg_u; - -#if _SL_INCLUDE_FUNC(sl_Connect) -_i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen) -{ - _SlSockConnectMsg_u Msg; - _SlReturnVal_t RetVal; - _SlCmdCtrl_t CmdCtrl = {0, 0, sizeof(_SocketResponse_t)}; - _SocketResponse_t AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - - switch(addr->sa_family) - { - case SL_AF_INET : - CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv4Command_t); - /* Do nothing - cmd already initialized to this type */ - break; - case SL_AF_INET6_EUI_48: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6EUI48Command_t); - break; -#ifdef SL_SUPPORT_IPV6 - case AF_INET6: - CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6; - CmdCtrl.TxDescLen = sizeof(_SocketAddrIPv6Command_t); - break; -#endif - case SL_AF_RF: - default: - return SL_RET_CODE_INVALID_INPUT; - } - - Msg.Cmd.IpV4.lenOrPadding = 0; - Msg.Cmd.IpV4.sd = (_u8)sd; - - _sl_BuildAddress(addr, &Msg.Cmd); - - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CONNECT_ID, sd & BSD_SOCKET_ID_MASK); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - /* send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL)); - VERIFY_PROTOCOL(Msg.Rsp.sd == sd) - - RetVal = Msg.Rsp.statusOrLen; - - if(SL_RET_CODE_OK == RetVal) - { - /* wait for async and get Data Read parameters */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - VERIFY_PROTOCOL(AsyncRsp.sd == sd); - - RetVal = AsyncRsp.statusOrLen; - } - - - - _SlDrvReleasePoolObj(ObjIdx); - return RetVal; -} - -#endif - - -/*******************************************************************************/ -/* _sl_HandleAsync_Connect */ -/*******************************************************************************/ -void _sl_HandleAsync_Connect(void *pVoidBuf) -{ - _SocketResponse_t *pMsgArgs = (_SocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_PROTOCOL((pMsgArgs->sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS); - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - - ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->sd = pMsgArgs->sd; - ((_SocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->statusOrLen = pMsgArgs->statusOrLen; - - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - return; -} - -/*******************************************************************************/ -/* sl_Send */ -/*******************************************************************************/ -typedef union -{ - _sendRecvCommand_t Cmd; - /* no response for 'sendto' commands*/ -}_SlSendMsg_u; - -const _SlCmdCtrl_t _SlSendCmdCtrl = -{ - SL_OPCODE_SOCKET_SEND, - sizeof(_sendRecvCommand_t), - 0 -}; - -#if _SL_INCLUDE_FUNC(sl_Send) -_i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags) -{ - _SlSendMsg_u Msg; - _SlCmdExt_t CmdExt; - _u16 ChunkLen; - _i16 RetVal; - _u32 tempVal; - _u8 runSingleChunk = FALSE; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = Len; - CmdExt.pTxPayload = (_u8 *)pBuf; - - /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */ - if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER) - { - tempVal = flags; - CmdExt.pRxPayload = (_u8 *)&tempVal; - CmdExt.RxPayloadLen = -4; /* mark as Rx data to send */ - runSingleChunk = TRUE; - } - else - { - CmdExt.pRxPayload = NULL; - } - - ChunkLen = _sl_TruncatePayloadByProtocol(sd,Len); - CmdExt.TxPayloadLen = ChunkLen; - Msg.Cmd.StatusOrLen = ChunkLen; - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.FamilyAndFlags |= flags & 0x0F; - - do - { - RetVal = _SlDrvDataWriteOp((_u8)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt); - if(SL_OS_RET_CODE_OK == RetVal) - { - CmdExt.pTxPayload += ChunkLen; - ChunkLen = (_u8 *)pBuf + Len - CmdExt.pTxPayload; - ChunkLen = _sl_TruncatePayloadByProtocol(sd,ChunkLen); - CmdExt.TxPayloadLen = ChunkLen; - Msg.Cmd.StatusOrLen = ChunkLen; - } - else - { - return RetVal; - } - }while((ChunkLen > 0) && (runSingleChunk==FALSE)); - - return (_i16)Len; -} -#endif - -/*******************************************************************************/ -/* sl_Listen */ -/*******************************************************************************/ -typedef union -{ - _ListenCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlListenMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_Listen) - -const _SlCmdCtrl_t _SlListenCmdCtrl = -{ - SL_OPCODE_SOCKET_LISTEN, - sizeof(_ListenCommand_t), - sizeof(_BasicResponse_t), -}; - -_i16 sl_Listen(_i16 sd, _i16 backlog) -{ - _SlListenMsg_u Msg; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.backlog = (_u8)backlog; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/*******************************************************************************/ -/* sl_Accept */ -/*******************************************************************************/ -typedef union -{ - _AcceptCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSockAcceptMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_Accept) - -const _SlCmdCtrl_t _SlAcceptCmdCtrl = -{ - SL_OPCODE_SOCKET_ACCEPT, - sizeof(_AcceptCommand_t), - sizeof(_BasicResponse_t), -}; - -_i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen) -{ - _SlSockAcceptMsg_u Msg; - _SlReturnVal_t RetVal; - _SocketAddrResponse_u AsyncRsp; - - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.family = (sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6; - - - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, ACCEPT_ID, sd & BSD_SOCKET_ID_MASK ); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - /* send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL)); - VERIFY_PROTOCOL(Msg.Rsp.sd == sd); - - RetVal = Msg.Rsp.statusOrLen; - - if(SL_OS_RET_CODE_OK == RetVal) - { - /* wait for async and get Data Read parameters */ - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - VERIFY_PROTOCOL(AsyncRsp.IpV4.sd == sd); - - RetVal = AsyncRsp.IpV4.statusOrLen; - if( (NULL != addr) && (NULL != addrlen) ) - { -#if 0 /* Kept for backup */ - _sl_ParseAddress(&AsyncRsp, addr, addrlen); -#else - addr->sa_family = AsyncRsp.IpV4.family; - - if(SL_AF_INET == addr->sa_family) - { - if( *addrlen == sizeof( SlSockAddrIn_t ) ) - { - ((SlSockAddrIn_t *)addr)->sin_port = AsyncRsp.IpV4.port; - ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = AsyncRsp.IpV4.address; - } - else - { - *addrlen = 0; - } - } - else if (SL_AF_INET6_EUI_48 == addr->sa_family ) - { - if( *addrlen == sizeof( SlSockAddrIn6_t ) ) - { - ((SlSockAddrIn6_t *)addr)->sin6_port = AsyncRsp.IpV6EUI48.port ; - /* will be called from here and from _sl_BuildAddress*/ - sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u8, AsyncRsp.IpV6EUI48.address, 6); - } - else - { - *addrlen = 0; - } - } -#ifdef SL_SUPPORT_IPV6 - else - { - if( *addrlen == sizeof( sockaddr_in6 ) ) - { - ((sockaddr_in6 *)addr)->sin6_port = AsyncRsp.IpV6.port ; - sl_Memcpy(((sockaddr_in6 *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.address, 16); - } - else - { - *addrlen = 0; - } - } -#endif -#endif - } - } - - _SlDrvReleasePoolObj(ObjIdx); - return (_i16)RetVal; -} -#endif - - -/*******************************************************************************/ -/* sl_Htonl */ -/*******************************************************************************/ -_u32 sl_Htonl( _u32 val ) -{ - _u32 i = 1; - _i8 *p = (_i8 *)&i; - if (p[0] == 1) /* little endian */ - { - p[0] = ((_i8* )&val)[3]; - p[1] = ((_i8* )&val)[2]; - p[2] = ((_i8* )&val)[1]; - p[3] = ((_i8* )&val)[0]; - return i; - } - else /* big endian */ - { - return val; - } -} - -/*******************************************************************************/ -/* sl_Htonl */ -/*******************************************************************************/ -_u16 sl_Htons( _u16 val ) -{ - _i16 i = 1; - _i8 *p = (_i8 *)&i; - if (p[0] == 1) /* little endian */ - { - p[0] = ((_i8* )&val)[1]; - p[1] = ((_i8* )&val)[0]; - return i; - } - else /* big endian */ - { - return val; - } -} - -/*******************************************************************************/ -/* _sl_HandleAsync_Accept */ -/*******************************************************************************/ -#ifndef SL_TINY_EXT -void _sl_HandleAsync_Accept(void *pVoidBuf) -{ - _SocketAddrResponse_u *pMsgArgs = (_SocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_PROTOCOL(( pMsgArgs->IpV4.sd & BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS); - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs,sizeof(_SocketAddrResponse_u)); - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - - _SlDrvProtectionObjUnLock(); - return; -} - -/*******************************************************************************/ -/* _sl_HandleAsync_Select */ -/*******************************************************************************/ -void _sl_HandleAsync_Select(void *pVoidBuf) -{ - _SelectAsyncResponse_t *pMsgArgs = (_SelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf); - - _SlDrvProtectionObjLockWaitForever(); - - VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs); - - sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(_SelectAsyncResponse_t)); - - _SlDrvSyncObjSignal(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj); - _SlDrvProtectionObjUnLock(); - - return; -} - -#endif - -/*******************************************************************************/ -/* sl_Recv */ -/*******************************************************************************/ -typedef union -{ - _sendRecvCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlRecvMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_Recv) - -const _SlCmdCtrl_t _SlRecvCmdCtrl = -{ - SL_OPCODE_SOCKET_RECV, - sizeof(_sendRecvCommand_t), - sizeof(_SocketResponse_t) -}; - - -_i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags) -{ - _SlRecvMsg_u Msg; - _SlCmdExt_t CmdExt; - _SlReturnVal_t status; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = Len; - CmdExt.pRxPayload = (_u8 *)pBuf; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.StatusOrLen = Len; - - /* no size truncation in recv path */ - CmdExt.RxPayloadLen = Msg.Cmd.StatusOrLen; - - Msg.Cmd.FamilyAndFlags = flags & 0x0F; - - status = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt); - if( status != SL_OS_RET_CODE_OK ) - { - return status; - } - - /* if the Device side sends less than expected it is not the Driver's role */ - /* the returned value could be smaller than the requested size */ - return (_i16)Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_SetSockOpt */ -/*******************************************************************************/ -typedef union -{ - _setSockOptCommand_t Cmd; - _SocketResponse_t Rsp; -}_SlSetSockOptMsg_u; - -const _SlCmdCtrl_t _SlSetSockOptCmdCtrl = -{ - SL_OPCODE_SOCKET_SETSOCKOPT, - sizeof(_setSockOptCommand_t), - sizeof(_SocketResponse_t) -}; - -#if _SL_INCLUDE_FUNC(sl_SetSockOpt) -_i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen) -{ - _SlSetSockOptMsg_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = optlen; - CmdExt.pTxPayload = (_u8 *)optval; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.level = (_u8)level; - Msg.Cmd.optionLen = (_u8)optlen; - Msg.Cmd.optionName = (_u8)optname; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.statusOrLen; -} -#endif - -/*******************************************************************************/ -/* sl_GetSockOpt */ -/*******************************************************************************/ -typedef union -{ - _getSockOptCommand_t Cmd; - _getSockOptResponse_t Rsp; -}_SlGetSockOptMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_GetSockOpt) - -const _SlCmdCtrl_t _SlGetSockOptCmdCtrl = -{ - SL_OPCODE_SOCKET_GETSOCKOPT, - sizeof(_getSockOptCommand_t), - sizeof(_getSockOptResponse_t) -}; - -_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen) -{ - _SlGetSockOptMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (*optlen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *optlen; - CmdExt.pRxPayload = optval; - - Msg.Cmd.sd = (_u8)sd; - Msg.Cmd.level = (_u8)level; - Msg.Cmd.optionLen = (_u8)(*optlen); - Msg.Cmd.optionName = (_u8)optname; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt)); - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *optlen = Msg.Rsp.optionLen; - return SL_ESMALLBUF; - } - else - { - *optlen = (_u8)CmdExt.ActualRxPayloadLen; - } - return (_i16)Msg.Rsp.status; -} -#endif - -/*******************************************************************************/ -/* sl_Select */ -/* ******************************************************************************/ -typedef union -{ - _SelectCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlSelectMsg_u; - - - -#ifndef SL_TINY_EXT -#if _SL_INCLUDE_FUNC(sl_Select) - -const _SlCmdCtrl_t _SlSelectCmdCtrl = -{ - SL_OPCODE_SOCKET_SELECT, - sizeof(_SelectCommand_t), - sizeof(_BasicResponse_t) -}; - - -_i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout) -{ - _SlSelectMsg_u Msg; - _SelectAsyncResponse_t AsyncRsp; - _u8 ObjIdx = MAX_CONCURRENT_ACTIONS; - - Msg.Cmd.nfds = (_u8)nfds; - Msg.Cmd.readFdsCount = 0; - Msg.Cmd.writeFdsCount = 0; - - Msg.Cmd.readFds = 0; - Msg.Cmd.writeFds = 0; - - - if( readsds ) - { - Msg.Cmd.readFds = (_u16)readsds->fd_array[0]; - } - if( writesds ) - { - Msg.Cmd.writeFds = (_u16)writesds->fd_array[0]; - } - if( NULL == timeout ) - { - Msg.Cmd.tv_sec = 0xffff; - Msg.Cmd.tv_usec = 0xffff; - } - else - { - if( 0xffff <= timeout->tv_sec ) - { - Msg.Cmd.tv_sec = 0xffff; - } - else - { - Msg.Cmd.tv_sec = (_u16)timeout->tv_sec; - } - timeout->tv_usec = timeout->tv_usec >> 10; /* convert to milliseconds */ - if( 0xffff <= timeout->tv_usec ) - { - Msg.Cmd.tv_usec = 0xffff; - } - else - { - Msg.Cmd.tv_usec = (_u16)timeout->tv_usec; - } - } - - /* Use Obj to issue the command, if not available try later */ - ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS); - - if (MAX_CONCURRENT_ACTIONS == ObjIdx) - { - return SL_POOL_IS_EMPTY; - } - - - /* send the command */ - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL)); - - if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status) - { - _SlDrvSyncObjWaitForever(&g_pCB->ObjPool[ObjIdx].SyncObj); - - Msg.Rsp.status = AsyncRsp.status; - - if( ((_i16)Msg.Rsp.status) >= 0 ) - { - if( readsds ) - { - readsds->fd_array[0] = AsyncRsp.readFds; - } - if( writesds ) - { - writesds->fd_array[0] = AsyncRsp.writeFds; - } - } - } - - _SlDrvReleasePoolObj(ObjIdx); - return (_i16)Msg.Rsp.status; -} - -/* Select helper functions */ -/*******************************************************************************/ -/* SL_FD_SET */ -/* ******************************************************************************/ -void SL_FD_SET(_i16 fd, SlFdSet_t *fdset) -{ - fdset->fd_array[0] |= (1<< (fd & BSD_SOCKET_ID_MASK)); -} -/*******************************************************************************/ -/* SL_FD_CLR */ -/*******************************************************************************/ -void SL_FD_CLR(_i16 fd, SlFdSet_t *fdset) -{ - fdset->fd_array[0] &= ~(1<< (fd & BSD_SOCKET_ID_MASK)); -} -/*******************************************************************************/ -/* SL_FD_ISSET */ -/*******************************************************************************/ -_i16 SL_FD_ISSET(_i16 fd, SlFdSet_t *fdset) -{ - if( fdset->fd_array[0] & (1<< (fd & BSD_SOCKET_ID_MASK)) ) - { - return 1; - } - return 0; -} -/*******************************************************************************/ -/* SL_FD_ZERO */ -/*******************************************************************************/ -void SL_FD_ZERO(SlFdSet_t *fdset) -{ - fdset->fd_array[0] = 0; -} - -#endif -#endif - - - diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/spawn.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/spawn.c deleted file mode 100644 index bb557581..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/spawn.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * spawn.c - CC31xx/CC32xx Host Driver Implementation - * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" - - -#if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN)) - -#define _SL_MAX_INTERNAL_SPAWN_ENTRIES 10 - -typedef struct _SlInternalSpawnEntry_t -{ - _SlSpawnEntryFunc_t pEntry; - void* pValue; - struct _SlInternalSpawnEntry_t* pNext; -}_SlInternalSpawnEntry_t; - -typedef struct -{ - _SlInternalSpawnEntry_t SpawnEntries[_SL_MAX_INTERNAL_SPAWN_ENTRIES]; - _SlInternalSpawnEntry_t* pFree; - _SlInternalSpawnEntry_t* pWaitForExe; - _SlInternalSpawnEntry_t* pLastInWaitList; - _SlSyncObj_t SyncObj; - _SlLockObj_t LockObj; -}_SlInternalSpawnCB_t; - -_SlInternalSpawnCB_t g_SlInternalSpawnCB; - - -void _SlInternalSpawnTaskEntry() -{ - _i16 i; - _SlInternalSpawnEntry_t* pEntry; - _u8 LastEntry; - - /* create and lock the locking object. lock in order to avoid race condition - on the first creation */ - sl_LockObjCreate(&g_SlInternalSpawnCB.LockObj,"SlSpawnProtect"); - sl_LockObjLock(&g_SlInternalSpawnCB.LockObj,SL_OS_NO_WAIT); - - /* create and clear the sync object */ - sl_SyncObjCreate(&g_SlInternalSpawnCB.SyncObj,"SlSpawnSync"); - sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_NO_WAIT); - - g_SlInternalSpawnCB.pFree = &g_SlInternalSpawnCB.SpawnEntries[0]; - g_SlInternalSpawnCB.pWaitForExe = NULL; - g_SlInternalSpawnCB.pLastInWaitList = NULL; - - /* create the link list between the entries */ - for (i=0 ; i<_SL_MAX_INTERNAL_SPAWN_ENTRIES - 1 ; i++) - { - g_SlInternalSpawnCB.SpawnEntries[i].pNext = &g_SlInternalSpawnCB.SpawnEntries[i+1]; - g_SlInternalSpawnCB.SpawnEntries[i].pEntry = NULL; - } - g_SlInternalSpawnCB.SpawnEntries[i].pNext = NULL; - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - /* here we ready to execute entries */ - - while (TRUE) - { - sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_WAIT_FOREVER); - /* go over all entries that already waiting for execution */ - LastEntry = FALSE; - do - { - /* get entry to execute */ - _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); - - pEntry = g_SlInternalSpawnCB.pWaitForExe; - if ( NULL == pEntry ) - { - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - break; - } - g_SlInternalSpawnCB.pWaitForExe = pEntry->pNext; - if (pEntry == g_SlInternalSpawnCB.pLastInWaitList) - { - g_SlInternalSpawnCB.pLastInWaitList = NULL; - LastEntry = TRUE; - } - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - /* pEntry could be null in case that the sync was already set by some - of the entries during execution of earlier entry */ - if (NULL != pEntry) - { - pEntry->pEntry(pEntry->pValue); - /* free the entry */ - - _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); - - pEntry->pNext = g_SlInternalSpawnCB.pFree; - g_SlInternalSpawnCB.pFree = pEntry; - - - if (NULL != g_SlInternalSpawnCB.pWaitForExe) - { - /* new entry received meanwhile */ - LastEntry = FALSE; - } - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - } - - }while (!LastEntry); - } -} - - -_i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags) -{ - _i16 Res = 0; - _SlInternalSpawnEntry_t* pSpawnEntry; - - if (NULL == pEntry) - { - Res = -1; - } - else - { - _SlDrvObjLockWaitForever(&g_SlInternalSpawnCB.LockObj); - - pSpawnEntry = g_SlInternalSpawnCB.pFree; - g_SlInternalSpawnCB.pFree = pSpawnEntry->pNext; - - pSpawnEntry->pEntry = pEntry; - pSpawnEntry->pValue = pValue; - pSpawnEntry->pNext = NULL; - - if (NULL == g_SlInternalSpawnCB.pWaitForExe) - { - g_SlInternalSpawnCB.pWaitForExe = pSpawnEntry; - g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry; - } - else - { - g_SlInternalSpawnCB.pLastInWaitList->pNext = pSpawnEntry; - g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry; - } - - _SlDrvObjUnLock(&g_SlInternalSpawnCB.LockObj); - - /* this sync is called after releasing the lock object to avoid unnecessary context switches */ - _SlDrvSyncObjSignal(&g_SlInternalSpawnCB.SyncObj); - } - - return Res; -} - - - - - -#endif diff --git a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/wlan.c b/MicroPython_BUILD/components/micropython/drivers/cc3100/src/wlan.c deleted file mode 100644 index 59adf02f..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/cc3100/src/wlan.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* -* wlan.c - CC31xx/CC32xx Host Driver Implementation -* -* Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ -* -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the -* distribution. -* -* Neither the name of Texas Instruments Incorporated nor the names of -* its contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - - - -/*****************************************************************************/ -/* Include files */ -/*****************************************************************************/ -#include "simplelink.h" -#include "protocol.h" -#include "driver.h" - -/*****************************************************************************/ -/* Macro declarations */ -/*****************************************************************************/ -#define MAX_SSID_LEN (32) -#define MAX_KEY_LEN (63) -#define MAX_USER_LEN (32) -#define MAX_ANON_USER_LEN (32) -#define MAX_SMART_CONFIG_KEY (16) - - -/***************************************************************************** -sl_WlanConnect -*****************************************************************************/ -typedef struct -{ - _WlanConnectEapCommand_t Args; - _i8 Strings[MAX_SSID_LEN + MAX_KEY_LEN + MAX_USER_LEN + MAX_ANON_USER_LEN]; -}_WlanConnectCmd_t; - -typedef union -{ - _WlanConnectCmd_t Cmd; - _BasicResponse_t Rsp; -}_SlWlanConnectMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanConnect) -_i16 sl_WlanConnect(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams) -{ - _SlWlanConnectMsg_u Msg; - _SlCmdCtrl_t CmdCtrl; - - sl_Memset (&Msg, 0, sizeof(Msg)); - - CmdCtrl.TxDescLen = 0;/* init */ - CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); - - /* verify SSID length */ - VERIFY_PROTOCOL(NameLen <= MAX_SSID_LEN); - /* verify SSID is not NULL */ - if( NULL == pName ) - { - return SL_INVALPARAM; - } - /* update SSID length */ - Msg.Cmd.Args.Common.SsidLen = (_u8)NameLen; - - /* Profile with no security */ - /* Enterprise security profile */ - if (NULL != pSecExtParams) - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_WLANCONNECTEAPCOMMAND; - CmdCtrl.TxDescLen += sizeof(_WlanConnectEapCommand_t); - /* copy SSID */ - sl_Memcpy(EAP_SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - /* Copy password if supplied */ - if ((NULL != pSecParams) && (pSecParams->KeyLen > 0)) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - /* verify key length */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - ARG_CHECK_PTR(pSecParams->Key); - /* copy key */ - sl_Memcpy(EAP_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - CmdCtrl.TxDescLen += pSecParams->KeyLen; - } - else - { - Msg.Cmd.Args.Common.PasswordLen = 0; - } - - ARG_CHECK_PTR(pSecExtParams); - /* Update Eap bitmask */ - Msg.Cmd.Args.EapBitmask = pSecExtParams->EapMethod; - /* Update Certificate file ID index - currently not supported */ - Msg.Cmd.Args.CertIndex = pSecExtParams->CertIndex; - /* verify user length */ - if (pSecExtParams->UserLen > MAX_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.UserLen = pSecExtParams->UserLen; - /* copy user name (identity) */ - if(pSecExtParams->UserLen > 0) - { - sl_Memcpy(EAP_USER_STRING(&Msg), pSecExtParams->User, pSecExtParams->UserLen); - CmdCtrl.TxDescLen += pSecExtParams->UserLen; - } - /* verify Anonymous user length */ - if (pSecExtParams->AnonUserLen > MAX_ANON_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.AnonUserLen = pSecExtParams->AnonUserLen; - /* copy Anonymous user */ - if(pSecExtParams->AnonUserLen > 0) - { - sl_Memcpy(EAP_ANON_USER_STRING(&Msg), pSecExtParams->AnonUser, pSecExtParams->AnonUserLen); - CmdCtrl.TxDescLen += pSecExtParams->AnonUserLen; - } - - } - - /* Regular or open security profile */ - else - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_WLANCONNECTCOMMAND; - CmdCtrl.TxDescLen += sizeof(_WlanConnectCommon_t); - /* copy SSID */ - sl_Memcpy(SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - /* Copy password if supplied */ - if( NULL != pSecParams ) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - /* verify key length is valid */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - CmdCtrl.TxDescLen += pSecParams->KeyLen; - /* copy key (could be no key in case of WPS pin) */ - if( NULL != pSecParams->Key ) - { - sl_Memcpy(PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - } - } - /* Profile with no security */ - else - { - Msg.Cmd.Args.Common.PasswordLen = 0; - Msg.Cmd.Args.Common.SecType = SL_SEC_TYPE_OPEN; - } - } - /* If BSSID is not null, copy to buffer, otherwise set to 0 */ - if(NULL != pMacAddr) - { - sl_Memcpy(Msg.Cmd.Args.Common.Bssid, pMacAddr, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - else - { - _SlDrvMemZero(Msg.Cmd.Args.Common.Bssid, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - - - VERIFY_RET_OK ( _SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - -/*******************************************************************************/ -/* sl_Disconnect */ -/* ******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanDisconnect) -_i16 sl_WlanDisconnect(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_WLANDISCONNECTCOMMAND); -} -#endif - -/******************************************************************************/ -/* sl_PolicySet */ -/******************************************************************************/ -typedef union -{ - _WlanPoliciySetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlPolicyMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanPolicySet) - -const _SlCmdCtrl_t _SlPolicySetCmdCtrl = -{ - SL_OPCODE_WLAN_POLICYSETCOMMAND, - sizeof(_WlanPoliciySetGet_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanPolicySet(const _u8 Type , const _u8 Policy, _u8 *pVal,const _u8 ValLen) -{ - _SlPolicyMsg_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = ValLen; - CmdExt.pTxPayload = (_u8 *)pVal; - - - Msg.Cmd.PolicyType = Type; - Msg.Cmd.PolicyOption = Policy; - Msg.Cmd.PolicyOptionLen = ValLen; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlPolicySetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_PolicyGet */ -/******************************************************************************/ -typedef union -{ - _WlanPoliciySetGet_t Cmd; - _WlanPoliciySetGet_t Rsp; -}_SlPolicyGetMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanPolicyGet) - -const _SlCmdCtrl_t _SlPolicyGetCmdCtrl = -{ - SL_OPCODE_WLAN_POLICYGETCOMMAND, - sizeof(_WlanPoliciySetGet_t), - sizeof(_WlanPoliciySetGet_t) -}; - -_i16 sl_WlanPolicyGet(const _u8 Type ,_u8 Policy,_u8 *pVal,_u8 *pValLen) -{ - _SlPolicyGetMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (*pValLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pValLen; - CmdExt.pRxPayload = pVal; - - Msg.Cmd.PolicyType = Type; - Msg.Cmd.PolicyOption = Policy; - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlPolicyGetCmdCtrl, &Msg, &CmdExt)); - - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pValLen = Msg.Rsp.PolicyOptionLen; - return SL_ESMALLBUF; - } - else - { - /* no pointer valus, fill the results into _i8 */ - *pValLen = (_u8)CmdExt.ActualRxPayloadLen; - if( 0 == CmdExt.ActualRxPayloadLen ) - { - *pValLen = 1; - pVal[0] = Msg.Rsp.PolicyOption; - } - } - return (_i16)SL_OS_RET_CODE_OK; -} -#endif - - -/*******************************************************************************/ -/* sl_ProfileAdd */ -/*******************************************************************************/ -typedef struct -{ - _WlanAddGetEapProfile_t Args; - _i8 Strings[MAX_SSID_LEN + MAX_KEY_LEN + MAX_USER_LEN + MAX_ANON_USER_LEN]; -}_SlProfileParams_t; - -typedef union -{ - _SlProfileParams_t Cmd; - _BasicResponse_t Rsp; -}_SlProfileAddMsg_u; - - - -#if _SL_INCLUDE_FUNC(sl_WlanProfileAdd) -_i16 sl_WlanProfileAdd(const _i8* pName,const _i16 NameLen,const _u8 *pMacAddr,const SlSecParams_t* pSecParams ,const SlSecParamsExt_t* pSecExtParams,const _u32 Priority,const _u32 Options) -{ - _SlProfileAddMsg_u Msg; - _SlCmdCtrl_t CmdCtrl = {0}; - CmdCtrl.TxDescLen = 0;/* init */ - CmdCtrl.RxDescLen = sizeof(_BasicResponse_t); - - /* update priority */ - Msg.Cmd.Args.Common.Priority = (_u8)Priority; - /* verify SSID is not NULL */ - if( NULL == pName ) - { - return SL_INVALPARAM; - } - /* verify SSID length */ - VERIFY_PROTOCOL(NameLen <= MAX_SSID_LEN); - /* update SSID length */ - Msg.Cmd.Args.Common.SsidLen = (_u8)NameLen; - - - /* Enterprise security profile */ - if (NULL != pSecExtParams) - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_EAP_PROFILEADDCOMMAND; - CmdCtrl.TxDescLen += sizeof(_WlanAddGetEapProfile_t); - - /* copy SSID */ - sl_Memcpy(EAP_PROFILE_SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - - /* Copy password if supplied */ - if ((NULL != pSecParams) && (pSecParams->KeyLen > 0)) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - - if( SL_SEC_TYPE_WEP == Msg.Cmd.Args.Common.SecType ) - { - Msg.Cmd.Args.Common.WepKeyId = 0; - } - - /* verify key length */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - VERIFY_PROTOCOL(pSecParams->KeyLen <= MAX_KEY_LEN); - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - CmdCtrl.TxDescLen += pSecParams->KeyLen; - ARG_CHECK_PTR(pSecParams->Key); - /* copy key */ - sl_Memcpy(EAP_PROFILE_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - } - else - { - Msg.Cmd.Args.Common.PasswordLen = 0; - } - - ARG_CHECK_PTR(pSecExtParams); - /* Update Eap bitmask */ - Msg.Cmd.Args.EapBitmask = pSecExtParams->EapMethod; - /* Update Certificate file ID index - currently not supported */ - Msg.Cmd.Args.CertIndex = pSecExtParams->CertIndex; - /* verify user length */ - if (pSecExtParams->UserLen > MAX_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.UserLen = pSecExtParams->UserLen; - /* copy user name (identity) */ - if(pSecExtParams->UserLen > 0) - { - sl_Memcpy(EAP_PROFILE_USER_STRING(&Msg), pSecExtParams->User, pSecExtParams->UserLen); - CmdCtrl.TxDescLen += pSecExtParams->UserLen; - } - - /* verify Anonymous user length (for tunneled) */ - if (pSecExtParams->AnonUserLen > MAX_ANON_USER_LEN) - { - return SL_INVALPARAM; - } - Msg.Cmd.Args.AnonUserLen = pSecExtParams->AnonUserLen; - - /* copy Anonymous user */ - if(pSecExtParams->AnonUserLen > 0) - { - sl_Memcpy(EAP_PROFILE_ANON_USER_STRING(&Msg), pSecExtParams->AnonUser, pSecExtParams->AnonUserLen); - CmdCtrl.TxDescLen += pSecExtParams->AnonUserLen; - } - - } - /* Regular or open security profile */ - else - { - /* Update command opcode */ - CmdCtrl.Opcode = SL_OPCODE_WLAN_PROFILEADDCOMMAND; - /* update commnad length */ - CmdCtrl.TxDescLen += sizeof(_WlanAddGetProfile_t); - - if (NULL != pName) - { - /* copy SSID */ - sl_Memcpy(PROFILE_SSID_STRING(&Msg), pName, NameLen); - CmdCtrl.TxDescLen += NameLen; - } - - /* Copy password if supplied */ - if( NULL != pSecParams ) - { - /* update security type */ - Msg.Cmd.Args.Common.SecType = pSecParams->Type; - - if( SL_SEC_TYPE_WEP == Msg.Cmd.Args.Common.SecType ) - { - Msg.Cmd.Args.Common.WepKeyId = 0; - } - - /* verify key length */ - if (pSecParams->KeyLen > MAX_KEY_LEN) - { - return SL_INVALPARAM; - } - /* update key length */ - Msg.Cmd.Args.Common.PasswordLen = pSecParams->KeyLen; - CmdCtrl.TxDescLen += pSecParams->KeyLen; - /* copy key (could be no key in case of WPS pin) */ - if( NULL != pSecParams->Key ) - { - sl_Memcpy(PROFILE_PASSWORD_STRING(&Msg), pSecParams->Key, pSecParams->KeyLen); - } - } - else - { - Msg.Cmd.Args.Common.SecType = SL_SEC_TYPE_OPEN; - Msg.Cmd.Args.Common.PasswordLen = 0; - } - - } - - - /* If BSSID is not null, copy to buffer, otherwise set to 0 */ - if(NULL != pMacAddr) - { - sl_Memcpy(Msg.Cmd.Args.Common.Bssid, pMacAddr, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - else - { - _SlDrvMemZero(Msg.Cmd.Args.Common.Bssid, sizeof(Msg.Cmd.Args.Common.Bssid)); - } - - VERIFY_RET_OK(_SlDrvCmdOp(&CmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif -/*******************************************************************************/ -/* sl_ProfileGet */ -/*******************************************************************************/ -typedef union -{ - _WlanProfileDelGetCommand_t Cmd; - _SlProfileParams_t Rsp; -}_SlProfileGetMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanProfileGet) - -const _SlCmdCtrl_t _SlProfileGetCmdCtrl = -{ - SL_OPCODE_WLAN_PROFILEGETCOMMAND, - sizeof(_WlanProfileDelGetCommand_t), - sizeof(_SlProfileParams_t) -}; - -_i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAddr, SlSecParams_t* pSecParams, SlGetSecParamsExt_t* pEntParams, _u32 *pPriority) -{ - _SlProfileGetMsg_u Msg; - Msg.Cmd.index = (_u8)Index; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlProfileGetCmdCtrl, &Msg, NULL)); - - pSecParams->Type = Msg.Rsp.Args.Common.SecType; - /* since password is not transferred in getprofile, password length should always be zero */ - pSecParams->KeyLen = Msg.Rsp.Args.Common.PasswordLen; - if (NULL != pEntParams) - { - pEntParams->UserLen = Msg.Rsp.Args.UserLen; - /* copy user name */ - if (pEntParams->UserLen > 0) - { - sl_Memcpy(pEntParams->User, EAP_PROFILE_USER_STRING(&Msg), pEntParams->UserLen); - } - pEntParams->AnonUserLen = Msg.Rsp.Args.AnonUserLen; - /* copy anonymous user name */ - if (pEntParams->AnonUserLen > 0) - { - sl_Memcpy(pEntParams->AnonUser, EAP_PROFILE_ANON_USER_STRING(&Msg), pEntParams->AnonUserLen); - } - } - - *pNameLen = Msg.Rsp.Args.Common.SsidLen; - *pPriority = Msg.Rsp.Args.Common.Priority; - - if (NULL != Msg.Rsp.Args.Common.Bssid) - { - sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid)); - } - - sl_Memcpy(pName, EAP_PROFILE_SSID_STRING(&Msg), *pNameLen); - - return (_i16)Msg.Rsp.Args.Common.SecType; - -} -#endif -/*******************************************************************************/ -/* sl_ProfileDel */ -/*******************************************************************************/ -typedef union -{ - _WlanProfileDelGetCommand_t Cmd; - _BasicResponse_t Rsp; -}_SlProfileDelMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanProfileDel) - -const _SlCmdCtrl_t _SlProfileDelCmdCtrl = -{ - SL_OPCODE_WLAN_PROFILEDELCOMMAND, - sizeof(_WlanProfileDelGetCommand_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanProfileDel(const _i16 Index) -{ - _SlProfileDelMsg_u Msg; - - Msg.Cmd.index = (_u8)Index; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlProfileDelCmdCtrl, &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_WlanGetNetworkList */ -/******************************************************************************/ -typedef union -{ - _WlanGetNetworkListCommand_t Cmd; - _WlanGetNetworkListResponse_t Rsp; -}_SlWlanGetNetworkListMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanGetNetworkList) - -const _SlCmdCtrl_t _SlWlanGetNetworkListCtrl = -{ - SL_OPCODE_WLAN_SCANRESULTSGETCOMMAND, - sizeof(_WlanGetNetworkListCommand_t), - sizeof(_WlanGetNetworkListResponse_t) -}; - -_i16 sl_WlanGetNetworkList(const _u8 Index,const _u8 Count, Sl_WlanNetworkEntry_t *pEntries) -{ - _i16 retVal = 0; - _SlWlanGetNetworkListMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (Count == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = sizeof(Sl_WlanNetworkEntry_t)*(Count); - CmdExt.pRxPayload = (_u8 *)pEntries; - - Msg.Cmd.index = Index; - Msg.Cmd.count = Count; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanGetNetworkListCtrl, &Msg, &CmdExt)); - retVal = Msg.Rsp.status; - - return (_i16)retVal; -} -#endif - - - - - -/******************************************************************************/ -/* RX filters message command response structures */ -/******************************************************************************/ - -/* Set command */ -typedef union -{ - _WlanRxFilterAddCommand_t Cmd; - _WlanRxFilterAddCommandReponse_t Rsp; -}_SlrxFilterAddMsg_u; - - -/* Set command */ -typedef union _SlRxFilterSetMsg_u -{ - _WlanRxFilterSetCommand_t Cmd; - _WlanRxFilterSetCommandReponse_t Rsp; -}_SlRxFilterSetMsg_u; - - -/* Get command */ -typedef union _SlRxFilterGetMsg_u -{ - _WlanRxFilterGetCommand_t Cmd; - _WlanRxFilterGetCommandReponse_t Rsp; -}_SlRxFilterGetMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterAdd) - -const _SlCmdCtrl_t _SlRxFilterAddtCmdCtrl = -{ - SL_OPCODE_WLAN_WLANRXFILTERADDCOMMAND, - sizeof(_WlanRxFilterAddCommand_t), - sizeof(_WlanRxFilterAddCommandReponse_t) -}; - - -/***************************************************************************** - RX filters -*****************************************************************************/ -SlrxFilterID_t sl_WlanRxFilterAdd( SlrxFilterRuleType_t RuleType, - SlrxFilterFlags_t FilterFlags, - const SlrxFilterRule_t* const Rule, - const SlrxFilterTrigger_t* const Trigger, - const SlrxFilterAction_t* const Action, - SlrxFilterID_t* pFilterId) -{ - - - _SlrxFilterAddMsg_u Msg; - Msg.Cmd.RuleType = RuleType; - /* filterId is zero */ - Msg.Cmd.FilterId = 0; - Msg.Cmd.FilterFlags = FilterFlags; - sl_Memcpy( &(Msg.Cmd.Rule), Rule, sizeof(SlrxFilterRule_t) ); - sl_Memcpy( &(Msg.Cmd.Trigger), Trigger, sizeof(SlrxFilterTrigger_t) ); - sl_Memcpy( &(Msg.Cmd.Action), Action, sizeof(SlrxFilterAction_t) ); - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterAddtCmdCtrl, &Msg, NULL) ); - *pFilterId = Msg.Rsp.FilterId; - return (_i16)Msg.Rsp.Status; - -} -#endif - - - -/*******************************************************************************/ -/* RX filters */ -/*******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterSet) - -const _SlCmdCtrl_t _SlRxFilterSetCmdCtrl = -{ - SL_OPCODE_WLAN_WLANRXFILTERSETCOMMAND, - sizeof(_WlanRxFilterSetCommand_t), - sizeof(_WlanRxFilterSetCommandReponse_t) -}; - -_i16 sl_WlanRxFilterSet(const SLrxFilterOperation_t RxFilterOperation, - const _u8* const pInputBuffer, - _u16 InputbufferLength) -{ - _SlRxFilterSetMsg_u Msg; - _SlCmdExt_t CmdExt; - - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = InputbufferLength; - CmdExt.pTxPayload = (_u8 *)pInputBuffer; - - Msg.Cmd.RxFilterOperation = RxFilterOperation; - Msg.Cmd.InputBufferLength = InputbufferLength; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterSetCmdCtrl, &Msg, &CmdExt) ); - - - return (_i16)Msg.Rsp.Status; -} -#endif - -/******************************************************************************/ -/* RX filters */ -/******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanRxFilterGet) - -const _SlCmdCtrl_t _SlRxFilterGetCmdCtrl = -{ - SL_OPCODE_WLAN_WLANRXFILTERGETCOMMAND, - sizeof(_WlanRxFilterGetCommand_t), - sizeof(_WlanRxFilterGetCommandReponse_t) -}; - - -_i16 sl_WlanRxFilterGet(const SLrxFilterOperation_t RxFilterOperation, - _u8* pOutputBuffer, - _u16 OutputbufferLength) -{ - _SlRxFilterGetMsg_u Msg; - _SlCmdExt_t CmdExt; - - if (OutputbufferLength == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = OutputbufferLength; - CmdExt.pRxPayload = (_u8 *)pOutputBuffer; - - Msg.Cmd.RxFilterOperation = RxFilterOperation; - Msg.Cmd.OutputBufferLength = OutputbufferLength; - - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlRxFilterGetCmdCtrl, &Msg, &CmdExt) ); - - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - return SL_ESMALLBUF; - } - - return (_i16)Msg.Rsp.Status; -} -#endif - -/*******************************************************************************/ -/* sl_WlanRxStatStart */ -/*******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStart) -_i16 sl_WlanRxStatStart(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_STARTRXSTATCOMMAND); -} -#endif - -#if _SL_INCLUDE_FUNC(sl_WlanRxStatStop) -_i16 sl_WlanRxStatStop(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_STOPRXSTATCOMMAND); -} -#endif - -#if _SL_INCLUDE_FUNC(sl_WlanRxStatGet) -_i16 sl_WlanRxStatGet(SlGetRxStatResponse_t *pRxStat,const _u32 Flags) -{ - _SlCmdCtrl_t CmdCtrl = {SL_OPCODE_WLAN_GETRXSTATCOMMAND, 0, sizeof(SlGetRxStatResponse_t)}; - - _SlDrvMemZero(pRxStat, sizeof(SlGetRxStatResponse_t)); - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, pRxStat, NULL)); - - return 0; -} -#endif - - - -/******************************************************************************/ -/* sl_WlanSmartConfigStop */ -/******************************************************************************/ -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStop) -_i16 sl_WlanSmartConfigStop(void) -{ - return _SlDrvBasicCmd(SL_OPCODE_WLAN_SMART_CONFIG_STOP_COMMAND); -} -#endif - - -/******************************************************************************/ -/* sl_WlanSmartConfigStart */ -/******************************************************************************/ - - -typedef struct -{ - _WlanSmartConfigStartCommand_t Args; - _i8 Strings[3 * MAX_SMART_CONFIG_KEY]; /* public key + groupId1 key + groupId2 key */ -}_SlSmartConfigStart_t; - -typedef union -{ - _SlSmartConfigStart_t Cmd; - _BasicResponse_t Rsp; -}_SlSmartConfigStartMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanSmartConfigStart) - -const _SlCmdCtrl_t _SlSmartConfigStartCmdCtrl = -{ - SL_OPCODE_WLAN_SMART_CONFIG_START_COMMAND, - sizeof(_SlSmartConfigStart_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanSmartConfigStart( const _u32 groupIdBitmask, - const _u8 cipher, - const _u8 publicKeyLen, - const _u8 group1KeyLen, - const _u8 group2KeyLen, - const _u8* pPublicKey, - const _u8* pGroup1Key, - const _u8* pGroup2Key) -{ - _SlSmartConfigStartMsg_u Msg; - - Msg.Cmd.Args.groupIdBitmask = (_u8)groupIdBitmask; - Msg.Cmd.Args.cipher = (_u8)cipher; - Msg.Cmd.Args.publicKeyLen = (_u8)publicKeyLen; - Msg.Cmd.Args.group1KeyLen = (_u8)group1KeyLen; - Msg.Cmd.Args.group2KeyLen = (_u8)group2KeyLen; - - /* copy keys (if exist) after command (one after another) */ - sl_Memcpy(SMART_CONFIG_START_PUBLIC_KEY_STRING(&Msg), pPublicKey, publicKeyLen); - sl_Memcpy(SMART_CONFIG_START_GROUP1_KEY_STRING(&Msg), pGroup1Key, group1KeyLen); - sl_Memcpy(SMART_CONFIG_START_GROUP2_KEY_STRING(&Msg), pGroup2Key, group2KeyLen); - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSmartConfigStartCmdCtrl , &Msg, NULL)); - - return (_i16)Msg.Rsp.status; - - -} -#endif - - -/*******************************************************************************/ -/* sl_WlanSetMode */ -/*******************************************************************************/ -typedef union -{ - _WlanSetMode_t Cmd; - _BasicResponse_t Rsp; -}_SlwlanSetModeMsg_u; - -#if _SL_INCLUDE_FUNC(sl_WlanSetMode) - -const _SlCmdCtrl_t _SlWlanSetModeCmdCtrl = -{ - SL_OPCODE_WLAN_SET_MODE, - sizeof(_WlanSetMode_t), - sizeof(_BasicResponse_t) -}; - -/* possible values are: -WLAN_SET_STA_MODE = 1 -WLAN_SET_AP_MODE = 2 -WLAN_SET_P2P_MODE = 3 */ -_i16 sl_WlanSetMode(const _u8 mode) -{ - _SlwlanSetModeMsg_u Msg; - - Msg.Cmd.mode = mode; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanSetModeCmdCtrl , &Msg, NULL)); - - return (_i16)Msg.Rsp.status; -} -#endif - - - - -/*******************************************************************************/ -/* sl_WlanSet */ -/* ******************************************************************************/ -typedef union -{ - _WlanCfgSetGet_t Cmd; - _BasicResponse_t Rsp; -}_SlWlanCfgSetMsg_u; - - -#if _SL_INCLUDE_FUNC(sl_WlanSet) - -const _SlCmdCtrl_t _SlWlanCfgSetCmdCtrl = -{ - SL_OPCODE_WLAN_CFG_SET, - sizeof(_WlanCfgSetGet_t), - sizeof(_BasicResponse_t) -}; - -_i16 sl_WlanSet(const _u16 ConfigId ,const _u16 ConfigOpt,const _u16 ConfigLen,const _u8 *pValues) -{ - _SlWlanCfgSetMsg_u Msg; - _SlCmdExt_t CmdExt; - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.TxPayloadLen = (ConfigLen+3) & (~3); - CmdExt.pTxPayload = (_u8 *)pValues; - - Msg.Cmd.ConfigId = ConfigId; - Msg.Cmd.ConfigLen = ConfigLen; - Msg.Cmd.ConfigOpt = ConfigOpt; - - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanCfgSetCmdCtrl, &Msg, &CmdExt)); - - return (_i16)Msg.Rsp.status; -} -#endif - - -/******************************************************************************/ -/* sl_WlanGet */ -/******************************************************************************/ -typedef union -{ - _WlanCfgSetGet_t Cmd; - _WlanCfgSetGet_t Rsp; -}_SlWlanCfgMsgGet_u; - -#if _SL_INCLUDE_FUNC(sl_WlanGet) - -const _SlCmdCtrl_t _SlWlanCfgGetCmdCtrl = -{ - SL_OPCODE_WLAN_CFG_GET, - sizeof(_WlanCfgSetGet_t), - sizeof(_WlanCfgSetGet_t) -}; - -_i16 sl_WlanGet(const _u16 ConfigId, _u16 *pConfigOpt,_u16 *pConfigLen, _u8 *pValues) -{ - _SlWlanCfgMsgGet_u Msg; - _SlCmdExt_t CmdExt; - - if (*pConfigLen == 0) - { - return SL_EZEROLEN; - } - - _SlDrvResetCmdExt(&CmdExt); - CmdExt.RxPayloadLen = *pConfigLen; - CmdExt.pRxPayload = (_u8 *)pValues; - - Msg.Cmd.ConfigId = ConfigId; - if( pConfigOpt ) - { - Msg.Cmd.ConfigOpt = (_u16)*pConfigOpt; - } - VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlWlanCfgGetCmdCtrl, &Msg, &CmdExt)); - - if( pConfigOpt ) - { - *pConfigOpt = (_u8)Msg.Rsp.ConfigOpt; - } - if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen) - { - *pConfigLen = (_u8)CmdExt.RxPayloadLen; - return SL_ESMALLBUF; - } - else - { - *pConfigLen = (_u8)CmdExt.ActualRxPayloadLen; - } - - - return (_i16)Msg.Rsp.Status; -} -#endif diff --git a/MicroPython_BUILD/components/micropython/drivers/memory/spiflash.c b/MicroPython_BUILD/components/micropython/drivers/memory/spiflash.c deleted file mode 100644 index 08564d05..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/memory/spiflash.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016-2017 Damien P. George - * - * 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 -#include - -#include "py/mperrno.h" -#include "py/mphal.h" -#include "extmod/machine_spi.h" -#include "drivers/memory/spiflash.h" - -#define CMD_WRITE (0x02) -#define CMD_READ (0x03) -#define CMD_WRDI (0x04) -#define CMD_RDSR (0x05) -#define CMD_WREN (0x06) -#define CMD_SEC_ERASE (0x20) -#define WAIT_SR_TIMEOUT (1000000) - -#define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer -#define SECTOR_SIZE (4096) // size of erase sector - -// Note: this code is not reentrant with this shared buffer -STATIC uint8_t buf[SECTOR_SIZE]; - -void mp_spiflash_init(mp_spiflash_t *self) { - mp_hal_pin_write(self->cs, 1); - mp_hal_pin_output(self->cs); - const mp_machine_spi_p_t *protocol = self->spi->type->protocol; - protocol->init(self->spi, 0, NULL, (mp_map_t*)&mp_const_empty_map); -} - -STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) { - // can be used for actions needed to acquire bus - (void)self; -} - -STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) { - // can be used for actions needed to release bus - (void)self; -} - -STATIC void mp_spiflash_transfer(mp_spiflash_t *self, size_t len, const uint8_t *src, uint8_t *dest) { - const mp_machine_spi_p_t *protocol = self->spi->type->protocol; - protocol->transfer(self->spi, len, src, dest); -} - -STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) { - uint8_t cmd[1] = {CMD_RDSR}; - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 1, cmd, NULL); - for (; timeout; --timeout) { - mp_spiflash_transfer(self, 1, cmd, cmd); - if ((cmd[0] & mask) == val) { - break; - } - } - mp_hal_pin_write(self->cs, 1); - if ((cmd[0] & mask) == val) { - return 0; // success - } else if (timeout == 0) { - return -MP_ETIMEDOUT; - } else { - return -MP_EIO; - } -} - -STATIC int mp_spiflash_wait_wel1(mp_spiflash_t *self) { - return mp_spiflash_wait_sr(self, 2, 2, WAIT_SR_TIMEOUT); -} - -STATIC int mp_spiflash_wait_wip0(mp_spiflash_t *self) { - return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT); -} - -STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) { - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 1, &cmd, NULL); - mp_hal_pin_write(self->cs, 1); -} - -STATIC int mp_spiflash_erase_sector(mp_spiflash_t *self, uint32_t addr) { - // enable writes - mp_spiflash_write_cmd(self, CMD_WREN); - - // wait WEL=1 - int ret = mp_spiflash_wait_wel1(self); - if (ret != 0) { - return ret; - } - - // erase the sector - mp_hal_pin_write(self->cs, 0); - uint8_t cmd[4] = {CMD_SEC_ERASE, addr >> 16, addr >> 8, addr}; - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_hal_pin_write(self->cs, 1); - - // wait WIP=0 - return mp_spiflash_wait_wip0(self); -} - -STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, const uint8_t *src) { - // enable writes - mp_spiflash_write_cmd(self, CMD_WREN); - - // wait WEL=1 - int ret = mp_spiflash_wait_wel1(self); - if (ret != 0) { - return ret; - } - - // write the page - mp_hal_pin_write(self->cs, 0); - uint8_t cmd[4] = {CMD_WRITE, addr >> 16, addr >> 8, addr}; - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_spiflash_transfer(self, PAGE_SIZE, src, NULL); - mp_hal_pin_write(self->cs, 1); - - // wait WIP=0 - return mp_spiflash_wait_wip0(self); -} - -void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) { - mp_spiflash_acquire_bus(self); - uint8_t cmd[4] = {CMD_READ, addr >> 16, addr >> 8, addr}; - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_spiflash_transfer(self, len, dest, dest); - mp_hal_pin_write(self->cs, 1); - mp_spiflash_release_bus(self); -} - -int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) { - // TODO optimise so we don't need to erase multiple times for successive writes to a sector - - // align to 4096 sector - uint32_t offset = addr & 0xfff; - addr = (addr >> 12) << 12; - - // restriction for now, so we don't need to erase multiple pages - if (offset + len > sizeof(buf)) { - printf("mp_spiflash_write: len is too large\n"); - return -MP_EIO; - } - - mp_spiflash_acquire_bus(self); - - // read sector - uint8_t cmd[4] = {CMD_READ, addr >> 16, addr >> 8, addr}; - mp_hal_pin_write(self->cs, 0); - mp_spiflash_transfer(self, 4, cmd, NULL); - mp_spiflash_transfer(self, SECTOR_SIZE, buf, buf); - mp_hal_pin_write(self->cs, 1); - - // erase sector - int ret = mp_spiflash_erase_sector(self, addr); - if (ret != 0) { - mp_spiflash_release_bus(self); - return ret; - } - - // copy new block into buffer - memcpy(buf + offset, src, len); - - // write sector in pages of 256 bytes - for (int i = 0; i < SECTOR_SIZE; i += 256) { - ret = mp_spiflash_write_page(self, addr + i, buf + i); - if (ret != 0) { - mp_spiflash_release_bus(self); - return ret; - } - } - - mp_spiflash_release_bus(self); - return 0; // success -} diff --git a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py index 7274a792..a95d2b5c 100644 --- a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py +++ b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01.py @@ -62,12 +62,11 @@ def __init__(self, spi, cs, ce, channel=46, payload_size=16): # init the SPI bus and pins self.init_spi(4000000) - cs.init(cs.OUT, value=1) - ce.init(ce.OUT, value=0) # reset everything - self.ce(0) - self.cs(1) + ce.init(ce.OUT, value=0) + cs.init(cs.OUT, value=1) + self.payload_size = payload_size self.pipe0_read_addr = None utime.sleep_ms(5) @@ -215,7 +214,7 @@ def recv(self): # blocking wait for tx complete def send(self, buf, timeout=500): - send_nonblock = self.send_start(buf) + self.send_start(buf) start = utime.ticks_ms() result = None while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout: diff --git a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py index 5413511c..876b2bbf 100644 --- a/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py +++ b/MicroPython_BUILD/components/micropython/drivers/nrf24l01/nrf24l01test.py @@ -1,14 +1,38 @@ -"""Test for nrf24l01 module.""" +"""Test for nrf24l01 module. Portable between MicroPython targets.""" -import struct +import sys +import ustruct as struct import utime from machine import Pin, SPI from nrf24l01 import NRF24L01 +from micropython import const + +# Slave pause between receiving data and checking for further packets. +_RX_POLL_DELAY = const(15) +# Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before +# transmitting to allow the (remote) master time to get into receive mode. The +# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266. +_SLAVE_SEND_DELAY = const(10) + +if sys.platform == 'pyboard': + cfg = {'spi': 2, 'miso': 'Y7', 'mosi': 'Y8', 'sck': 'Y6', 'csn': 'Y5', 'ce': 'Y4'} +elif sys.platform == 'esp8266': # Hardware SPI + cfg = {'spi': 1, 'miso': 12, 'mosi': 13, 'sck': 14, 'csn': 4, 'ce': 5} +elif sys.platform == 'esp32': # Software SPI + cfg = {'spi': -1, 'miso': 32, 'mosi': 33, 'sck': 25, 'csn': 26, 'ce': 27} +else: + raise ValueError('Unsupported platform {}'.format(sys.platform)) pipes = (b'\xf0\xf0\xf0\xf0\xe1', b'\xf0\xf0\xf0\xf0\xd2') def master(): - nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8) + csn = Pin(cfg['csn'], mode=Pin.OUT, value=1) + ce = Pin(cfg['ce'], mode=Pin.OUT, value=0) + if cfg['spi'] == -1: + spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso'])) + nrf = NRF24L01(spi, csn, ce, payload_size=8) + else: + nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8) nrf.open_tx_pipe(pipes[0]) nrf.open_rx_pipe(1, pipes[1]) @@ -60,7 +84,13 @@ def master(): print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures)) def slave(): - nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8) + csn = Pin(cfg['csn'], mode=Pin.OUT, value=1) + ce = Pin(cfg['ce'], mode=Pin.OUT, value=0) + if cfg['spi'] == -1: + spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso'])) + nrf = NRF24L01(spi, csn, ce, payload_size=8) + else: + nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8) nrf.open_tx_pipe(pipes[1]) nrf.open_rx_pipe(1, pipes[0]) @@ -69,7 +99,6 @@ def slave(): print('NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)') while True: - machine.idle() if nrf.any(): while nrf.any(): buf = nrf.recv() @@ -81,8 +110,10 @@ def slave(): else: led.off() led_state >>= 1 - utime.sleep_ms(15) + utime.sleep_ms(_RX_POLL_DELAY) + # Give master time to get into receive mode. + utime.sleep_ms(_SLAVE_SEND_DELAY) nrf.stop_listening() try: nrf.send(struct.pack('i', millis)) @@ -99,9 +130,9 @@ def slave(): print('NRF24L01 test module loaded') print('NRF24L01 pinout for test:') -print(' CE on Y4') -print(' CSN on Y5') -print(' SCK on Y6') -print(' MISO on Y7') -print(' MOSI on Y8') +print(' CE on', cfg['ce']) +print(' CSN on', cfg['csn']) +print(' SCK on', cfg['sck']) +print(' MISO on', cfg['miso']) +print(' MOSI on', cfg['mosi']) print('run nrf24l01test.slave() on slave, then nrf24l01test.master() on master') diff --git a/MicroPython_BUILD/components/micropython/drivers/sdcard/sdcard.py b/MicroPython_BUILD/components/micropython/drivers/sdcard/sdcard.py deleted file mode 100644 index 75a0c501..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/sdcard/sdcard.py +++ /dev/null @@ -1,272 +0,0 @@ -""" -MicroPython driver for SD cards using SPI bus. - -Requires an SPI bus and a CS pin. Provides readblocks and writeblocks -methods so the device can be mounted as a filesystem. - -Example usage on pyboard: - - import pyb, sdcard, os - sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5) - pyb.mount(sd, '/sd2') - os.listdir('/') - -Example usage on ESP8266: - - import machine, sdcard, os - sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15)) - os.umount() - os.VfsFat(sd, "") - os.listdir() - -""" - -from micropython import const -import time - - -_CMD_TIMEOUT = const(100) - -_R1_IDLE_STATE = const(1 << 0) -#R1_ERASE_RESET = const(1 << 1) -_R1_ILLEGAL_COMMAND = const(1 << 2) -#R1_COM_CRC_ERROR = const(1 << 3) -#R1_ERASE_SEQUENCE_ERROR = const(1 << 4) -#R1_ADDRESS_ERROR = const(1 << 5) -#R1_PARAMETER_ERROR = const(1 << 6) -_TOKEN_CMD25 = const(0xfc) -_TOKEN_STOP_TRAN = const(0xfd) -_TOKEN_DATA = const(0xfe) - - -class SDCard: - def __init__(self, spi, cs): - self.spi = spi - self.cs = cs - - self.cmdbuf = bytearray(6) - self.dummybuf = bytearray(512) - for i in range(512): - self.dummybuf[i] = 0xff - self.dummybuf_memoryview = memoryview(self.dummybuf) - - # initialise the card - self.init_card() - - def init_spi(self, baudrate): - try: - master = self.spi.MASTER - except AttributeError: - # on ESP8266 - self.spi.init(baudrate=baudrate, phase=0, polarity=0) - else: - # on pyboard - self.spi.init(master, baudrate=baudrate, phase=0, polarity=0) - - def init_card(self): - # init CS pin - self.cs.init(self.cs.OUT, value=1) - - # init SPI bus; use low data rate for initialisation - self.init_spi(100000) - - # clock card at least 100 cycles with cs high - for i in range(16): - self.spi.write(b'\xff') - - # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) - for _ in range(5): - if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: - break - else: - raise OSError("no SD card") - - # CMD8: determine card version - r = self.cmd(8, 0x01aa, 0x87, 4) - if r == _R1_IDLE_STATE: - self.init_card_v2() - elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): - self.init_card_v1() - else: - raise OSError("couldn't determine SD card version") - - # get the number of sectors - # CMD9: response R2 (R1 byte + 16-byte block read) - if self.cmd(9, 0, 0, 0, False) != 0: - raise OSError("no response from SD card") - csd = bytearray(16) - self.readinto(csd) - if csd[0] & 0xc0 != 0x40: - raise OSError("SD card CSD format not supported") - self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 2014 - #print('sectors', self.sectors) - - # CMD16: set block length to 512 bytes - if self.cmd(16, 512, 0) != 0: - raise OSError("can't set 512 block size") - - # set to high data rate now that it's initialised - self.init_spi(1320000) - - def init_card_v1(self): - for i in range(_CMD_TIMEOUT): - self.cmd(55, 0, 0) - if self.cmd(41, 0, 0) == 0: - self.cdv = 512 - #print("[SDCard] v1 card") - return - raise OSError("timeout waiting for v1 card") - - def init_card_v2(self): - for i in range(_CMD_TIMEOUT): - time.sleep_ms(50) - self.cmd(58, 0, 0, 4) - self.cmd(55, 0, 0) - if self.cmd(41, 0x40000000, 0) == 0: - self.cmd(58, 0, 0, 4) - self.cdv = 1 - #print("[SDCard] v2 card") - return - raise OSError("timeout waiting for v2 card") - - def cmd(self, cmd, arg, crc, final=0, release=True): - self.cs(0) - - # create and send the command - buf = self.cmdbuf - buf[0] = 0x40 | cmd - buf[1] = arg >> 24 - buf[2] = arg >> 16 - buf[3] = arg >> 8 - buf[4] = arg - buf[5] = crc - self.spi.write(buf) - - # wait for the response (response[7] == 0) - for i in range(_CMD_TIMEOUT): - response = self.spi.read(1, 0xff)[0] - if not (response & 0x80): - # this could be a big-endian integer that we are getting here - for j in range(final): - self.spi.write(b'\xff') - if release: - self.cs(1) - self.spi.write(b'\xff') - return response - - # timeout - self.cs(1) - self.spi.write(b'\xff') - return -1 - - def cmd_nodata(self, cmd): - self.spi.write(cmd) - self.spi.read(1, 0xff) # ignore stuff byte - for _ in range(_CMD_TIMEOUT): - if self.spi.read(1, 0xff)[0] == 0xff: - self.cs(1) - self.spi.write(b'\xff') - return 0 # OK - self.cs(1) - self.spi.write(b'\xff') - return 1 # timeout - - def readinto(self, buf): - self.cs(0) - - # read until start byte (0xff) - while self.spi.read(1, 0xff)[0] != 0xfe: - pass - - # read data - mv = self.dummybuf_memoryview[:len(buf)] - self.spi.write_readinto(mv, buf) - - # read checksum - self.spi.write(b'\xff') - self.spi.write(b'\xff') - - self.cs(1) - self.spi.write(b'\xff') - - def write(self, token, buf): - self.cs(0) - - # send: start of block, data, checksum - self.spi.read(1, token) - self.spi.write(buf) - self.spi.write(b'\xff') - self.spi.write(b'\xff') - - # check the response - if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05: - self.cs(1) - self.spi.write(b'\xff') - return - - # wait for write to finish - while self.spi.read(1, 0xff)[0] == 0: - pass - - self.cs(1) - self.spi.write(b'\xff') - - def write_token(self, token): - self.cs(0) - self.spi.read(1, token) - self.spi.write(b'\xff') - # wait for write to finish - while self.spi.read(1, 0xff)[0] == 0x00: - pass - - self.cs(1) - self.spi.write(b'\xff') - - def count(self): - return self.sectors - - def readblocks(self, block_num, buf): - nblocks, err = divmod(len(buf), 512) - assert nblocks and not err, 'Buffer length is invalid' - if nblocks == 1: - # CMD17: set read address for single block - if self.cmd(17, block_num * self.cdv, 0) != 0: - return 1 - # receive the data - self.readinto(buf) - else: - # CMD18: set read address for multiple blocks - if self.cmd(18, block_num * self.cdv, 0) != 0: - return 1 - offset = 0 - mv = memoryview(buf) - while nblocks: - self.readinto(mv[offset : offset + 512]) - offset += 512 - nblocks -= 1 - return self.cmd_nodata(b'\x0c') # cmd 12 - return 0 - - def writeblocks(self, block_num, buf): - nblocks, err = divmod(len(buf), 512) - assert nblocks and not err, 'Buffer length is invalid' - if nblocks == 1: - # CMD24: set write address for single block - if self.cmd(24, block_num * self.cdv, 0) != 0: - return 1 - - # send the data - self.write(_TOKEN_DATA, buf) - else: - # CMD25: set write address for first block - if self.cmd(25, block_num * self.cdv, 0) != 0: - return 1 - # send the data - offset = 0 - mv = memoryview(buf) - while nblocks: - self.write(_TOKEN_CMD25, mv[offset : offset + 512]) - offset += 512 - nblocks -= 1 - self.write_token(_TOKEN_STOP_TRAN) - return 0 diff --git a/MicroPython_BUILD/components/micropython/drivers/sdcard/sdtest.py b/MicroPython_BUILD/components/micropython/drivers/sdcard/sdtest.py deleted file mode 100644 index 438baa24..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/sdcard/sdtest.py +++ /dev/null @@ -1,57 +0,0 @@ -# Test for sdcard block protocol -# Peter hinch 30th Jan 2016 -import os, sdcard, pyb - -def sdtest(): - sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X21) # Compatible with PCB - pyb.mount(sd, '/fc') - print('Filesystem check') - print(os.listdir('/fc')) - - line = 'abcdefghijklmnopqrstuvwxyz\n' - lines = line * 200 # 5400 chars - short = '1234567890\n' - - fn = '/fc/rats.txt' - print() - print('Multiple block read/write') - with open(fn,'w') as f: - n = f.write(lines) - print(n, 'bytes written') - n = f.write(short) - print(n, 'bytes written') - n = f.write(lines) - print(n, 'bytes written') - - with open(fn,'r') as f: - result1 = f.read() - print(len(result1), 'bytes read') - - fn = '/fc/rats1.txt' - print() - print('Single block read/write') - with open(fn,'w') as f: - n = f.write(short) # one block - print(n, 'bytes written') - - with open(fn,'r') as f: - result2 = f.read() - print(len(result2), 'bytes read') - - pyb.mount(None, '/fc') - - print() - print('Verifying data read back') - success = True - if result1 == ''.join((lines, short, lines)): - print('Large file Pass') - else: - print('Large file Fail') - success = False - if result2 == short: - print('Small file Pass') - else: - print('Small file Fail') - success = False - print() - print('Tests', 'passed' if success else 'failed') diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/README.md b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/README.md deleted file mode 100644 index 88f25a2b..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/README.md +++ /dev/null @@ -1,6 +0,0 @@ -This is the driver for the WIZnet5x00 series of Ethernet controllers. - -Adapted for MicroPython. - -Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary -Taken on: 30 August 2014 diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/socket.c b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/socket.c deleted file mode 100644 index ec25fcc7..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/socket.c +++ /dev/null @@ -1,724 +0,0 @@ -//***************************************************************************** -// -//! \file socket.c -//! \brief SOCKET APIs Implements file. -//! \details SOCKET APIs like as Berkeley Socket APIs. -//! \version 1.0.3 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.3. Refer to M20140501 -//! 1. Implicit type casting -> Explicit type casting. -//! 2. replace 0x01 with PACK_REMAINED in recvfrom() -//! 3. Validation a destination ip in connect() & sendto(): -//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. -//! Copy 4 byte addr value into temporary uint32 variable and then compares it. -//! <2013/12/20> V1.0.2 Refer to M20131220 -//! Remove Warning. -//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". -//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include - -#include "py/mpthread.h" -#include "socket.h" - -#define SOCK_ANY_PORT_NUM 0xC000; - -static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; -static uint16_t sock_io_mode = 0; -static uint16_t sock_is_sending = 0; -static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; -static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; - -#if _WIZCHIP_ == 5200 - static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,}; -#endif - -#define CHECK_SOCKNUM() \ - do{ \ - if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ - }while(0); \ - -#define CHECK_SOCKMODE(mode) \ - do{ \ - if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ - }while(0); \ - -#define CHECK_SOCKINIT() \ - do{ \ - if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ - }while(0); \ - -#define CHECK_SOCKDATA() \ - do{ \ - if(len == 0) return SOCKERR_DATALEN; \ - }while(0); \ - -void WIZCHIP_EXPORT(socket_reset)(void) { - sock_any_port = SOCK_ANY_PORT_NUM; - sock_io_mode = 0; - sock_is_sending = 0; - /* - memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); - memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t)); - */ - -#if _WIZCHIP_ == 5200 - memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); -#endif -} - -int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) -{ - CHECK_SOCKNUM(); - switch(protocol) - { - case Sn_MR_TCP : - case Sn_MR_UDP : - case Sn_MR_MACRAW : - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW : - case Sn_MR_PPPoE : - break; - #endif - default : - return SOCKERR_SOCKMODE; - } - if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; -#if _WIZCHIP_ == 5200 - if(flag & 0x10) return SOCKERR_SOCKFLAG; -#endif - - if(flag != 0) - { - switch(protocol) - { - case Sn_MR_TCP: - if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; - break; - case Sn_MR_UDP: - if(flag & SF_IGMP_VER2) - { - if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; - } - #if _WIZCHIP_ == 5500 - if(flag & SF_UNI_BLOCK) - { - if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; - } - #endif - break; - default: - break; - } - } - WIZCHIP_EXPORT(close)(sn); - setSn_MR(sn, (protocol | (flag & 0xF0))); - if(!port) - { - port = sock_any_port++; - if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; - } - setSn_PORT(sn,port); - setSn_CR(sn,Sn_CR_OPEN); - while(getSn_CR(sn)); - sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); - sock_is_sending &= ~(1< freesize) len = freesize; // check size not to exceed MAX size. - while(1) - { - freesize = getSn_TX_FSR(sn); - tmp = getSn_SR(sn); - if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) - { - WIZCHIP_EXPORT(close)(sn); - return SOCKERR_SOCKSTATUS; - } - if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; - if(len <= freesize) break; - MICROPY_THREAD_YIELD(); - } - wiz_send_data(sn, buf, len); - #if _WIZCHIP_ == 5200 - sock_next_rd[sn] = getSn_TX_RD(sn) + len; - #endif - setSn_CR(sn,Sn_CR_SEND); - /* wait to process the command... */ - while(getSn_CR(sn)); - sock_is_sending |= (1 << sn); - return len; -} - - -int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len) -{ - uint8_t tmp = 0; - uint16_t recvsize = 0; - CHECK_SOCKNUM(); - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKDATA(); - - recvsize = getSn_RxMAX(sn); - if(recvsize < len) len = recvsize; - while(1) - { - recvsize = getSn_RX_RSR(sn); - tmp = getSn_SR(sn); - if (tmp != SOCK_ESTABLISHED) - { - if(tmp == SOCK_CLOSE_WAIT) - { - if(recvsize != 0) break; - else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) - { - // dpgeorge: Getting here seems to be an orderly shutdown of the - // socket, and trying to get POSIX behaviour we return 0 because: - // "If no messages are available to be received and the peer has per‐ - // formed an orderly shutdown, recv() shall return 0". - // TODO this return value clashes with SOCK_BUSY in non-blocking mode. - WIZCHIP_EXPORT(close)(sn); - return 0; - } - } - else - { - WIZCHIP_EXPORT(close)(sn); - return SOCKERR_SOCKSTATUS; - } - } - if((sock_io_mode & (1< freesize) len = freesize; // check size not to exceed MAX size. - while(1) - { - freesize = getSn_TX_FSR(sn); - if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; - if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY; - if(len <= freesize) break; - MICROPY_THREAD_YIELD(); - }; - wiz_send_data(sn, buf, len); - - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR(wizchip_getsubn()); - #endif - - setSn_CR(sn,Sn_CR_SEND); - /* wait to process the command... */ - while(getSn_CR(sn)); - while(1) - { - tmp = getSn_IR(sn); - if(tmp & Sn_IR_SENDOK) - { - setSn_IR(sn, Sn_IR_SENDOK); - break; - } - //M:20131104 - //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT; - else if(tmp & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR((uint8_t*)"\x00\x00\x00\x00"); - #endif - return SOCKERR_TIMEOUT; - } - //////////// - MICROPY_THREAD_YIELD(); - } - #if _WIZCHIP_ == 5200 // for W5200 ARP errata - setSUBR((uint8_t*)"\x00\x00\x00\x00"); - #endif - return len; -} - - - -int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) -{ - uint8_t mr; - uint8_t head[8]; - uint16_t pack_len=0; - - CHECK_SOCKNUM(); - //CHECK_SOCKMODE(Sn_MR_UDP); - switch((mr=getSn_MR(sn)) & 0x0F) - { - case Sn_MR_UDP: - case Sn_MR_MACRAW: - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW: - case Sn_MR_PPPoE: - break; - #endif - default: - return SOCKERR_SOCKMODE; - } - CHECK_SOCKDATA(); - if(sock_remained_size[sn] == 0) - { - while(1) - { - pack_len = getSn_RX_RSR(sn); - if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; - if( (sock_io_mode & (1< 1514) - { - WIZCHIP_EXPORT(close)(sn); - return SOCKFATAL_PACKLEN; - } - sock_pack_info[sn] = PACK_FIRST; - } - if(len < sock_remained_size[sn]) pack_len = len; - else pack_len = sock_remained_size[sn]; - wiz_recv_data(sn,buf,pack_len); - break; - #if ( _WIZCHIP_ < 5200 ) - case Sn_MR_IPRAW: - if(sock_remained_size[sn] == 0) - { - wiz_recv_data(sn, head, 6); - setSn_CR(sn,Sn_CR_RECV); - while(getSn_CR(sn)); - addr[0] = head[0]; - addr[1] = head[1]; - addr[2] = head[2]; - addr[3] = head[3]; - sock_remained_size[sn] = head[4]; - sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5]; - sock_pack_info[sn] = PACK_FIRST; - } - // - // Need to packet length check - // - if(len < sock_remained_size[sn]) pack_len = len; - else pack_len = sock_remained_size[sn]; - wiz_recv_data(sn, buf, pack_len); // data copy. - break; - #endif - default: - wiz_recv_ignore(sn, pack_len); // data copy. - sock_remained_size[sn] = pack_len; - break; - } - setSn_CR(sn,Sn_CR_RECV); - /* wait to process the command... */ - while(getSn_CR(sn)) ; - sock_remained_size[sn] -= pack_len; - //M20140501 : replace 0x01 with PACK_REMAINED - //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01; - if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED; - // - return pack_len; -} - - -int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg) -{ - uint8_t tmp = 0; - CHECK_SOCKNUM(); - switch(cstype) - { - case CS_SET_IOMODE: - tmp = *((uint8_t*)arg); - if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1< explict type casting - //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; - *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001); - // - break; - case CS_GET_MAXTXBUF: - *((uint16_t*)arg) = getSn_TxMAX(sn); - break; - case CS_GET_MAXRXBUF: - *((uint16_t*)arg) = getSn_RxMAX(sn); - break; - case CS_CLR_INTERRUPT: - if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; - setSn_IR(sn,*(uint8_t*)arg); - break; - case CS_GET_INTERRUPT: - *((uint8_t*)arg) = getSn_IR(sn); - break; - case CS_SET_INTMASK: - if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; - setSn_IMR(sn,*(uint8_t*)arg); - break; - case CS_GET_INTMASK: - *((uint8_t*)arg) = getSn_IMR(sn); - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg) -{ - // M20131220 : Remove warning - //uint8_t tmp; - CHECK_SOCKNUM(); - switch(sotype) - { - case SO_TTL: - setSn_TTL(sn,*(uint8_t*)arg); - break; - case SO_TOS: - setSn_TOS(sn,*(uint8_t*)arg); - break; - case SO_MSS: - setSn_MSSR(sn,*(uint16_t*)arg); - break; - case SO_DESTIP: - setSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - setSn_DPORT(sn, *(uint16_t*)arg); - break; -#if _WIZCHIP_ != 5100 - case SO_KEEPALIVESEND: - CHECK_SOCKMODE(Sn_MR_TCP); - #if _WIZCHIP_ > 5200 - if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; - #endif - setSn_CR(sn,Sn_CR_SEND_KEEP); - while(getSn_CR(sn) != 0) - { - // M20131220 - //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT) - if (getSn_IR(sn) & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - return SOCKERR_TIMEOUT; - } - } - break; - #if _WIZCHIP_ > 5200 - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - setSn_KPALVTR(sn,*(uint8_t*)arg); - break; - #endif -#endif - default: - return SOCKERR_ARG; - } - return SOCK_OK; -} - -int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg) -{ - CHECK_SOCKNUM(); - switch(sotype) - { - case SO_FLAG: - *(uint8_t*)arg = getSn_MR(sn) & 0xF0; - break; - case SO_TTL: - *(uint8_t*) arg = getSn_TTL(sn); - break; - case SO_TOS: - *(uint8_t*) arg = getSn_TOS(sn); - break; - case SO_MSS: - *(uint8_t*) arg = getSn_MSSR(sn); - case SO_DESTIP: - getSn_DIPR(sn, (uint8_t*)arg); - break; - case SO_DESTPORT: - *(uint16_t*) arg = getSn_DPORT(sn); - break; - #if _WIZCHIP_ > 5200 - case SO_KEEPALIVEAUTO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint16_t*) arg = getSn_KPALVTR(sn); - break; - #endif - case SO_SENDBUF: - *(uint16_t*) arg = getSn_TX_FSR(sn); - case SO_RECVBUF: - *(uint16_t*) arg = getSn_RX_RSR(sn); - case SO_STATUS: - *(uint8_t*) arg = getSn_SR(sn); - break; - case SO_REMAINSIZE: - if(getSn_MR(sn) == Sn_MR_TCP) - *(uint16_t*)arg = getSn_RX_RSR(sn); - else - *(uint16_t*)arg = sock_remained_size[sn]; - break; - case SO_PACKINFO: - CHECK_SOCKMODE(Sn_MR_TCP); - *(uint8_t*)arg = sock_pack_info[sn]; - break; - default: - return SOCKERR_SOCKOPT; - } - return SOCK_OK; -} diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/socket.h b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/socket.h deleted file mode 100644 index 2f03a34e..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/socket.h +++ /dev/null @@ -1,472 +0,0 @@ -//***************************************************************************** -// -//! \file socket.h -//! \brief SOCKET APIs Header file. -//! \details SOCKET APIs like as berkeley socket api. -//! \version 1.0.2 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2. Refer to M20140501 -//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED -//! 2. Add the comment as zero byte udp data reception in getsockopt(). -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -/** - * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs - * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. - * But there is a little bit of difference. - * @details - * Comparison between WIZnet and Berkeley SOCKET APIs - * - * - * - * - * - * - * - * - * - * - * - * - *
API WIZnet Berkeley
socket() O O
bind() X O
listen() O O
connect() O O
accept() X O
recv() O O
send() O O
recvfrom() O O
sendto() O O
closesocket() O
close() & disconnect()
O
- * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but, - * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, - * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n - * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. - * When the listen SOCKET accepts a connection request from a client, it keeps listening. - * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n - * Following figure shows network flow diagram by Berkeley SOCKET API. - * @image html Berkeley_SOCKET.jpg "" - * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n - * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, - * it is changed in order to communicate with the client. - * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n - * If there're many listen SOCKET with same listen port number and a client requests a connection, - * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n - * Following figure shows network flow diagram by WIZnet SOCKET API. - * @image html WIZnet_SOCKET.jpg "" - */ -#ifndef _WIZCHIP_SOCKET_H_ -#define _WIZCHIP_SOCKET_H_ - -// use this macro for exported names to avoid name clashes -#define WIZCHIP_EXPORT(name) wizchip_ ## name - -#include "wizchip_conf.h" - -#define SOCKET uint8_t ///< SOCKET type define for legacy driver - -#define SOCK_OK 1 ///< Result is OK about socket process. -#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. -#define SOCK_FATAL -1000 ///< Result is fatal error about socket process. - -#define SOCK_ERROR 0 -#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number -#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option -#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized -#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. -#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. -#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag -#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. -#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. -#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero -#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address -#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred -#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. -#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. - -#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. - -/* - * SOCKET FLAG - */ -#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet -#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2. -#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack. -#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode. - -#if _WIZCHIP_ == 5500 - #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500 - #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500 - #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500 - #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500 -#endif - -#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). - -/* - * UDP & MACRAW Packet Infomation - */ -#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. -#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. -#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. - -// resets all global state associated with the socket interface -void WIZCHIP_EXPORT(socket_reset)(void); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Open a socket. - * @details Initializes the socket with 'sn' passed as parameter and open. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param protocol Protocol type to operate such as TCP, UDP and MACRAW. - * @param port Port number to be bined. - * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n - * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK. - * @sa Sn_MR - * - * @return @b Success : The socket number @b 'sn' passed as parameter\n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n - * @ref SOCKERR_SOCKFLAG - Invaild socket flag. - */ -int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Close a socket. - * @details It closes the socket with @b'sn' passed as parameter. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number - */ -int8_t WIZCHIP_EXPORT(close)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Listen to a connection request from a client. - * @details It is listening to a connection request from a client. - * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n - * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. - */ -int8_t WIZCHIP_EXPORT(listen)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to connect a server. - * @details It requests connection to the server with destination IP address and port number passed as parameter.\n - * @note It is valid only in TCP client mode. - * In block io mode, it does not return until connection is completed. - * In Non-block io mode, it return @ref SOCK_BUSY immediately. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n - * @ref SOCKERR_SOCKMODE - Invalid socket mode\n - * @ref SOCKERR_SOCKINIT - Socket is not initialized\n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n - * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n - */ -int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to disconnect a connection socket. - * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. - * @note It is valid only in TCP server or client mode. \n - * In block io mode, it does not return until disconnection is completed. \n - * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n - - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Send data to the connected peer in TCP socket. - * @details It is used to send outgoing data to the connected socket. - * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n - * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer containing data to be sent. - * @param len The byte length of data in buf. - * @return @b Success : The sent data size \n - * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive data from the connected peer. - * @details It is used to read incoming data from the connected socket.\n - * It waits for data as much as the application wants to receive. - * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n - * In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer. \n - * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. \n - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * @return @b Success : The real received data size \n - * @b Fail :\n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. - * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n - * Even if the connectionless socket has been previously connected to a specific address, - * the address and port number parameters override the destination address for that particular datagram only. - * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than len. - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to send outgoing data. - * @param len The byte length of data in buf. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * @param port Destination port number. - * - * @return @b Success : The sent data size \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_IPINVALID - Wrong server IP address\n - * @ref SOCKERR_PORTZERO - Server port zero\n - * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive datagram of UDP or MACRAW - * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n - * This function is used to receive UDP and MAC_RAW mode, and handle the header as well. - * This function can divide to received the packet data. - * On the MACRAW SOCKET, the addr and port parameters are ignored. - * @note In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer - * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. - * - * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * When the received packet size <= len, receives data as packet sized. - * When others, receives data as len. - * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. - * It is valid only when the first call recvfrom for receiving the packet. - * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * @param port Pointer variable of destination port number. - * It is valid only when the first call recvform for receiving the packet. -* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). - * - * @return @b Success : This function return real received data size for success.\n - * @b Fail : @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKBUSY - Socket is busy. - */ -int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); - - -///////////////////////////// -// SOCKET CONTROL & OPTION // -///////////////////////////// -#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). -#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). - -/** - * @defgroup DATA_TYPE DATA TYPE - */ - -/** - * @ingroup DATA_TYPE - * @brief The kind of Socket Interrupt. - * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() - */ -typedef enum -{ - SIK_CONNECTED = (1 << 0), ///< connected - SIK_DISCONNECTED = (1 << 1), ///< disconnected - SIK_RECEIVED = (1 << 2), ///< data received - SIK_TIMEOUT = (1 << 3), ///< timeout occurred - SIK_SENT = (1 << 4), ///< send ok - SIK_ALL = 0x1F, ///< all interrupt -}sockint_kind; - -/** - * @ingroup DATA_TYPE - * @brief The type of @ref ctlsocket(). - */ -typedef enum -{ - CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK - CS_GET_IOMODE, ///< get socket IO mode - CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory - CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory - CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind - CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind - CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind - CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind -}ctlsock_type; - - -/** - * @ingroup DATA_TYPE - * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() - */ -typedef enum -{ - SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to flag in @ref socket(). - SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() ) - SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() ) - SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() ) - SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() ) - SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() ) -#if _WIZCHIP_ != 5100 - SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode - #if _WIZCHIP_ > 5200 - SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode - #endif -#endif - SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR() - SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR() - SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR() - SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode. - SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode. -}sockopt_type; - -/** - * @ingroup WIZnet_socket_APIs - * @brief Control socket. - * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information. - * Refer to @ref ctlsock_type. - * @param sn socket number - * @param cstype type of control socket. refer to @ref ctlsock_type. - * @param arg Data type and value is determined according to @ref ctlsock_type. \n - * - * - * - * - * - *
@b cstype @b data type@b value
@ref CS_SET_IOMODE \n @ref CS_GET_IOMODE uint8_t @ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK
@ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF uint16_t 0 ~ 16K
@ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK @ref sockint_kind @ref SIK_CONNECTED, etc.
- * @return @b Success @ref SOCK_OK \n - * @b fail @ref SOCKERR_ARG - Invalid argument\n - */ -int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief set socket options - * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. - * - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to sotype. \n - * - * - * - * - * - * - * - * - * - *
@b sotype @b data type@b value
@ref SO_TTL uint8_t 0 ~ 255
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t 0 ~ 65535
@ref SO_KEEPALIVESEND null null
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
- * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n - */ -int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg); - -/** - * @ingroup WIZnet_socket_APIs - * @brief get socket options - * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to sotype. \n - * - * - * - * - * - * - * - * - * - * - * - * - * - *
@b sotype @b data type@b value
@ref SO_FLAG uint8_t @ref SF_ETHER_OWN, etc...
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP uint8_t[4]
@ref SO_DESTPORT uint16_t
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
@ref SO_SENDBUF uint16_t 0 ~ 65535
@ref SO_RECVBUF uint16_t 0 ~ 65535
@ref SO_STATUS uint8_t @ref SOCK_ESTABLISHED, etc..
@ref SO_REMAINSIZE uint16_t 0~ 65535
@ref SO_PACKINFO uint8_t @ref PACK_FIRST, etc...
- * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * @note - * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n - * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, - * This means the zero byte UDP data(UDP Header only) received. - */ -int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg); - -#endif // _WIZCHIP_SOCKET_H_ diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5200/w5200.c b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5200/w5200.c deleted file mode 100644 index 8c378079..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5200/w5200.c +++ /dev/null @@ -1,206 +0,0 @@ -// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200 - -//***************************************************************************** -// -//! \file w5500.c -//! \brief W5500 HAL Interface. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2 -//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 -//! Fixed the problem on porting into under 32bit MCU -//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh -//! Thank for your interesting and serious advices. -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.0.1 -//! 1. Remove warning -//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ -//! for loop optimized(removed). refer to M20131220 -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include "w5200.h" - -#define SMASK (0x7ff) /* tx buffer mask */ -#define RMASK (0x7ff) /* rx buffer mask */ -#define SSIZE (2048) /* max tx buffer size */ -#define RSIZE (2048) /* max rx buffer size */ - -#define TXBUF_BASE (0x8000) -#define RXBUF_BASE (0xc000) -#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */ -#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */ - -uint8_t WIZCHIP_READ(uint32_t AddrSel) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x00, - 0x01, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - uint8_t ret; - WIZCHIP.IF.SPI._read_bytes(&ret, 1); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); - - return ret; -} - -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[5] = { - AddrSel >> 8, - AddrSel, - 0x80, - 0x01, - wb, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 5); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x00 | ((len >> 8) & 0x7f), - len & 0xff, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - WIZCHIP.IF.SPI._read_bytes(pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - uint8_t spi_data[4] = { - AddrSel >> 8, - AddrSel, - 0x80 | ((len >> 8) & 0x7f), - len & 0xff, - }; - WIZCHIP.IF.SPI._write_bytes(spi_data, 4); - WIZCHIP.IF.SPI._write_bytes(pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -uint16_t getSn_TX_FSR(uint8_t sn) { - uint16_t val = 0, val1 = 0; - do { - val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); - if (val1 != 0) { - val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); - } - } while (val != val1); - return val; -} - -uint16_t getSn_RX_RSR(uint8_t sn) { - uint16_t val = 0, val1 = 0; - do { - val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); - if (val1 != 0) { - val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); - } - } while (val != val1); - return val; -} - -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { - if (len == 0) { - return; - } - - uint16_t ptr = getSn_TX_WR(sn); - uint16_t offset = ptr & SMASK; - uint32_t addr = offset + SBASE(sn); - - if (offset + len > SSIZE) { - // implement wrap-around circular buffer - uint16_t size = SSIZE - offset; - WIZCHIP_WRITE_BUF(addr, wizdata, size); - WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size); - } else { - WIZCHIP_WRITE_BUF(addr, wizdata, len); - } - - ptr += len; - setSn_TX_WR(sn, ptr); -} - -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { - if (len == 0) { - return; - } - - uint16_t ptr = getSn_RX_RD(sn); - uint16_t offset = ptr & RMASK; - uint16_t addr = RBASE(sn) + offset; - - if (offset + len > RSIZE) { - // implement wrap-around circular buffer - uint16_t size = RSIZE - offset; - WIZCHIP_READ_BUF(addr, wizdata, size); - WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size); - } else { - WIZCHIP_READ_BUF(addr, wizdata, len); - } - - ptr += len; - setSn_RX_RD(sn, ptr); -} - -void wiz_recv_ignore(uint8_t sn, uint16_t len) { - uint16_t ptr = getSn_RX_RD(sn); - ptr += len; - setSn_RX_RD(sn, ptr); -} diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5200/w5200.h b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5200/w5200.h deleted file mode 100644 index 63561940..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5200/w5200.h +++ /dev/null @@ -1,2092 +0,0 @@ -// dpgeorge: this file taken from w5500/w5500.h and adapted to W5200 - -//***************************************************************************** -// -//! \file w5500.h -//! \brief W5500 HAL Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _W5200_H_ -#define _W5200_H_ - -#include -#include "../wizchip_conf.h" -//#include "board.h" - -#define _W5200_IO_BASE_ 0x00000000 - -#define WIZCHIP_CREG_ADDR(addr) (_W5200_IO_BASE_ + (addr)) - -#define WIZCHIP_CH_BASE (0x4000) -#define WIZCHIP_CH_SIZE (0x100) -#define WIZCHIP_SREG_ADDR(sn, addr) (_W5200_IO_BASE_ + WIZCHIP_CH_BASE + (sn) * WIZCHIP_CH_SIZE + (addr)) - -////////////////////////////// -//-------------------------- defgroup --------------------------------- -/** - * @defgroup W5500 W5500 - * - * @brief WHIZCHIP register defines and I/O functions of @b W5500. - * - * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group - * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function - */ - - -/** - * @defgroup WIZCHIP_register WIZCHIP register - * @ingroup W5500 - * - * @brief WHIZCHIP register defines register group of @b W5500. - * - * - @ref Common_register_group : Common register group - * - @ref Socket_register_group : \c SOCKET n register group - */ - - -/** - * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions - * @ingroup W5500 - * - * @brief This supports the basic I/O functions for @ref WIZCHIP_register. - * - * - Basic I/O function \n - * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n - * - * - @ref Common_register_group access functions \n - * -# @b Mode \n - * getMR(), setMR() - * -# @b Interrupt \n - * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() - * -# Network Information \n - * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() - * -# @b Retransmission \n - * getRCR(), setRCR(), getRTR(), setRTR() - * -# @b PPPoE \n - * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() - * -# ICMP packet \n - * getUIPR(), getUPORTR() - * -# @b etc. \n - * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n - * - * - \ref Socket_register_group access functions \n - * -# SOCKET control \n - * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() - * -# SOCKET information \n - * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() - * getSn_MSSR(), setSn_MSSR() - * -# SOCKET communication \n - * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n - * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n - * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n - * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() - * -# IP header field \n - * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n - * getSn_TTL(), setSn_TTL() - */ - - - -/** - * @defgroup Common_register_group Common register - * @ingroup WIZCHIP_register - * - * @brief Common register group\n - * It set the basic for the networking\n - * It set the configuration such as interrupt, network information, ICMP, etc. - * @details - * @sa MR : Mode register. - * @sa GAR, SUBR, SHAR, SIPR - * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. - * @sa RTR, RCR : Data retransmission. - * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. - * @sa UIPR, UPORTR : ICMP message. - * @sa PHYCFGR, VERSIONR : etc. - */ - - - -/** - * @defgroup Socket_register_group Socket register - * @ingroup WIZCHIP_register - * - * @brief Socket register group.\n - * Socket register configures and control SOCKETn which is necessary to data communication. - * @details - * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control - * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information - * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. - * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication - */ - - - - /** - * @defgroup Basic_IO_function Basic I/O function - * @ingroup WIZCHIP_IO_Functions - * @brief These are basic input/output functions to read values from register or write values to register. - */ - -/** - * @defgroup Common_register_access_function Common register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access common registers. - */ - -/** - * @defgroup Socket_register_access_function Socket register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access socket registers. - */ - -//------------------------------- defgroup end -------------------------------------------- -//----------------------------- W5500 Common Registers IOMAP ----------------------------- -/** - * @ingroup Common_register_group - * @brief Mode Register address(R/W)\n - * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. - * @details Each bit of @ref MR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
- * - \ref MR_RST : Reset - * - \ref MR_WOL : Wake on LAN - * - \ref MR_PB : Ping block - * - \ref MR_PPPOE : PPPoE mode - * - \ref MR_FARP : Force ARP mode - */ -#define MR WIZCHIP_CREG_ADDR(0x0000) - -/** - * @ingroup Common_register_group - * @brief Gateway IP Register address(R/W) - * @details @ref GAR configures the default gateway address. - */ -#define GAR WIZCHIP_CREG_ADDR(0x0001) - -/** - * @ingroup Common_register_group - * @brief Subnet mask Register address(R/W) - * @details @ref SUBR configures the subnet mask address. - */ -#define SUBR WIZCHIP_CREG_ADDR(0x0005) - -/** - * @ingroup Common_register_group - * @brief Source MAC Register address(R/W) - * @details @ref SHAR configures the source hardware address. - */ -#define SHAR WIZCHIP_CREG_ADDR(0x0009) - -/** - * @ingroup Common_register_group - * @brief Source IP Register address(R/W) - * @details @ref SIPR configures the source IP address. - */ -#define SIPR WIZCHIP_CREG_ADDR(0x000f) - -/** - * @ingroup Common_register_group - * @brief Set Interrupt low level timer register address(R/W) - * @details @ref INTLEVEL configures the Interrupt Assert Time. - */ -//#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt Register(R/W) - * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. - * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n - * Each bit of @ref IR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
- * - \ref IR_CONFLICT : IP conflict - * - \ref IR_UNREACH : Destination unreachable - * - \ref IR_PPPoE : PPPoE connection close - * - \ref IR_MP : Magic packet - */ -#define IR WIZCHIP_CREG_ADDR(0x0015) - -/** - * @ingroup Common_register_group - * @brief Interrupt mask register(R/W) - * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. - * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, - * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n - * Each bit of @ref IMR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
- * - \ref IM_IR7 : IP Conflict Interrupt Mask - * - \ref IM_IR6 : Destination unreachable Interrupt Mask - * - \ref IM_IR5 : PPPoE Close Interrupt Mask - * - \ref IM_IR4 : Magic Packet Interrupt Mask - */ -#define IMR WIZCHIP_CREG_ADDR(0x0016) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Register(R/W) - * @details @ref SIR indicates the interrupt status of Socket.\n - * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n - * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ -//#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Mask Register(R/W) - * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. - * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. - * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is - */ -//#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Timeout register address( 1 is 100us )(R/W) - * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 - * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response - * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). - * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. - */ -#define RTR WIZCHIP_CREG_ADDR(0x0017) - -/** - * @ingroup Common_register_group - * @brief Retry count register(R/W) - * @details @ref RCR configures the number of time of retransmission. - * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . - */ -#define RCR WIZCHIP_CREG_ADDR(0x0019) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Request Timer register in PPPoE mode(R/W) - * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. - */ -#define PTIMER WIZCHIP_CREG_ADDR(0x0028) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Magic number register in PPPoE mode(R/W) - * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. - */ -#define PMAGIC WIZCHIP_CREG_ADDR(0x0029) - -/** - * @ingroup Common_register_group - * @brief PPP Destination MAC Register address(R/W) - * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. - */ -//#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Session Identification Register(R/W) - * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. - */ -//#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Maximum Segment Size(MSS) register(R/W) - * @details @ref PMRU configures the maximum receive unit of PPPoE. - */ -//#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable IP register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates - * the destination IP address & port number respectively. - */ -//#define UIPR (_W5500_IO_BASE_ + (0x002a << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable Port register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR - * indicates the destination IP address & port number respectively. - */ -//#define UPORTR (_W5500_IO_BASE_ + (0x002e << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PHY Status Register(R/W) - * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. - */ -//#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) -#define PHYSTATUS WIZCHIP_CREG_ADDR(0x0035) - -// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief chip version register address(R) - * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. - */ -//#define VERSIONR (_W5200_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - - -//----------------------------- W5500 Socket Registers IOMAP ----------------------------- -/** - * @ingroup Socket_register_group - * @brief socket Mode register(R/W) - * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n - * Each bit of @ref Sn_MR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
- * - @ref Sn_MR_MULTI : Support UDP Multicasting - * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting - * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag - * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting - * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode - * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating - * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * - Protocol - * - * - * - * - * - * - *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n - * - @ref Sn_MR_UDP : UDP - * - @ref Sn_MR_TCP : TCP - * - @ref Sn_MR_CLOSE : Unused socket - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR(N) WIZCHIP_SREG_ADDR(N, 0x0000) - -/** - * @ingroup Socket_register_group - * @brief Socket command register(R/W) - * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n - * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. - * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n - * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. - * - @ref Sn_CR_OPEN : Initialize or open socket. - * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) - * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) - * - @ref Sn_CR_DISCON : Send closing request in TCP mode. - * - @ref Sn_CR_CLOSE : Close socket. - * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. - * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. - * - @ref Sn_CR_SEND_KEEP : Send keep alive message. - * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. - */ -#define Sn_CR(N) WIZCHIP_SREG_ADDR(N, 0x0001) - -/** - * @ingroup Socket_register_group - * @brief Socket interrupt register(R) - * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n - * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n - * In order to clear the @ref Sn_IR bit, the host should write the bit to \n - * - * - * - *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt - * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt - * - \ref Sn_IR_RECV : RECV Interrupt - * - \ref Sn_IR_DISCON : DISCON Interrupt - * - \ref Sn_IR_CON : CON Interrupt - */ -#define Sn_IR(N) WIZCHIP_SREG_ADDR(N, 0x0002) - -/** - * @ingroup Socket_register_group - * @brief Socket status register(R) - * @details @ref Sn_SR indicates the status of Socket n.\n - * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. - * @par Normal status - * - @ref SOCK_CLOSED : Closed - * - @ref SOCK_INIT : Initiate state - * - @ref SOCK_LISTEN : Listen state - * - @ref SOCK_ESTABLISHED : Success to connect - * - @ref SOCK_CLOSE_WAIT : Closing state - * - @ref SOCK_UDP : UDP socket - * - @ref SOCK_MACRAW : MAC raw mode socket - *@par Temporary status during changing the status of Socket n. - * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. - * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. - * - @ref SOCK_FIN_WAIT : Connection state - * - @ref SOCK_CLOSING : Closing state - * - @ref SOCK_TIME_WAIT : Closing state - * - @ref SOCK_LAST_ACK : Closing state - */ -#define Sn_SR(N) WIZCHIP_SREG_ADDR(N, 0x0003) - -/** - * @ingroup Socket_register_group - * @brief source port register(R/W) - * @details @ref Sn_PORT configures the source port number of Socket n. - * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. - */ -#define Sn_PORT(N) WIZCHIP_SREG_ADDR(N, 0x0004) - -/** - * @ingroup Socket_register_group - * @brief Peer MAC register address(R/W) - * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or - * it indicates that it is acquired in ARP-process by CONNECT/SEND command. - */ -#define Sn_DHAR(N) WIZCHIP_SREG_ADDR(N, 0x0006) - -/** - * @ingroup Socket_register_group - * @brief Peer IP register address(R/W) - * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. - * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. - * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. - */ -#define Sn_DIPR(N) WIZCHIP_SREG_ADDR(N, 0x000c) - -/** - * @ingroup Socket_register_group - * @brief Peer port register address(R/W) - * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. - * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. - * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. - */ -#define Sn_DPORT(N) WIZCHIP_SREG_ADDR(N, 0x0010) - -/** - * @ingroup Socket_register_group - * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) - * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. - */ -#define Sn_MSSR(N) WIZCHIP_SREG_ADDR(N, 0x0012) - -// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief IP Type of Service(TOS) Register(R/W) - * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TOS(N) WIZCHIP_SREG_ADDR(N, 0x0015) -/** - * @ingroup Socket_register_group - * @brief IP Time to live(TTL) Register(R/W) - * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TTL(N) WIZCHIP_SREG_ADDR(N, 0x0016) -// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Receive memory size register(R/W) - * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. - * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data cannot be normally received from a peer. - * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, - * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data reception error is occurred. - */ -#define Sn_RXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001e) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory size register(R/W) - * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data can�t be normally transmitted to a peer. - * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, - * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data transmission error is occurred. - */ -#define Sn_TXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001f) - -/** - * @ingroup Socket_register_group - * @brief Transmit free memory size register(R) - * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. - * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. - * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, - * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, - * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. - */ -#define Sn_TX_FSR(N) WIZCHIP_SREG_ADDR(N, 0x0020) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory read pointer register address(R) - * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. - * After its initialization, it is auto-increased by SEND command. - * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. - * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. - * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_TX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0022) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory write pointer register address(R/W) - * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n - * It should be read or be updated like as follows.\n - * 1. Read the starting address for saving the transmitting data.\n - * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n - * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. - * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value.\n - * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command - */ -#define Sn_TX_WR(N) WIZCHIP_SREG_ADDR(N, 0x0024) - -/** - * @ingroup Socket_register_group - * @brief Received data size register(R) - * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. - * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between - * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) - */ -#define Sn_RX_RSR(N) WIZCHIP_SREG_ADDR(N, 0x0026) - -/** - * @ingroup Socket_register_group - * @brief Read point of Receive memory(R/W) - * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n - * 1. Read the starting save address of the received data.\n - * 2. Read data from the starting address of Socket n RX Buffer.\n - * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. - * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, - * update with the lower 16bits value ignored the carry bit.\n - * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. - */ -#define Sn_RX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0028) - -/** - * @ingroup Socket_register_group - * @brief Write point of Receive memory(R) - * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. - * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_RX_WR(N) WIZCHIP_SREG_ADDR(N, 0x002a) - -/** - * @ingroup Socket_register_group - * @brief socket interrupt mask register(R) - * @details @ref Sn_IMR masks the interrupt of Socket n. - * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is - * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is - * Host is interrupted by asserted INTn PIN to low. - */ -//#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Fragment field value in IP header register(R/W) - * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). - */ -//#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Keep Alive Timer register(R/W) - * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, - * and ignored in other modes. The time unit is 5s. - * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. - * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). - * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, - * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). - * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. - */ -//#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - - -//----------------------------- W5500 Register values ----------------------------- - -/* MODE register values */ -/** - * @brief Reset - * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. - */ -#define MR_RST 0x80 - -/** - * @brief Wake on LAN - * @details 0 : Disable WOL mode\n - * 1 : Enable WOL mode\n - * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. - * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) - * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and - * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. - */ -#define MR_WOL 0x20 - -/** - * @brief Ping block - * @details 0 : Disable Ping block\n - * 1 : Enable Ping block\n - * If the bit is it blocks the response to a ping request. - */ -#define MR_PB 0x10 - -/** - * @brief Enable PPPoE - * @details 0 : DisablePPPoE mode\n - * 1 : EnablePPPoE mode\n - * If you use ADSL, this bit should be - */ -#define MR_PPPOE 0x08 - -/** - * @brief Enable UDP_FORCE_ARP CHECHK - * @details 0 : Disable Force ARP mode\n - * 1 : Enable Force ARP mode\n - * In Force ARP mode, It forces on sending ARP Request whenever data is sent. - */ -#define MR_FARP 0x02 - -/* IR register values */ -/** - * @brief Check IP conflict. - * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. - */ -#define IR_CONFLICT 0x80 - -/** - * @brief Get the destination unreachable message in UDP sending. - * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as - * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. - */ -#define IR_UNREACH 0x40 - -/** - * @brief Get the PPPoE close message. - * @details When PPPoE is disconnected during PPPoE mode, this bit is set. - */ -#define IR_PPPoE 0x20 - -/** - * @brief Get the magic packet interrupt. - * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. - */ -#define IR_MP 0x10 - - -/* PHYCFGR register value */ -#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. -#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value -#define PHYCFGR_OPMDC_ALLA (7<<3) -#define PHYCFGR_OPMDC_PDOWN (6<<3) -#define PHYCFGR_OPMDC_NA (5<<3) -#define PHYCFGR_OPMDC_100FA (4<<3) -#define PHYCFGR_OPMDC_100F (3<<3) -#define PHYCFGR_OPMDC_100H (2<<3) -#define PHYCFGR_OPMDC_10F (1<<3) -#define PHYCFGR_OPMDC_10H (0<<3) -#define PHYCFGR_DPX_FULL (1<<2) -#define PHYCFGR_DPX_HALF (0<<2) -#define PHYCFGR_SPD_100 (1<<1) -#define PHYCFGR_SPD_10 (0<<1) -#define PHYCFGR_LNK_ON (1<<0) -#define PHYCFGR_LNK_OFF (0<<0) - -// PHYSTATUS register -#define PHYSTATUS_POWERDOWN (0x08) -#define PHYSTATUS_LINK (0x20) - -/* IMR register values */ -/** - * @brief IP Conflict Interrupt Mask. - * @details 0: Disable IP Conflict Interrupt\n - * 1: Enable IP Conflict Interrupt - */ -#define IM_IR7 0x80 - -/** - * @brief Destination unreachable Interrupt Mask. - * @details 0: Disable Destination unreachable Interrupt\n - * 1: Enable Destination unreachable Interrupt - */ -#define IM_IR6 0x40 - -/** - * @brief PPPoE Close Interrupt Mask. - * @details 0: Disable PPPoE Close Interrupt\n - * 1: Enable PPPoE Close Interrupt - */ -#define IM_IR5 0x20 - -/** - * @brief Magic Packet Interrupt Mask. - * @details 0: Disable Magic Packet Interrupt\n - * 1: Enable Magic Packet Interrupt - */ -#define IM_IR4 0x10 - -/* Sn_MR Default values */ -/** - * @brief Support UDP Multicasting - * @details 0 : disable Multicasting\n - * 1 : enable Multicasting\n - * This bit is applied only during UDP mode(P[3:0] = 010.\n - * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number - * before Socket n is opened by OPEN command of @ref Sn_CR. - */ -#define Sn_MR_MULTI 0x80 - -/** - * @brief Broadcast block in UDP Multicasting. - * @details 0 : disable Broadcast Blocking\n - * 1 : enable Broadcast Blocking\n - * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m - * In addition, This bit does when MACRAW mode(P[3:0] = 100 - */ -//#define Sn_MR_BCASTB 0x40 - -/** - * @brief No Delayed Ack(TCP), Multicast flag - * @details 0 : Disable No Delayed ACK option\n - * 1 : Enable No Delayed ACK option\n - * This bit is applied only during TCP mode (P[3:0] = 001.\n - * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n - * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. - */ -#define Sn_MR_ND 0x20 - -/** - * @brief Unicast Block in UDP Multicasting - * @details 0 : disable Unicast Blocking\n - * 1 : enable Unicast Blocking\n - * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = - */ -//#define Sn_MR_UCASTB 0x10 - -/** - * @brief MAC LAYER RAW SOCK - * @details This configures the protocol mode of Socket n. - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR_MACRAW 0x04 - -#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ - -/** - * @brief UDP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_UDP 0x02 - -/** - * @brief TCP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_TCP 0x01 - -/** - * @brief Unused socket - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_CLOSE 0x00 - -/* Sn_MR values used with Sn_MR_MACRAW */ -/** - * @brief MAC filter enable in @ref Sn_MR_MACRAW mode - * @details 0 : disable MAC Filtering\n - * 1 : enable MAC Filtering\n - * This bit is applied only during MACRAW mode(P[3:0] = 100.\n - * When set as W5500 can only receive broadcasting packet or packet sent to itself. - * When this bit is W5500 can receive all packets on Ethernet. - * If user wants to implement Hybrid TCP/IP stack, - * it is recommended that this bit is set as for reducing host overhead to process the all received packets. - */ -#define Sn_MR_MFEN Sn_MR_MULTI - -/** - * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : using IGMP version 2\n - * 1 : using IGMP version 1\n - * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = - * It configures the version for IGMP messages (Join/Leave/Report). - */ -#define Sn_MR_MMB Sn_MR_ND - -/** - * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : disable IPv6 Blocking\n - * 1 : enable IPv6 Blocking\n - * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. - */ -#define Sn_MR_MIP6B Sn_MR_UCASTB - -/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ -/** - * @brief IGMP version used in UDP mulitcasting - * @details 0 : disable Multicast Blocking\n - * 1 : enable Multicast Blocking\n - * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. - */ -#define Sn_MR_MC Sn_MR_ND - -/* Sn_MR alternate values */ -/** - * @brief For Berkeley Socket API - */ -#define SOCK_STREAM Sn_MR_TCP - -/** - * @brief For Berkeley Socket API - */ -#define SOCK_DGRAM Sn_MR_UDP - - -/* Sn_CR values */ -/** - * @brief Initialize or open socket - * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). - * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n - * - * - * - * - * - * - *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
- */ -#define Sn_CR_OPEN 0x01 - -/** - * @brief Wait connection request in TCP mode(Server mode) - * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). - * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client - * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. - * When a �TCP clientconnection request is successfully established, - * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes - * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. - */ -#define Sn_CR_LISTEN 0x02 - -/** - * @brief Send connection request in TCP mode(Client mode) - * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). - * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n - * The connect-request fails in the following three cases.\n - * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n - * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n - * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client - */ -#define Sn_CR_CONNECT 0x04 - -/** - * @brief Send closing request in TCP mode - * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n - * @par Active close - * it transmits disconnect-request(FIN packet) to the connected peer\n - * @par Passive close - * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n - * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n - * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note Valid only in TCP mode. - */ -#define Sn_CR_DISCON 0x08 - -/** - * @brief Close socket - * @details Sn_SR is changed to @ref SOCK_CLOSED. - */ -#define Sn_CR_CLOSE 0x10 - -/** - * @brief Update TX buffer pointer and send data - * @details SEND transmits all the data in the Socket n TX buffer.\n - * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, - * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). - */ -#define Sn_CR_SEND 0x20 - -/** - * @brief Send data with MAC address, so without ARP process - * @details The basic operation is same as SEND.\n - * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n - * But SEND_MAC transmits data without the automatic ARP-process.\n - * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. - * @note Valid only in UDP mode. - */ -#define Sn_CR_SEND_MAC 0x21 - -/** - * @brief Send keep alive message - * @details It checks the connection status by sending 1byte keep-alive packet.\n - * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. - * @note Valid only in TCP mode. - */ -#define Sn_CR_SEND_KEEP 0x22 - -/** - * @brief Update RX buffer pointer and receive data - * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n - * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), - * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). - */ -#define Sn_CR_RECV 0x40 - -/* Sn_IR values */ -/** - * @brief SEND_OK Interrupt - * @details This is issued when SEND command is completed. - */ -#define Sn_IR_SENDOK 0x10 - -/** - * @brief TIMEOUT Interrupt - * @details This is issued when ARPTO or TCPTO occurs. - */ -#define Sn_IR_TIMEOUT 0x08 - -/** - * @brief RECV Interrupt - * @details This is issued whenever data is received from a peer. - */ -#define Sn_IR_RECV 0x04 - -/** - * @brief DISCON Interrupt - * @details This is issued when FIN or FIN/ACK packet is received from a peer. - */ -#define Sn_IR_DISCON 0x02 - -/** - * @brief CON Interrupt - * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. - */ -#define Sn_IR_CON 0x01 - -/* Sn_SR values */ -/** - * @brief Closed - * @details This indicates that Socket n is released.\N - * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. - */ -#define SOCK_CLOSED 0x00 - -/** - * @brief Initiate state - * @details This indicates Socket n is opened with TCP mode.\N - * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N - * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. - */ -#define SOCK_INIT 0x13 - -/** - * @brief Listen state - * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n - * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n - * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . - */ -#define SOCK_LISTEN 0x14 - -/** - * @brief Connection state - * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n - * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n - * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n - * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. - */ -#define SOCK_SYNSENT 0x15 - -/** - * @brief Connection state - * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n - * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n - * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_SYNRECV 0x16 - -/** - * @brief Success to connect - * @details This indicates the status of the connection of Socket n.\n - * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or - * when the CONNECT command is successful.\n - * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. - */ -#define SOCK_ESTABLISHED 0x17 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_FIN_WAIT 0x18 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_CLOSING 0x1A - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_TIME_WAIT 0x1B - -/** - * @brief Closing state - * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n - * This is half-closing status, and data can be transferred.\n - * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. - */ -#define SOCK_CLOSE_WAIT 0x1C - -/** - * @brief Closing state - * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n - * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_LAST_ACK 0x1D - -/** - * @brief UDP socket - * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n - * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n - * Unlike TCP mode, data can be transfered without the connection-process. - */ -#define SOCK_UDP 0x22 - -//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ - -/** - * @brief MAC raw mode socket - * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n - * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n - * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. - */ -#define SOCK_MACRAW 0x42 - -//#define SOCK_PPPOE 0x5F - -/* IP PROTOCOL */ -#define IPPROTO_IP 0 //< Dummy for IP -#define IPPROTO_ICMP 1 //< Control message protocol -#define IPPROTO_IGMP 2 //< Internet group management protocol -#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) -#define IPPROTO_TCP 6 //< TCP -#define IPPROTO_PUP 12 //< PUP -#define IPPROTO_UDP 17 //< UDP -#define IPPROTO_IDP 22 //< XNS idp -#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol -#define IPPROTO_RAW 255 //< Raw IP packet - - -/** - * @brief Enter a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n \n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt.\n - * In OS environment, You can replace it to critical section api supported by OS. - * - * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * \sa WIZCHIP_CRITICAL_EXIT() - */ -#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() - -/** - * @brief Exit a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n\n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt. \n - * In OS environment, You can replace it to critical section api supported by OS. - * - * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * @sa WIZCHIP_CRITICAL_ENTER() - */ -#ifdef _exit -#undef _exit -#endif -#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() - - - -//////////////////////// -// Basic I/O Function // -//////////////////////// - -/** - * @ingroup Basic_IO_function - * @brief It reads 1 byte value from a register. - * @param AddrSel Register address - * @return The value of register - */ -uint8_t WIZCHIP_READ (uint32_t AddrSel); - -/** - * @ingroup Basic_IO_function - * @brief It writes 1 byte value to a register. - * @param AddrSel Register address - * @param wb Write data - * @return void - */ -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); - -/** - * @ingroup Basic_IO_function - * @brief It reads sequence data from registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to read data - * @param len Data length - */ -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It writes sequence data to registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to write data - * @param len Data length - */ -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -///////////////////////////////// -// Common Register I/O function // -///////////////////////////////// -/** - * @ingroup Common_register_access_function - * @brief Set Mode Register - * @param (uint8_t)mr The value to be set. - * @sa getMR() - */ -#define setMR(mr) \ - WIZCHIP_WRITE(MR,mr) - - -/** - * @ingroup Common_register_access_function - * @brief Get Mode Register - * @return uint8_t. The value of Mode register. - * @sa setMR() - */ -#define getMR() \ - WIZCHIP_READ(MR) - -/** - * @ingroup Common_register_access_function - * @brief Set gateway IP address - * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. - * @sa getGAR() - */ -#define setGAR(gar) \ - WIZCHIP_WRITE_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Get gateway IP address - * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. - * @sa setGAR() - */ -#define getGAR(gar) \ - WIZCHIP_READ_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Set subnet mask address - * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. - * @sa getSUBR() - */ -#define setSUBR(subr) \ - WIZCHIP_WRITE_BUF(SUBR, subr,4) - - -/** - * @ingroup Common_register_access_function - * @brief Get subnet mask address - * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. - * @sa setSUBR() - */ -#define getSUBR(subr) \ - WIZCHIP_READ_BUF(SUBR, subr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set local MAC address - * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. - * @sa getSHAR() - */ -#define setSHAR(shar) \ - WIZCHIP_WRITE_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local MAC address - * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. - * @sa setSHAR() - */ -#define getSHAR(shar) \ - WIZCHIP_READ_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set local IP address - * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. - * @sa getSIPR() - */ -#define setSIPR(sipr) \ - WIZCHIP_WRITE_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. - * @sa setSIPR() - */ -#define getSIPR(sipr) \ - WIZCHIP_READ_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set INTLEVEL register - * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. - * @sa getINTLEVEL() - */ -// dpgeorge: not yet implemented -#define setINTLEVEL(intlevel) (void)intlevel -#if 0 -#define setINTLEVEL(intlevel) {\ - WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ - } -#endif - - -/** - * @ingroup Common_register_access_function - * @brief Get INTLEVEL register - * @return uint16_t. Value of @ref INTLEVEL register. - * @sa setINTLEVEL() - */ -// dpgeorge: not yet implemented -#define getINTLEVEL() (0) -#if 0 -#define getINTLEVEL() \ - ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref IR register - * @param (uint8_t)ir Value to set @ref IR register. - * @sa getIR() - */ -#define setIR(ir) \ - WIZCHIP_WRITE(IR, (ir & 0xF0)) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IR register - * @return uint8_t. Value of @ref IR register. - * @sa setIR() - */ -#define getIR() \ - (WIZCHIP_READ(IR) & 0xF0) -/** - * @ingroup Common_register_access_function - * @brief Set @ref IMR register - * @param (uint8_t)imr Value to set @ref IMR register. - * @sa getIMR() - */ -#define setIMR(imr) \ - WIZCHIP_WRITE(IMR, imr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IMR register - * @return uint8_t. Value of @ref IMR register. - * @sa setIMR() - */ -#define getIMR() \ - WIZCHIP_READ(IMR) - - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIR register - * @param (uint8_t)sir Value to set @ref SIR register. - * @sa getSIR() - */ -// dpgeorge: not yet implemented -#define setSIR(sir) ((void)sir) -#if 0 -#define setSIR(sir) \ - WIZCHIP_WRITE(SIR, sir) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIR register - * @return uint8_t. Value of @ref SIR register. - * @sa setSIR() - */ -// dpgeorge: not yet implemented -#define getSIR() (0) -#if 0 -#define getSIR() \ - WIZCHIP_READ(SIR) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIMR register - * @param (uint8_t)simr Value to set @ref SIMR register. - * @sa getSIMR() - */ -// dpgeorge: not yet implemented -#define setSIMR(simr) ((void)simr) -#if 0 -#define setSIMR(simr) \ - WIZCHIP_WRITE(SIMR, simr) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIMR register - * @return uint8_t. Value of @ref SIMR register. - * @sa setSIMR() - */ -// dpgeorge: not yet implemented -#define getSIMR() (0) -#if 0 -#define getSIMR() \ - WIZCHIP_READ(SIMR) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RTR register - * @param (uint16_t)rtr Value to set @ref RTR register. - * @sa getRTR() - */ -#define setRTR(rtr) {\ - WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ - WIZCHIP_WRITE(RTR + 1, (uint8_t) rtr); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RTR register - * @return uint16_t. Value of @ref RTR register. - * @sa setRTR() - */ -#define getRTR() \ - ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(RTR + 1)) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RCR register - * @param (uint8_t)rcr Value to set @ref RCR register. - * @sa getRCR() - */ -#define setRCR(rcr) \ - WIZCHIP_WRITE(RCR, rcr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RCR register - * @return uint8_t. Value of @ref RCR register. - * @sa setRCR() - */ -#define getRCR() \ - WIZCHIP_READ(RCR) - -//================================================== test done =========================================================== - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PTIMER register - * @param (uint8_t)ptimer Value to set @ref PTIMER register. - * @sa getPTIMER() - */ -#define setPTIMER(ptimer) \ - WIZCHIP_WRITE(PTIMER, ptimer) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PTIMER register - * @return uint8_t. Value of @ref PTIMER register. - * @sa setPTIMER() - */ -#define getPTIMER() \ - WIZCHIP_READ(PTIMER) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMAGIC register - * @param (uint8_t)pmagic Value to set @ref PMAGIC register. - * @sa getPMAGIC() - */ -#define setPMAGIC(pmagic) \ - WIZCHIP_WRITE(PMAGIC, pmagic) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMAGIC register - * @return uint8_t. Value of @ref PMAGIC register. - * @sa setPMAGIC() - */ -#define getPMAGIC() \ - WIZCHIP_READ(PMAGIC) - -/** - * @ingroup Common_register_access_function - * @brief Set PHAR address - * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. - * @sa getPHAR() - */ -#if 0 -#define setPHAR(phar) \ - WIZCHIP_WRITE_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. - * @sa setPHAR() - */ -#define getPHAR(phar) \ - WIZCHIP_READ_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PSID register - * @param (uint16_t)psid Value to set @ref PSID register. - * @sa getPSID() - */ -#define setPSID(psid) {\ - WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PSID register - * @return uint16_t. Value of @ref PSID register. - * @sa setPSID() - */ -//uint16_t getPSID(void); -#define getPSID() \ - ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMRU register - * @param (uint16_t)pmru Value to set @ref PMRU register. - * @sa getPMRU() - */ -#define setPMRU(pmru) { \ - WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMRU register - * @return uint16_t. Value of @ref PMRU register. - * @sa setPMRU() - */ -#define getPMRU() \ - ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) - -/** - * @ingroup Common_register_access_function - * @brief Get unreachable IP address - * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. - */ -#define getUIPR(uipr) \ - WIZCHIP_READ_BUF(UIPR,uipr,6) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref UPORTR register - * @return uint16_t. Value of @ref UPORTR register. - */ -#define getUPORTR() \ - ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHYCFGR register - * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. - * @sa getPHYCFGR() - */ -#define setPHYCFGR(phycfgr) \ - WIZCHIP_WRITE(PHYCFGR, phycfgr) -#endif - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHYCFGR register - * @return uint8_t. Value of @ref PHYCFGR register. - * @sa setPHYCFGR() - */ -#define getPHYSTATUS() \ - WIZCHIP_READ(PHYSTATUS) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref VERSIONR register - * @return uint8_t. Value of @ref VERSIONR register. - */ -/* -#define getVERSIONR() \ - WIZCHIP_READ(VERSIONR) - */ -///////////////////////////////////// - -/////////////////////////////////// -// Socket N register I/O function // -/////////////////////////////////// -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)mr Value to set @ref Sn_MR - * @sa getSn_MR() - */ -#define setSn_MR(sn, mr) \ - WIZCHIP_WRITE(Sn_MR(sn),mr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_MR. - * @sa setSn_MR() - */ -#define getSn_MR(sn) \ - WIZCHIP_READ(Sn_MR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)cr Value to set @ref Sn_CR - * @sa getSn_CR() - */ -#define setSn_CR(sn, cr) \ - WIZCHIP_WRITE(Sn_CR(sn), cr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_CR. - * @sa setSn_CR() - */ -#define getSn_CR(sn) \ - WIZCHIP_READ(Sn_CR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ir Value to set @ref Sn_IR - * @sa getSn_IR() - */ -#define setSn_IR(sn, ir) \ - WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IR. - * @sa setSn_IR() - */ -#define getSn_IR(sn) \ - (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)imr Value to set @ref Sn_IMR - * @sa getSn_IMR() - */ -// dpgeorge: not yet implemented -#define setSn_IMR(sn, imr) (void)sn; (void)imr -#if 0 -#define setSn_IMR(sn, imr) \ - WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) -#endif - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IMR. - * @sa setSn_IMR() - */ -// dpgeorge: not yet implemented -#define getSn_IMR(sn) (0) -#if 0 -#define getSn_IMR(sn) \ - (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) -#endif - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_SR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_SR. - */ -#define getSn_SR(sn) \ - WIZCHIP_READ(Sn_SR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)port Value to set @ref Sn_PORT. - * @sa getSn_PORT() - */ -#define setSn_PORT(sn, port) { \ - WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ - WIZCHIP_WRITE(Sn_PORT(sn) + 1, (uint8_t) port); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_PORT. - * @sa setSn_PORT() - */ -#define getSn_PORT(sn) \ - ((WIZCHIP_READ(Sn_PORT(sn)) << 8) | WIZCHIP_READ(Sn_PORT(sn) + 1)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DHAR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. - * @sa getSn_DHAR() - */ -#define setSn_DHAR(sn, dhar) \ - WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. - * @sa setSn_DHAR() - */ -#define getSn_DHAR(sn, dhar) \ - WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. - * @sa getSn_DIPR() - */ -#define setSn_DIPR(sn, dipr) \ - WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. - * @sa SetSn_DIPR() - */ -#define getSn_DIPR(sn, dipr) \ - WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)dport Value to set @ref Sn_DPORT - * @sa getSn_DPORT() - */ -#define setSn_DPORT(sn, dport) { \ - WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ - WIZCHIP_WRITE(Sn_DPORT(sn) + 1, (uint8_t) dport); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_DPORT. - * @sa setSn_DPORT() - */ -#define getSn_DPORT(sn) \ - ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ((Sn_DPORT(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)mss Value to set @ref Sn_MSSR - * @sa setSn_MSSR() - */ -#define setSn_MSSR(sn, mss) { \ - WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ - WIZCHIP_WRITE((Sn_MSSR(sn)+1), (uint8_t) mss); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_MSSR. - * @sa setSn_MSSR() - */ -#define getSn_MSSR(sn) \ - ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ((Sn_MSSR(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)tos Value to set @ref Sn_TOS - * @sa getSn_TOS() - */ -#define setSn_TOS(sn, tos) \ - WIZCHIP_WRITE(Sn_TOS(sn), tos) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of Sn_TOS. - * @sa setSn_TOS() - */ -#define getSn_TOS(sn) \ - WIZCHIP_READ(Sn_TOS(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ttl Value to set @ref Sn_TTL - * @sa getSn_TTL() - */ -#define setSn_TTL(sn, ttl) \ - WIZCHIP_WRITE(Sn_TTL(sn), ttl) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TTL. - * @sa setSn_TTL() - */ -#define getSn_TTL(sn) \ - WIZCHIP_READ(Sn_TTL(sn)) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE - * @sa getSn_RXBUF_SIZE() - */ -#define setSn_RXBUF_SIZE(sn, rxbufsize) \ - WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. - * @sa setSn_RXBUF_SIZE() - */ -#define getSn_RXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE - * @sa getSn_TXBUF_SIZE() - */ -#define setSn_TXBUF_SIZE(sn, txbufsize) \ - WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. - * @sa setSn_TXBUF_SIZE() - */ -#define getSn_TXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_FSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_FSR. - */ -uint16_t getSn_TX_FSR(uint8_t sn); - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_RD. - */ -#define getSn_TX_RD(sn) \ - ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ((Sn_TX_RD(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)txwr Value to set @ref Sn_TX_WR - * @sa GetSn_TX_WR() - */ -#define setSn_TX_WR(sn, txwr) { \ - WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ - WIZCHIP_WRITE((Sn_TX_WR(sn)+1), (uint8_t) txwr); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_WR. - * @sa setSn_TX_WR() - */ -#define getSn_TX_WR(sn) \ - ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ((Sn_TX_WR(sn)+1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_RSR. - */ -uint16_t getSn_RX_RSR(uint8_t sn); - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD - * @sa getSn_RX_RD() - */ -#define setSn_RX_RD(sn, rxrd) { \ - WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ - WIZCHIP_WRITE((Sn_RX_RD(sn)+1), (uint8_t) rxrd); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @regurn uint16_t. Value of @ref Sn_RX_RD. - * @sa setSn_RX_RD() - */ -#define getSn_RX_RD(sn) \ - ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ((Sn_RX_RD(sn)+1))) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_WR. - */ -#define getSn_RX_WR(sn) \ - ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ((Sn_RX_WR(sn)+1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)frag Value to set @ref Sn_FRAG - * @sa getSn_FRAD() - */ -#if 0 // dpgeorge -#define setSn_FRAG(sn, frag) { \ - WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_FRAG. - * @sa setSn_FRAG() - */ -#define getSn_FRAG(sn) \ - ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR - * @sa getSn_KPALVTR() - */ -#define setSn_KPALVTR(sn, kpalvt) \ - WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_KPALVTR. - * @sa setSn_KPALVTR() - */ -#define getSn_KPALVTR(sn) \ - WIZCHIP_READ(Sn_KPALVTR(sn)) - -////////////////////////////////////// -#endif - -///////////////////////////////////// -// Sn_TXBUF & Sn_RXBUF IO function // -///////////////////////////////////// -/** - * @brief Gets the max buffer size of socket sn passed as parameter. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n RX max buffer size. - */ -#define getSn_RxMAX(sn) \ - (getSn_RXBUF_SIZE(sn) << 10) - -/** - * @brief Gets the max buffer size of socket sn passed as parameters. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n TX max buffer size. - */ -//uint16_t getSn_TxMAX(uint8_t sn); -#define getSn_TxMAX(sn) \ - (getSn_TXBUF_SIZE(sn) << 10) - -void wiz_init(void); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to internal TX memory - * - * @details This function reads the Tx write pointer register and after that, - * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory - * and updates the Tx write pointer register. - * This function is being called by send() and sendto() function also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to write data - * @param len Data length - * @sa wiz_recv_data() - */ -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to your buffer from internal RX memory - * - * @details This function read the Rx read pointer register and after that, - * it copies the received data from internal RX memory - * to wizdata(pointer variable) of the length of len(variable) bytes. - * This function is being called by recv() also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to read data - * @param len Data length - * @sa wiz_send_data() - */ -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It discard the received data in RX memory. - * @details It discards the data of the length of len(variable) bytes in internal RX memory. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param len Data length - */ -void wiz_recv_ignore(uint8_t sn, uint16_t len); - -#endif // _W5500_H_ diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5500/w5500.c b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5500/w5500.c deleted file mode 100644 index 3107b1b7..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5500/w5500.c +++ /dev/null @@ -1,247 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.c -//! \brief W5500 HAL Interface. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.2 -//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 -//! Fixed the problem on porting into under 32bit MCU -//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh -//! Thank for your interesting and serious advices. -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.0.1 -//! 1. Remove warning -//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ -//! for loop optimized(removed). refer to M20131220 -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -//#include -#include "w5500.h" - -#define _W5500_SPI_VDM_OP_ 0x00 -#define _W5500_SPI_FDM_OP_LEN1_ 0x01 -#define _W5500_SPI_FDM_OP_LEN2_ 0x02 -#define _W5500_SPI_FDM_OP_LEN4_ 0x03 - -//////////////////////////////////////////////////// - -#define LPC_SSP0 (0) - -static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) { - WIZCHIP.IF.SPI._read_bytes(buf, len); -} - -static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) { - WIZCHIP.IF.SPI._write_bytes(buf, len); -} - -uint8_t WIZCHIP_READ(uint32_t AddrSel) -{ - uint8_t ret; - uint8_t spi_data[3]; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //ret = WIZCHIP.IF.SPI._read_byte(); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); - return ret; -} - -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) -{ - uint8_t spi_data[4]; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //WIZCHIP.IF.SPI._write_byte(wb); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - spi_data[3] = wb; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) -{ - uint8_t spi_data[3]; - //uint16_t i; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //for(i = 0; i < len; i++) - // pBuf[i] = WIZCHIP.IF.SPI._read_byte(); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) -{ - uint8_t spi_data[3]; - //uint16_t i; - - WIZCHIP_CRITICAL_ENTER(); - WIZCHIP.CS._select(); - - AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); - - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); - //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); - //for(i = 0; i < len; i++) - // WIZCHIP.IF.SPI._write_byte(pBuf[i]); - spi_data[0] = (AddrSel & 0x00FF0000) >> 16; - spi_data[1] = (AddrSel & 0x0000FF00) >> 8; - spi_data[2] = (AddrSel & 0x000000FF) >> 0; - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); - Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len); - - WIZCHIP.CS._deselect(); - WIZCHIP_CRITICAL_EXIT(); -} - - -uint16_t getSn_TX_FSR(uint8_t sn) -{ - uint16_t val=0,val1=0; - - do - { - val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_TX_FSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); - } - }while (val != val1); - return val; -} - - -uint16_t getSn_RX_RSR(uint8_t sn) -{ - uint16_t val=0,val1=0; - - do - { - val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); - val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - if (val1 != 0) - { - val = WIZCHIP_READ(Sn_RX_RSR(sn)); - val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); - } - }while (val != val1); - return val; -} - -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) -{ - uint16_t ptr = 0; - uint32_t addrsel = 0; - - if(len == 0) return; - ptr = getSn_TX_WR(sn); - //M20140501 : implict type casting -> explict type casting - //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); - addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); - // - WIZCHIP_WRITE_BUF(addrsel,wizdata, len); - - ptr += len; - setSn_TX_WR(sn,ptr); -} - -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) -{ - uint16_t ptr = 0; - uint32_t addrsel = 0; - - if(len == 0) return; - ptr = getSn_RX_RD(sn); - //M20140501 : implict type casting -> explict type casting - //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); - addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); - // - WIZCHIP_READ_BUF(addrsel, wizdata, len); - ptr += len; - - setSn_RX_RD(sn,ptr); -} - - -void wiz_recv_ignore(uint8_t sn, uint16_t len) -{ - uint16_t ptr = 0; - - ptr = getSn_RX_RD(sn); - ptr += len; - setSn_RX_RD(sn,ptr); -} - diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5500/w5500.h b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5500/w5500.h deleted file mode 100644 index c2afb180..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/w5500/w5500.h +++ /dev/null @@ -1,2057 +0,0 @@ -//***************************************************************************** -// -//! \file w5500.h -//! \brief W5500 HAL Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _W5500_H_ -#define _W5500_H_ - -#include -#include "../wizchip_conf.h" - -#define _W5500_IO_BASE_ 0x00000000 - -#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase -#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase - -#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block -#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block -#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block -#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block - -#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address - - -/////////////////////////////////////// -// Definition For Legacy Chip Driver // -/////////////////////////////////////// -#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver -#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver -#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver -#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver - -////////////////////////////// -//-------------------------- defgroup --------------------------------- -/** - * @defgroup W5500 W5500 - * - * @brief WHIZCHIP register defines and I/O functions of @b W5500. - * - * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group - * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function - */ - - -/** - * @defgroup WIZCHIP_register WIZCHIP register - * @ingroup W5500 - * - * @brief WHIZCHIP register defines register group of @b W5500. - * - * - @ref Common_register_group : Common register group - * - @ref Socket_register_group : \c SOCKET n register group - */ - - -/** - * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions - * @ingroup W5500 - * - * @brief This supports the basic I/O functions for @ref WIZCHIP_register. - * - * - Basic I/O function \n - * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n - * - * - @ref Common_register_group access functions \n - * -# @b Mode \n - * getMR(), setMR() - * -# @b Interrupt \n - * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() - * -# Network Information \n - * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() - * -# @b Retransmission \n - * getRCR(), setRCR(), getRTR(), setRTR() - * -# @b PPPoE \n - * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() - * -# ICMP packet \n - * getUIPR(), getUPORTR() - * -# @b etc. \n - * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n - * - * - \ref Socket_register_group access functions \n - * -# SOCKET control \n - * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() - * -# SOCKET information \n - * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() - * getSn_MSSR(), setSn_MSSR() - * -# SOCKET communication \n - * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n - * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n - * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n - * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() - * -# IP header field \n - * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n - * getSn_TTL(), setSn_TTL() - */ - - - -/** - * @defgroup Common_register_group Common register - * @ingroup WIZCHIP_register - * - * @brief Common register group\n - * It set the basic for the networking\n - * It set the configuration such as interrupt, network information, ICMP, etc. - * @details - * @sa MR : Mode register. - * @sa GAR, SUBR, SHAR, SIPR - * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. - * @sa RTR, RCR : Data retransmission. - * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. - * @sa UIPR, UPORTR : ICMP message. - * @sa PHYCFGR, VERSIONR : etc. - */ - - - -/** - * @defgroup Socket_register_group Socket register - * @ingroup WIZCHIP_register - * - * @brief Socket register group.\n - * Socket register configures and control SOCKETn which is necessary to data communication. - * @details - * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control - * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information - * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. - * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication - */ - - - - /** - * @defgroup Basic_IO_function Basic I/O function - * @ingroup WIZCHIP_IO_Functions - * @brief These are basic input/output functions to read values from register or write values to register. - */ - -/** - * @defgroup Common_register_access_function Common register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access common registers. - */ - -/** - * @defgroup Socket_register_access_function Socket register access functions - * @ingroup WIZCHIP_IO_Functions - * @brief These are functions to access socket registers. - */ - -//------------------------------- defgroup end -------------------------------------------- -//----------------------------- W5500 Common Registers IOMAP ----------------------------- -/** - * @ingroup Common_register_group - * @brief Mode Register address(R/W)\n - * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. - * @details Each bit of @ref MR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
RST Reserved WOL PB PPPoE Reserved FARP Reserved
- * - \ref MR_RST : Reset - * - \ref MR_WOL : Wake on LAN - * - \ref MR_PB : Ping block - * - \ref MR_PPPOE : PPPoE mode - * - \ref MR_FARP : Force ARP mode - */ -#define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Gateway IP Register address(R/W) - * @details @ref GAR configures the default gateway address. - */ -#define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Subnet mask Register address(R/W) - * @details @ref SUBR configures the subnet mask address. - */ -#define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Source MAC Register address(R/W) - * @details @ref SHAR configures the source hardware address. - */ -#define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Source IP Register address(R/W) - * @details @ref SIPR configures the source IP address. - */ -#define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Set Interrupt low level timer register address(R/W) - * @details @ref INTLEVEL configures the Interrupt Assert Time. - */ -#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt Register(R/W) - * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. - * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n - * Each bit of @ref IR defined as follows. - * - * - * - *
7 6 5 4 3 2 1 0
CONFLICT UNREACH PPPoE MP Reserved Reserved Reserved Reserved
- * - \ref IR_CONFLICT : IP conflict - * - \ref IR_UNREACH : Destination unreachable - * - \ref IR_PPPoE : PPPoE connection close - * - \ref IR_MP : Magic packet - */ -#define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Interrupt mask register(R/W) - * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. - * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, - * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n - * Each bit of @ref IMR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
IM_IR7 IM_IR6 IM_IR5 IM_IR4 Reserved Reserved Reserved Reserved
- * - \ref IM_IR7 : IP Conflict Interrupt Mask - * - \ref IM_IR6 : Destination unreachable Interrupt Mask - * - \ref IM_IR5 : PPPoE Close Interrupt Mask - * - \ref IM_IR4 : Magic Packet Interrupt Mask - */ -#define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Register(R/W) - * @details @ref SIR indicates the interrupt status of Socket.\n - * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n - * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ -#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Socket Interrupt Mask Register(R/W) - * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. - * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. - * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is - */ -#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Timeout register address( 1 is 100us )(R/W) - * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 - * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response - * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). - * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. - */ -#define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Retry count register(R/W) - * @details @ref RCR configures the number of time of retransmission. - * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . - */ -#define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Request Timer register in PPPoE mode(R/W) - * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. - */ -#define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP LCP Magic number register in PPPoE mode(R/W) - * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. - */ -#define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Destination MAC Register address(R/W) - * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. - */ -#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Session Identification Register(R/W) - * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. - */ -#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PPP Maximum Segment Size(MSS) register(R/W) - * @details @ref PMRU configures the maximum receive unit of PPPoE. - */ -#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable IP register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates - * the destination IP address & port number respectively. - */ -#define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief Unreachable Port register address in UDP mode(R) - * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number - * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR - * indicates the destination IP address & port number respectively. - */ -#define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief PHY Status Register(R/W) - * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. - */ -#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - -/** - * @ingroup Common_register_group - * @brief chip version register address(R) - * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. - */ -#define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) - - -//----------------------------- W5500 Socket Registers IOMAP ----------------------------- -/** - * @ingroup Socket_register_group - * @brief socket Mode register(R/W) - * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n - * Each bit of @ref Sn_MR defined as the following. - * - * - * - *
7 6 5 4 3 2 1 0
MULTI/MFEN BCASTB ND/MC/MMB UCASTB/MIP6B Protocol[3] Protocol[2] Protocol[1] Protocol[0]
- * - @ref Sn_MR_MULTI : Support UDP Multicasting - * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting - * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag - * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting - * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode - * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating - * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * - Protocol - * - * - * - * - * - * - *
Protocol[3] Protocol[2] Protocol[1] Protocol[0] @b Meaning
0 0 0 0 Closed
0 0 0 1 TCP
0 0 1 0 UDP
0 1 0 0 MACRAW
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n - * - @ref Sn_MR_UDP : UDP - * - @ref Sn_MR_TCP : TCP - * - @ref Sn_MR_CLOSE : Unused socket - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket command register(R/W) - * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n - * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. - * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n - * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. - * - @ref Sn_CR_OPEN : Initialize or open socket. - * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode) - * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode) - * - @ref Sn_CR_DISCON : Send closing request in TCP mode. - * - @ref Sn_CR_CLOSE : Close socket. - * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. - * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. - * - @ref Sn_CR_SEND_KEEP : Send keep alive message. - * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. - */ -#define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket interrupt register(R) - * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n - * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n - * In order to clear the @ref Sn_IR bit, the host should write the bit to \n - * - * - * - *
7 6 5 4 3 2 1 0
Reserved Reserved Reserved SEND_OK TIMEOUT RECV DISCON CON
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt - * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt - * - \ref Sn_IR_RECV : RECV Interrupt - * - \ref Sn_IR_DISCON : DISCON Interrupt - * - \ref Sn_IR_CON : CON Interrupt - */ -#define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Socket status register(R) - * @details @ref Sn_SR indicates the status of Socket n.\n - * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. - * @par Normal status - * - @ref SOCK_CLOSED : Closed - * - @ref SOCK_INIT : Initiate state - * - @ref SOCK_LISTEN : Listen state - * - @ref SOCK_ESTABLISHED : Success to connect - * - @ref SOCK_CLOSE_WAIT : Closing state - * - @ref SOCK_UDP : UDP socket - * - @ref SOCK_MACRAW : MAC raw mode socket - *@par Temporary status during changing the status of Socket n. - * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. - * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. - * - @ref SOCK_FIN_WAIT : Connection state - * - @ref SOCK_CLOSING : Closing state - * - @ref SOCK_TIME_WAIT : Closing state - * - @ref SOCK_LAST_ACK : Closing state - */ -#define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief source port register(R/W) - * @details @ref Sn_PORT configures the source port number of Socket n. - * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. - */ -#define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer MAC register address(R/W) - * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or - * it indicates that it is acquired in ARP-process by CONNECT/SEND command. - */ -#define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer IP register address(R/W) - * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. - * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. - * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. - */ -#define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Peer port register address(R/W) - * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. - * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. - * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. - * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. - */ -#define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) - * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. - */ -#define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief IP Type of Service(TOS) Register(R/W) - * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -/** - * @ingroup Socket_register_group - * @brief IP Time to live(TTL) Register(R/W) - * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. - * It is set before OPEN command. - */ -#define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) -// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Receive memory size register(R/W) - * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. - * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data cannot be normally received from a peer. - * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, - * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data reception error is occurred. - */ -#define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory size register(R/W) - * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. - * If a different size is configured, the data can�t be normally transmitted to a peer. - * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, - * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. - * When exceeded, the data transmission error is occurred. - */ -#define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit free memory size register(R) - * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. - * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. - * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, - * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, - * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. - */ -#define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory read pointer register address(R) - * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. - * After its initialization, it is auto-increased by SEND command. - * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. - * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. - * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Transmit memory write pointer register address(R/W) - * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n - * It should be read or be updated like as follows.\n - * 1. Read the starting address for saving the transmitting data.\n - * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n - * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. - * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value.\n - * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command - */ -#define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Received data size register(R) - * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. - * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between - * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) - */ -#define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Read point of Receive memory(R/W) - * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n - * 1. Read the starting save address of the received data.\n - * 2. Read data from the starting address of Socket n RX Buffer.\n - * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. - * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, - * update with the lower 16bits value ignored the carry bit.\n - * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. - */ -#define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Write point of Receive memory(R) - * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. - * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), - * then the carry bit is ignored and will automatically update with the lower 16bits value. - */ -#define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief socket interrupt mask register(R) - * @details @ref Sn_IMR masks the interrupt of Socket n. - * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is - * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is - * Host is interrupted by asserted INTn PIN to low. - */ -#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Fragment field value in IP header register(R/W) - * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). - */ -#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -/** - * @ingroup Socket_register_group - * @brief Keep Alive Timer register(R/W) - * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, - * and ignored in other modes. The time unit is 5s. - * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. - * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). - * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, - * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). - * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. - */ -#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - -//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) - - -//----------------------------- W5500 Register values ----------------------------- - -/* MODE register values */ -/** - * @brief Reset - * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. - */ -#define MR_RST 0x80 - -/** - * @brief Wake on LAN - * @details 0 : Disable WOL mode\n - * 1 : Enable WOL mode\n - * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. - * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) - * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and - * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. - */ -#define MR_WOL 0x20 - -/** - * @brief Ping block - * @details 0 : Disable Ping block\n - * 1 : Enable Ping block\n - * If the bit is it blocks the response to a ping request. - */ -#define MR_PB 0x10 - -/** - * @brief Enable PPPoE - * @details 0 : DisablePPPoE mode\n - * 1 : EnablePPPoE mode\n - * If you use ADSL, this bit should be - */ -#define MR_PPPOE 0x08 - -/** - * @brief Enable UDP_FORCE_ARP CHECHK - * @details 0 : Disable Force ARP mode\n - * 1 : Enable Force ARP mode\n - * In Force ARP mode, It forces on sending ARP Request whenever data is sent. - */ -#define MR_FARP 0x02 - -/* IR register values */ -/** - * @brief Check IP conflict. - * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. - */ -#define IR_CONFLICT 0x80 - -/** - * @brief Get the destination unreachable message in UDP sending. - * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as - * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. - */ -#define IR_UNREACH 0x40 - -/** - * @brief Get the PPPoE close message. - * @details When PPPoE is disconnected during PPPoE mode, this bit is set. - */ -#define IR_PPPoE 0x20 - -/** - * @brief Get the magic packet interrupt. - * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. - */ -#define IR_MP 0x10 - - -/* PHYCFGR register value */ -#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. -#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value -#define PHYCFGR_OPMDC_ALLA (7<<3) -#define PHYCFGR_OPMDC_PDOWN (6<<3) -#define PHYCFGR_OPMDC_NA (5<<3) -#define PHYCFGR_OPMDC_100FA (4<<3) -#define PHYCFGR_OPMDC_100F (3<<3) -#define PHYCFGR_OPMDC_100H (2<<3) -#define PHYCFGR_OPMDC_10F (1<<3) -#define PHYCFGR_OPMDC_10H (0<<3) -#define PHYCFGR_DPX_FULL (1<<2) -#define PHYCFGR_DPX_HALF (0<<2) -#define PHYCFGR_SPD_100 (1<<1) -#define PHYCFGR_SPD_10 (0<<1) -#define PHYCFGR_LNK_ON (1<<0) -#define PHYCFGR_LNK_OFF (0<<0) - -/* IMR register values */ -/** - * @brief IP Conflict Interrupt Mask. - * @details 0: Disable IP Conflict Interrupt\n - * 1: Enable IP Conflict Interrupt - */ -#define IM_IR7 0x80 - -/** - * @brief Destination unreachable Interrupt Mask. - * @details 0: Disable Destination unreachable Interrupt\n - * 1: Enable Destination unreachable Interrupt - */ -#define IM_IR6 0x40 - -/** - * @brief PPPoE Close Interrupt Mask. - * @details 0: Disable PPPoE Close Interrupt\n - * 1: Enable PPPoE Close Interrupt - */ -#define IM_IR5 0x20 - -/** - * @brief Magic Packet Interrupt Mask. - * @details 0: Disable Magic Packet Interrupt\n - * 1: Enable Magic Packet Interrupt - */ -#define IM_IR4 0x10 - -/* Sn_MR Default values */ -/** - * @brief Support UDP Multicasting - * @details 0 : disable Multicasting\n - * 1 : enable Multicasting\n - * This bit is applied only during UDP mode(P[3:0] = 010.\n - * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number - * before Socket n is opened by OPEN command of @ref Sn_CR. - */ -#define Sn_MR_MULTI 0x80 - -/** - * @brief Broadcast block in UDP Multicasting. - * @details 0 : disable Broadcast Blocking\n - * 1 : enable Broadcast Blocking\n - * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m - * In addition, This bit does when MACRAW mode(P[3:0] = 100 - */ -#define Sn_MR_BCASTB 0x40 - -/** - * @brief No Delayed Ack(TCP), Multicast flag - * @details 0 : Disable No Delayed ACK option\n - * 1 : Enable No Delayed ACK option\n - * This bit is applied only during TCP mode (P[3:0] = 001.\n - * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n - * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. - */ -#define Sn_MR_ND 0x20 - -/** - * @brief Unicast Block in UDP Multicasting - * @details 0 : disable Unicast Blocking\n - * 1 : enable Unicast Blocking\n - * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = - */ -#define Sn_MR_UCASTB 0x10 - -/** - * @brief MAC LAYER RAW SOCK - * @details This configures the protocol mode of Socket n. - * @note MACRAW mode should be only used in Socket 0. - */ -#define Sn_MR_MACRAW 0x04 - -//#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ - -/** - * @brief UDP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_UDP 0x02 - -/** - * @brief TCP - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_TCP 0x01 - -/** - * @brief Unused socket - * @details This configures the protocol mode of Socket n. - */ -#define Sn_MR_CLOSE 0x00 - -/* Sn_MR values used with Sn_MR_MACRAW */ -/** - * @brief MAC filter enable in @ref Sn_MR_MACRAW mode - * @details 0 : disable MAC Filtering\n - * 1 : enable MAC Filtering\n - * This bit is applied only during MACRAW mode(P[3:0] = 100.\n - * When set as W5500 can only receive broadcasting packet or packet sent to itself. - * When this bit is W5500 can receive all packets on Ethernet. - * If user wants to implement Hybrid TCP/IP stack, - * it is recommended that this bit is set as for reducing host overhead to process the all received packets. - */ -#define Sn_MR_MFEN Sn_MR_MULTI - -/** - * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : using IGMP version 2\n - * 1 : using IGMP version 1\n - * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = - * It configures the version for IGMP messages (Join/Leave/Report). - */ -#define Sn_MR_MMB Sn_MR_ND - -/** - * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode - * @details 0 : disable IPv6 Blocking\n - * 1 : enable IPv6 Blocking\n - * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. - */ -#define Sn_MR_MIP6B Sn_MR_UCASTB - -/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ -/** - * @brief IGMP version used in UDP mulitcasting - * @details 0 : disable Multicast Blocking\n - * 1 : enable Multicast Blocking\n - * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. - */ -#define Sn_MR_MC Sn_MR_ND - -/* Sn_MR alternate values */ -/** - * @brief For Berkeley Socket API - */ -#define SOCK_STREAM Sn_MR_TCP - -/** - * @brief For Berkeley Socket API - */ -#define SOCK_DGRAM Sn_MR_UDP - - -/* Sn_CR values */ -/** - * @brief Initialize or open socket - * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). - * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n - * - * - * - * - * - * - *
\b Sn_MR (P[3:0]) \b Sn_SR
Sn_MR_CLOSE (000
Sn_MR_TCP (001 SOCK_INIT (0x13)
Sn_MR_UDP (010 SOCK_UDP (0x22)
S0_MR_MACRAW (100 SOCK_MACRAW (0x02)
- */ -#define Sn_CR_OPEN 0x01 - -/** - * @brief Wait connection request in TCP mode(Server mode) - * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). - * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client - * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. - * When a �TCP clientconnection request is successfully established, - * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes - * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. - */ -#define Sn_CR_LISTEN 0x02 - -/** - * @brief Send connection request in TCP mode(Client mode) - * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port). - * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n - * The connect-request fails in the following three cases.\n - * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n - * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n - * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client - */ -#define Sn_CR_CONNECT 0x04 - -/** - * @brief Send closing request in TCP mode - * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n - * @par Active close - * it transmits disconnect-request(FIN packet) to the connected peer\n - * @par Passive close - * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n - * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n - * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. - * @note Valid only in TCP mode. - */ -#define Sn_CR_DISCON 0x08 - -/** - * @brief Close socket - * @details Sn_SR is changed to @ref SOCK_CLOSED. - */ -#define Sn_CR_CLOSE 0x10 - -/** - * @brief Update TX buffer pointer and send data - * @details SEND transmits all the data in the Socket n TX buffer.\n - * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, - * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). - */ -#define Sn_CR_SEND 0x20 - -/** - * @brief Send data with MAC address, so without ARP process - * @details The basic operation is same as SEND.\n - * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n - * But SEND_MAC transmits data without the automatic ARP-process.\n - * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. - * @note Valid only in UDP mode. - */ -#define Sn_CR_SEND_MAC 0x21 - -/** - * @brief Send keep alive message - * @details It checks the connection status by sending 1byte keep-alive packet.\n - * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. - * @note Valid only in TCP mode. - */ -#define Sn_CR_SEND_KEEP 0x22 - -/** - * @brief Update RX buffer pointer and receive data - * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n - * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), - * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). - */ -#define Sn_CR_RECV 0x40 - -/* Sn_IR values */ -/** - * @brief SEND_OK Interrupt - * @details This is issued when SEND command is completed. - */ -#define Sn_IR_SENDOK 0x10 - -/** - * @brief TIMEOUT Interrupt - * @details This is issued when ARPTO or TCPTO occurs. - */ -#define Sn_IR_TIMEOUT 0x08 - -/** - * @brief RECV Interrupt - * @details This is issued whenever data is received from a peer. - */ -#define Sn_IR_RECV 0x04 - -/** - * @brief DISCON Interrupt - * @details This is issued when FIN or FIN/ACK packet is received from a peer. - */ -#define Sn_IR_DISCON 0x02 - -/** - * @brief CON Interrupt - * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. - */ -#define Sn_IR_CON 0x01 - -/* Sn_SR values */ -/** - * @brief Closed - * @details This indicates that Socket n is released.\N - * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. - */ -#define SOCK_CLOSED 0x00 - -/** - * @brief Initiate state - * @details This indicates Socket n is opened with TCP mode.\N - * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N - * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. - */ -#define SOCK_INIT 0x13 - -/** - * @brief Listen state - * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n - * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n - * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . - */ -#define SOCK_LISTEN 0x14 - -/** - * @brief Connection state - * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n - * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n - * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n - * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. - */ -#define SOCK_SYNSENT 0x15 - -/** - * @brief Connection state - * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n - * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n - * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_SYNRECV 0x16 - -/** - * @brief Success to connect - * @details This indicates the status of the connection of Socket n.\n - * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or - * when the CONNECT command is successful.\n - * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. - */ -#define SOCK_ESTABLISHED 0x17 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_FIN_WAIT 0x18 - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_CLOSING 0x1A - -/** - * @brief Closing state - * @details These indicate Socket n is closing.\n - * These are shown in disconnect-process such as active-close and passive-close.\n - * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. - */ -#define SOCK_TIME_WAIT 0x1B - -/** - * @brief Closing state - * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n - * This is half-closing status, and data can be transferred.\n - * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. - */ -#define SOCK_CLOSE_WAIT 0x1C - -/** - * @brief Closing state - * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n - * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . - */ -#define SOCK_LAST_ACK 0x1D - -/** - * @brief UDP socket - * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n - * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n - * Unlike TCP mode, data can be transfered without the connection-process. - */ -#define SOCK_UDP 0x22 - -//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ - -/** - * @brief MAC raw mode socket - * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n - * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n - * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. - */ -#define SOCK_MACRAW 0x42 - -//#define SOCK_PPPOE 0x5F - -/* IP PROTOCOL */ -#define IPPROTO_IP 0 //< Dummy for IP -#define IPPROTO_ICMP 1 //< Control message protocol -#define IPPROTO_IGMP 2 //< Internet group management protocol -#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) -#define IPPROTO_TCP 6 //< TCP -#define IPPROTO_PUP 12 //< PUP -#define IPPROTO_UDP 17 //< UDP -#define IPPROTO_IDP 22 //< XNS idp -#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol -#define IPPROTO_RAW 255 //< Raw IP packet - - -/** - * @brief Enter a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n \n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt.\n - * In OS environment, You can replace it to critical section api supported by OS. - * - * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * \sa WIZCHIP_CRITICAL_EXIT() - */ -#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() - -/** - * @brief Exit a critical section - * - * @details It is provided to protect your shared code which are executed without distribution. \n\n - * - * In non-OS environment, It can be just implemented by disabling whole interrupt. \n - * In OS environment, You can replace it to critical section api supported by OS. - * - * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() - * @sa WIZCHIP_CRITICAL_ENTER() - */ -#ifdef _exit -#undef _exit -#endif -#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() - - - -//////////////////////// -// Basic I/O Function // -//////////////////////// - -/** - * @ingroup Basic_IO_function - * @brief It reads 1 byte value from a register. - * @param AddrSel Register address - * @return The value of register - */ -uint8_t WIZCHIP_READ (uint32_t AddrSel); - -/** - * @ingroup Basic_IO_function - * @brief It writes 1 byte value to a register. - * @param AddrSel Register address - * @param wb Write data - * @return void - */ -void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); - -/** - * @ingroup Basic_IO_function - * @brief It reads sequence data from registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to read data - * @param len Data length - */ -void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It writes sequence data to registers. - * @param AddrSel Register address - * @param pBuf Pointer buffer to write data - * @param len Data length - */ -void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); - -///////////////////////////////// -// Common Register I/O function // -///////////////////////////////// -/** - * @ingroup Common_register_access_function - * @brief Set Mode Register - * @param (uint8_t)mr The value to be set. - * @sa getMR() - */ -#define setMR(mr) \ - WIZCHIP_WRITE(MR,mr) - - -/** - * @ingroup Common_register_access_function - * @brief Get Mode Register - * @return uint8_t. The value of Mode register. - * @sa setMR() - */ -#define getMR() \ - WIZCHIP_READ(MR) - -/** - * @ingroup Common_register_access_function - * @brief Set gateway IP address - * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. - * @sa getGAR() - */ -#define setGAR(gar) \ - WIZCHIP_WRITE_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Get gateway IP address - * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. - * @sa setGAR() - */ -#define getGAR(gar) \ - WIZCHIP_READ_BUF(GAR,gar,4) - -/** - * @ingroup Common_register_access_function - * @brief Set subnet mask address - * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. - * @sa getSUBR() - */ -#define setSUBR(subr) \ - WIZCHIP_WRITE_BUF(SUBR, subr,4) - - -/** - * @ingroup Common_register_access_function - * @brief Get subnet mask address - * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. - * @sa setSUBR() - */ -#define getSUBR(subr) \ - WIZCHIP_READ_BUF(SUBR, subr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set local MAC address - * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. - * @sa getSHAR() - */ -#define setSHAR(shar) \ - WIZCHIP_WRITE_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local MAC address - * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. - * @sa setSHAR() - */ -#define getSHAR(shar) \ - WIZCHIP_READ_BUF(SHAR, shar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set local IP address - * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. - * @sa getSIPR() - */ -#define setSIPR(sipr) \ - WIZCHIP_WRITE_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. - * @sa setSIPR() - */ -#define getSIPR(sipr) \ - WIZCHIP_READ_BUF(SIPR, sipr, 4) - -/** - * @ingroup Common_register_access_function - * @brief Set INTLEVEL register - * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. - * @sa getINTLEVEL() - */ -#define setINTLEVEL(intlevel) {\ - WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ - } - - -/** - * @ingroup Common_register_access_function - * @brief Get INTLEVEL register - * @return uint16_t. Value of @ref INTLEVEL register. - * @sa setINTLEVEL() - */ -#define getINTLEVEL() \ - ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref IR register - * @param (uint8_t)ir Value to set @ref IR register. - * @sa getIR() - */ -#define setIR(ir) \ - WIZCHIP_WRITE(IR, (ir & 0xF0)) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IR register - * @return uint8_t. Value of @ref IR register. - * @sa setIR() - */ -#define getIR() \ - (WIZCHIP_READ(IR) & 0xF0) -/** - * @ingroup Common_register_access_function - * @brief Set @ref IMR register - * @param (uint8_t)imr Value to set @ref IMR register. - * @sa getIMR() - */ -#define setIMR(imr) \ - WIZCHIP_WRITE(IMR, imr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref IMR register - * @return uint8_t. Value of @ref IMR register. - * @sa setIMR() - */ -#define getIMR() \ - WIZCHIP_READ(IMR) - - -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIR register - * @param (uint8_t)sir Value to set @ref SIR register. - * @sa getSIR() - */ -#define setSIR(sir) \ - WIZCHIP_WRITE(SIR, sir) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIR register - * @return uint8_t. Value of @ref SIR register. - * @sa setSIR() - */ -#define getSIR() \ - WIZCHIP_READ(SIR) -/** - * @ingroup Common_register_access_function - * @brief Set @ref SIMR register - * @param (uint8_t)simr Value to set @ref SIMR register. - * @sa getSIMR() - */ -#define setSIMR(simr) \ - WIZCHIP_WRITE(SIMR, simr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref SIMR register - * @return uint8_t. Value of @ref SIMR register. - * @sa setSIMR() - */ -#define getSIMR() \ - WIZCHIP_READ(SIMR) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RTR register - * @param (uint16_t)rtr Value to set @ref RTR register. - * @sa getRTR() - */ -#define setRTR(rtr) {\ - WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RTR,1), (uint8_t) rtr); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RTR register - * @return uint16_t. Value of @ref RTR register. - * @sa setRTR() - */ -#define getRTR() \ - ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(RTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref RCR register - * @param (uint8_t)rcr Value to set @ref RCR register. - * @sa getRCR() - */ -#define setRCR(rcr) \ - WIZCHIP_WRITE(RCR, rcr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref RCR register - * @return uint8_t. Value of @ref RCR register. - * @sa setRCR() - */ -#define getRCR() \ - WIZCHIP_READ(RCR) - -//================================================== test done =========================================================== - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PTIMER register - * @param (uint8_t)ptimer Value to set @ref PTIMER register. - * @sa getPTIMER() - */ -#define setPTIMER(ptimer) \ - WIZCHIP_WRITE(PTIMER, ptimer) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PTIMER register - * @return uint8_t. Value of @ref PTIMER register. - * @sa setPTIMER() - */ -#define getPTIMER() \ - WIZCHIP_READ(PTIMER) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMAGIC register - * @param (uint8_t)pmagic Value to set @ref PMAGIC register. - * @sa getPMAGIC() - */ -#define setPMAGIC(pmagic) \ - WIZCHIP_WRITE(PMAGIC, pmagic) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMAGIC register - * @return uint8_t. Value of @ref PMAGIC register. - * @sa setPMAGIC() - */ -#define getPMAGIC() \ - WIZCHIP_READ(PMAGIC) - -/** - * @ingroup Common_register_access_function - * @brief Set PHAR address - * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. - * @sa getPHAR() - */ -#define setPHAR(phar) \ - WIZCHIP_WRITE_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Get local IP address - * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. - * @sa setPHAR() - */ -#define getPHAR(phar) \ - WIZCHIP_READ_BUF(PHAR, phar, 6) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PSID register - * @param (uint16_t)psid Value to set @ref PSID register. - * @sa getPSID() - */ -#define setPSID(psid) {\ - WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PSID register - * @return uint16_t. Value of @ref PSID register. - * @sa setPSID() - */ -//uint16_t getPSID(void); -#define getPSID() \ - ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PMRU register - * @param (uint16_t)pmru Value to set @ref PMRU register. - * @sa getPMRU() - */ -#define setPMRU(pmru) { \ - WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ - } - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PMRU register - * @return uint16_t. Value of @ref PMRU register. - * @sa setPMRU() - */ -#define getPMRU() \ - ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) - -/** - * @ingroup Common_register_access_function - * @brief Get unreachable IP address - * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. - */ -#define getUIPR(uipr) \ - WIZCHIP_READ_BUF(UIPR,uipr,6) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref UPORTR register - * @return uint16_t. Value of @ref UPORTR register. - */ -#define getUPORTR() \ - ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) - -/** - * @ingroup Common_register_access_function - * @brief Set @ref PHYCFGR register - * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. - * @sa getPHYCFGR() - */ -#define setPHYCFGR(phycfgr) \ - WIZCHIP_WRITE(PHYCFGR, phycfgr) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref PHYCFGR register - * @return uint8_t. Value of @ref PHYCFGR register. - * @sa setPHYCFGR() - */ -#define getPHYCFGR() \ - WIZCHIP_READ(PHYCFGR) - -/** - * @ingroup Common_register_access_function - * @brief Get @ref VERSIONR register - * @return uint8_t. Value of @ref VERSIONR register. - */ -#define getVERSIONR() \ - WIZCHIP_READ(VERSIONR) - -///////////////////////////////////// - -/////////////////////////////////// -// Socket N register I/O function // -/////////////////////////////////// -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)mr Value to set @ref Sn_MR - * @sa getSn_MR() - */ -#define setSn_MR(sn, mr) \ - WIZCHIP_WRITE(Sn_MR(sn),mr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_MR. - * @sa setSn_MR() - */ -#define getSn_MR(sn) \ - WIZCHIP_READ(Sn_MR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)cr Value to set @ref Sn_CR - * @sa getSn_CR() - */ -#define setSn_CR(sn, cr) \ - WIZCHIP_WRITE(Sn_CR(sn), cr) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_CR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_CR. - * @sa setSn_CR() - */ -#define getSn_CR(sn) \ - WIZCHIP_READ(Sn_CR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ir Value to set @ref Sn_IR - * @sa getSn_IR() - */ -#define setSn_IR(sn, ir) \ - WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IR. - * @sa setSn_IR() - */ -#define getSn_IR(sn) \ - (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)imr Value to set @ref Sn_IMR - * @sa getSn_IMR() - */ -#define setSn_IMR(sn, imr) \ - WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_IMR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_IMR. - * @sa setSn_IMR() - */ -#define getSn_IMR(sn) \ - (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_SR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_SR. - */ -#define getSn_SR(sn) \ - WIZCHIP_READ(Sn_SR(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)port Value to set @ref Sn_PORT. - * @sa getSn_PORT() - */ -#define setSn_PORT(sn, port) { \ - WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_PORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_PORT. - * @sa setSn_PORT() - */ -#define getSn_PORT(sn) \ - ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DHAR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. - * @sa getSn_DHAR() - */ -#define setSn_DHAR(sn, dhar) \ - WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. - * @sa setSn_DHAR() - */ -#define getSn_DHAR(sn, dhar) \ - WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. - * @sa getSn_DIPR() - */ -#define setSn_DIPR(sn, dipr) \ - WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DIPR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. - * @sa SetSn_DIPR() - */ -#define getSn_DIPR(sn, dipr) \ - WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)dport Value to set @ref Sn_DPORT - * @sa getSn_DPORT() - */ -#define setSn_DPORT(sn, dport) { \ - WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_DPORT register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_DPORT. - * @sa setSn_DPORT() - */ -#define getSn_DPORT(sn) \ - ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)mss Value to set @ref Sn_MSSR - * @sa setSn_MSSR() - */ -#define setSn_MSSR(sn, mss) { \ - WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_MSSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_MSSR. - * @sa setSn_MSSR() - */ -#define getSn_MSSR(sn) \ - ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)tos Value to set @ref Sn_TOS - * @sa getSn_TOS() - */ -#define setSn_TOS(sn, tos) \ - WIZCHIP_WRITE(Sn_TOS(sn), tos) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TOS register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of Sn_TOS. - * @sa setSn_TOS() - */ -#define getSn_TOS(sn) \ - WIZCHIP_READ(Sn_TOS(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)ttl Value to set @ref Sn_TTL - * @sa getSn_TTL() - */ -#define setSn_TTL(sn, ttl) \ - WIZCHIP_WRITE(Sn_TTL(sn), ttl) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TTL register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TTL. - * @sa setSn_TTL() - */ -#define getSn_TTL(sn) \ - WIZCHIP_READ(Sn_TTL(sn)) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE - * @sa getSn_RXBUF_SIZE() - */ -#define setSn_RXBUF_SIZE(sn, rxbufsize) \ - WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. - * @sa setSn_RXBUF_SIZE() - */ -#define getSn_RXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE - * @sa getSn_TXBUF_SIZE() - */ -#define setSn_TXBUF_SIZE(sn, txbufsize) \ - WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TXBUF_SIZE register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. - * @sa setSn_TXBUF_SIZE() - */ -#define getSn_TXBUF_SIZE(sn) \ - WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_FSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_FSR. - */ -uint16_t getSn_TX_FSR(uint8_t sn); - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_RD. - */ -#define getSn_TX_RD(sn) \ - ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)txwr Value to set @ref Sn_TX_WR - * @sa GetSn_TX_WR() - */ -#define setSn_TX_WR(sn, txwr) { \ - WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_TX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_TX_WR. - * @sa setSn_TX_WR() - */ -#define getSn_TX_WR(sn) \ - ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RSR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_RSR. - */ -uint16_t getSn_RX_RSR(uint8_t sn); - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD - * @sa getSn_RX_RD() - */ -#define setSn_RX_RD(sn, rxrd) { \ - WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_RD register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @regurn uint16_t. Value of @ref Sn_RX_RD. - * @sa setSn_RX_RD() - */ -#define getSn_RX_RD(sn) \ - ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_RX_WR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_RX_WR. - */ -#define getSn_RX_WR(sn) \ - ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) - - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint16_t)frag Value to set @ref Sn_FRAG - * @sa getSn_FRAD() - */ -#define setSn_FRAG(sn, frag) { \ - WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ - WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ - } - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_FRAG register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of @ref Sn_FRAG. - * @sa setSn_FRAG() - */ -#define getSn_FRAG(sn) \ - ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) - -/** - * @ingroup Socket_register_access_function - * @brief Set @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR - * @sa getSn_KPALVTR() - */ -#define setSn_KPALVTR(sn, kpalvt) \ - WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) - -/** - * @ingroup Socket_register_access_function - * @brief Get @ref Sn_KPALVTR register - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint8_t. Value of @ref Sn_KPALVTR. - * @sa setSn_KPALVTR() - */ -#define getSn_KPALVTR(sn) \ - WIZCHIP_READ(Sn_KPALVTR(sn)) - -////////////////////////////////////// - -///////////////////////////////////// -// Sn_TXBUF & Sn_RXBUF IO function // -///////////////////////////////////// -/** - * @brief Gets the max buffer size of socket sn passed as parameter. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n RX max buffer size. - */ -#define getSn_RxMAX(sn) \ - (getSn_RXBUF_SIZE(sn) << 10) - -/** - * @brief Gets the max buffer size of socket sn passed as parameters. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @return uint16_t. Value of Socket n TX max buffer size. - */ -//uint16_t getSn_TxMAX(uint8_t sn); -#define getSn_TxMAX(sn) \ - (getSn_TXBUF_SIZE(sn) << 10) - -/** - * @ingroup Basic_IO_function - * @brief It copies data to internal TX memory - * - * @details This function reads the Tx write pointer register and after that, - * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory - * and updates the Tx write pointer register. - * This function is being called by send() and sendto() function also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to write data - * @param len Data length - * @sa wiz_recv_data() - */ -void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It copies data to your buffer from internal RX memory - * - * @details This function read the Rx read pointer register and after that, - * it copies the received data from internal RX memory - * to wizdata(pointer variable) of the length of len(variable) bytes. - * This function is being called by recv() also. - * - * @note User should read upper byte first and lower byte later to get proper value. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param wizdata Pointer buffer to read data - * @param len Data length - * @sa wiz_send_data() - */ -void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); - -/** - * @ingroup Basic_IO_function - * @brief It discard the received data in RX memory. - * @details It discards the data of the length of len(variable) bytes in internal RX memory. - * @param (uint8_t)sn Socket number. It should be 0 ~ 7. - * @param len Data length - */ -void wiz_recv_ignore(uint8_t sn, uint16_t len); - -#endif // _W5500_H_ diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/wizchip_conf.c b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/wizchip_conf.c deleted file mode 100644 index 3e54d2c9..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/wizchip_conf.c +++ /dev/null @@ -1,662 +0,0 @@ -//****************************************************************************/ -//! -//! \file wizchip_conf.c -//! \brief WIZCHIP Config Header File. -//! \version 1.0.1 -//! \date 2013/10/21 -//! \par Revision history -//! <2014/05/01> V1.0.1 Refer to M20140501 -//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte() -// Issued by Mathias ClauBen. -//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t* -//! For remove the warning when pointer type size is not 32bit. -//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type. -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//*****************************************************************************/ -//A20140501 : for use the type - ptrdiff_t -#include -// - -#include "wizchip_conf.h" -#include "socket.h" - -/** - * @brief Default function to enable interrupt. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cris_enter(void) {}; -/** - * @brief Default function to disable interrupt. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cris_exit(void) {}; -/** - * @brief Default function to select chip. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cs_select(void) {}; -/** - * @brief Default function to deselect chip. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_cs_deselect(void) {}; -/** - * @brief Default function to read in direct or indirect interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ - //M20140501 : Explict pointer type casting -//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); }; -uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); }; -/** - * @brief Default function to write in direct or indirect interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ - -//M20140501 : Explict pointer type casting -//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; }; -void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; }; - -/** - * @brief Default function to read in SPI interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {} -/** - * @brief Default function to write in SPI interface. - * @note This function help not to access wrong address. If you do not describe this function or register any functions, - * null function is called. - */ -void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {} - -/** - * @\ref _WIZCHIP instance - */ -_WIZCHIP WIZCHIP = - { - .id = _WIZCHIP_ID_, - .if_mode = _WIZCHIP_IO_MODE_, - .CRIS._enter = wizchip_cris_enter, - .CRIS._exit = wizchip_cris_exit, - .CS._select = wizchip_cs_select, - .CS._deselect = wizchip_cs_deselect, - .IF.BUS._read_byte = wizchip_bus_readbyte, - .IF.BUS._write_byte = wizchip_bus_writebyte -// .IF.SPI._read_byte = wizchip_spi_readbyte, -// .IF.SPI._write_byte = wizchip_spi_writebyte - }; - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -static uint8_t _SUBN_[4]; // subnet -#endif -static uint8_t _DNS_[4]; // DNS server ip address -static dhcp_mode _DHCP_; // DHCP mode - -void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) -{ - if(!cris_en || !cris_ex) - { - WIZCHIP.CRIS._enter = wizchip_cris_enter; - WIZCHIP.CRIS._exit = wizchip_cris_exit; - } - else - { - WIZCHIP.CRIS._enter = cris_en; - WIZCHIP.CRIS._exit = cris_ex; - } -} - -void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) -{ - if(!cs_sel || !cs_desel) - { - WIZCHIP.CS._select = wizchip_cs_select; - WIZCHIP.CS._deselect = wizchip_cs_deselect; - } - else - { - WIZCHIP.CS._select = cs_sel; - WIZCHIP.CS._deselect = cs_desel; - } -} - -void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)) -{ - while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_)); - - if(!bus_rb || !bus_wb) - { - WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte; - WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte; - } - else - { - WIZCHIP.IF.BUS._read_byte = bus_rb; - WIZCHIP.IF.BUS._write_byte = bus_wb; - } -} - -void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)) -{ - while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); - - if(!spi_rb || !spi_wb) - { - WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes; - WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes; - } - else - { - WIZCHIP.IF.SPI._read_bytes = spi_rb; - WIZCHIP.IF.SPI._write_bytes = spi_wb; - } -} - -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) -{ - uint8_t tmp = 0; - uint8_t* ptmp[2] = {0,0}; - switch(cwtype) - { - case CW_RESET_WIZCHIP: - wizchip_sw_reset(); - break; - case CW_INIT_WIZCHIP: - if(arg != 0) - { - ptmp[0] = (uint8_t*)arg; - ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; - } - return wizchip_init(ptmp[0], ptmp[1]); - case CW_CLR_INTERRUPT: - wizchip_clrinterrupt(*((intr_kind*)arg)); - break; - case CW_GET_INTERRUPT: - *((intr_kind*)arg) = wizchip_getinterrupt(); - break; - case CW_SET_INTRMASK: - wizchip_setinterruptmask(*((intr_kind*)arg)); - break; - case CW_GET_INTRMASK: - *((intr_kind*)arg) = wizchip_getinterruptmask(); - break; - #if _WIZCHIP_ > 5100 - case CW_SET_INTRTIME: - setINTLEVEL(*(uint16_t*)arg); - break; - case CW_GET_INTRTIME: - *(uint16_t*)arg = getINTLEVEL(); - break; - #endif - case CW_GET_ID: - ((uint8_t*)arg)[0] = WIZCHIP.id[0]; - ((uint8_t*)arg)[1] = WIZCHIP.id[1]; - ((uint8_t*)arg)[2] = WIZCHIP.id[2]; - ((uint8_t*)arg)[3] = WIZCHIP.id[3]; - ((uint8_t*)arg)[4] = WIZCHIP.id[4]; - ((uint8_t*)arg)[5] = 0; - break; - #if _WIZCHIP_ == 5500 - case CW_RESET_PHY: - wizphy_reset(); - break; - case CW_SET_PHYCONF: - wizphy_setphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYCONF: - wizphy_getphyconf((wiz_PhyConf*)arg); - break; - case CW_GET_PHYSTATUS: - break; - case CW_SET_PHYPOWMODE: - return wizphy_setphypmode(*(uint8_t*)arg); - #endif - case CW_GET_PHYPOWMODE: - tmp = wizphy_getphypmode(); - if((int8_t)tmp == -1) return -1; - *(uint8_t*)arg = tmp; - break; - case CW_GET_PHYLINK: - tmp = wizphy_getphylink(); - if((int8_t)tmp == -1) return -1; - *(uint8_t*)arg = tmp; - break; - default: - return -1; - } - return 0; -} - - -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) -{ - - switch(cntype) - { - case CN_SET_NETINFO: - wizchip_setnetinfo((wiz_NetInfo*)arg); - break; - case CN_GET_NETINFO: - wizchip_getnetinfo((wiz_NetInfo*)arg); - break; - case CN_SET_NETMODE: - return wizchip_setnetmode(*(netmode_type*)arg); - case CN_GET_NETMODE: - *(netmode_type*)arg = wizchip_getnetmode(); - break; - case CN_SET_TIMEOUT: - wizchip_settimeout((wiz_NetTimeout*)arg); - break; - case CN_GET_TIMEOUT: - wizchip_gettimeout((wiz_NetTimeout*)arg); - break; - default: - return -1; - } - return 0; -} - -void wizchip_sw_reset(void) -{ - uint8_t gw[4], sn[4], sip[4]; - uint8_t mac[6]; - getSHAR(mac); - getGAR(gw); getSUBR(sn); getSIPR(sip); - setMR(MR_RST); - getMR(); // for delay - setSHAR(mac); - setGAR(gw); - setSUBR(sn); - setSIPR(sip); -} - -int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) -{ - int8_t i; - int8_t tmp = 0; - wizchip_sw_reset(); - if(txsize) - { - tmp = 0; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - tmp += txsize[i]; - if(tmp > 16) return -1; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - setSn_TXBUF_SIZE(i, txsize[i]); - } - if(rxsize) - { - tmp = 0; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - tmp += rxsize[i]; - if(tmp > 16) return -1; - for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) - setSn_RXBUF_SIZE(i, rxsize[i]); - } - - WIZCHIP_EXPORT(socket_reset)(); - - return 0; -} - -void wizchip_clrinterrupt(intr_kind intr) -{ - uint8_t ir = (uint8_t)intr; - uint8_t sir = (uint8_t)((uint16_t)intr >> 8); -#if _WIZCHIP_ < 5500 - ir |= (1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - ir |= (1 << 6); -#endif - -#if _WIZCHIP_ < 5200 - sir &= 0x0F; -#endif - -#if _WIZCHIP_ == 5100 - ir |= sir; - setIR(ir); -#else - setIR(ir); - setSIR(sir); -#endif -} - -intr_kind wizchip_getinterrupt(void) -{ - uint8_t ir = 0; - uint8_t sir = 0; - uint16_t ret = 0; -#if _WIZCHIP_ == 5100 - ir = getIR(); - sir = ir 0x0F; -#else - ir = getIR(); - sir = getSIR(); -#endif - -#if _WIZCHIP_ < 5500 - ir &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - ir &= ~(1 << 6); -#endif - ret = sir; - ret = (ret << 8) + ir; - return (intr_kind)ret; -} - -void wizchip_setinterruptmask(intr_kind intr) -{ - uint8_t imr = (uint8_t)intr; - uint8_t simr = (uint8_t)((uint16_t)intr >> 8); -#if _WIZCHIP_ < 5500 - imr &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - imr &= ~(1 << 6); -#endif - -#if _WIZCHIP_ < 5200 - simr &= 0x0F; -#endif - -#if _WIZCHIP_ == 5100 - imr |= simr; - setIMR(imr); -#else - setIMR(imr); - setSIMR(simr); -#endif -} - -intr_kind wizchip_getinterruptmask(void) -{ - uint8_t imr = 0; - uint8_t simr = 0; - uint16_t ret = 0; -#if _WIZCHIP_ == 5100 - imr = getIMR(); - simr = imr 0x0F; -#else - imr = getIMR(); - simr = getSIMR(); -#endif - -#if _WIZCHIP_ < 5500 - imr &= ~(1<<4); // IK_WOL -#endif -#if _WIZCHIP_ == 5200 - imr &= ~(1 << 6); // IK_DEST_UNREACH -#endif - ret = simr; - ret = (ret << 8) + imr; - return (intr_kind)ret; -} - -int8_t wizphy_getphylink(void) -{ - int8_t tmp; -#if _WIZCHIP_ == 5200 - if(getPHYSTATUS() & PHYSTATUS_LINK) - tmp = PHY_LINK_ON; - else - tmp = PHY_LINK_OFF; -#elif _WIZCHIP_ == 5500 - if(getPHYCFGR() & PHYCFGR_LNK_ON) - tmp = PHY_LINK_ON; - else - tmp = PHY_LINK_OFF; -#else - tmp = -1; -#endif - return tmp; -} - -#if _WIZCHIP_ > 5100 - -int8_t wizphy_getphypmode(void) -{ - int8_t tmp = 0; - #if _WIZCHIP_ == 5200 - if(getPHYSTATUS() & PHYSTATUS_POWERDOWN) - tmp = PHY_POWER_DOWN; - else - tmp = PHY_POWER_NORM; - #elif _WIZCHIP_ == 5500 - if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN) - tmp = PHY_POWER_DOWN; - else - tmp = PHY_POWER_NORM; - #else - tmp = -1; - #endif - return tmp; -} -#endif - -#if _WIZCHIP_ == 5500 -void wizphy_reset(void) -{ - uint8_t tmp = getPHYCFGR(); - tmp &= PHYCFGR_RST; - setPHYCFGR(tmp); - tmp = getPHYCFGR(); - tmp |= ~PHYCFGR_RST; - setPHYCFGR(tmp); -} - -void wizphy_setphyconf(wiz_PhyConf* phyconf) -{ - uint8_t tmp = 0; - if(phyconf->by == PHY_CONFBY_SW) - tmp |= PHYCFGR_OPMD; - else - tmp &= ~PHYCFGR_OPMD; - if(phyconf->mode == PHY_MODE_AUTONEGO) - tmp |= PHYCFGR_OPMDC_ALLA; - else - { - if(phyconf->duplex == PHY_DUPLEX_FULL) - { - if(phyconf->speed == PHY_SPEED_100) - tmp |= PHYCFGR_OPMDC_100F; - else - tmp |= PHYCFGR_OPMDC_10F; - } - else - { - if(phyconf->speed == PHY_SPEED_100) - tmp |= PHYCFGR_OPMDC_100H; - else - tmp |= PHYCFGR_OPMDC_10H; - } - } - setPHYCFGR(tmp); - wizphy_reset(); -} - -void wizphy_getphyconf(wiz_PhyConf* phyconf) -{ - uint8_t tmp = 0; - tmp = getPHYCFGR(); - phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW; - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_ALLA: - case PHYCFGR_OPMDC_100FA: - phyconf->mode = PHY_MODE_AUTONEGO; - break; - default: - phyconf->mode = PHY_MODE_MANUAL; - break; - } - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_100H: - phyconf->speed = PHY_SPEED_100; - break; - default: - phyconf->speed = PHY_SPEED_10; - break; - } - switch(tmp & PHYCFGR_OPMDC_ALLA) - { - case PHYCFGR_OPMDC_100FA: - case PHYCFGR_OPMDC_100F: - case PHYCFGR_OPMDC_10F: - phyconf->duplex = PHY_DUPLEX_FULL; - break; - default: - phyconf->duplex = PHY_DUPLEX_HALF; - break; - } -} - -void wizphy_getphystat(wiz_PhyConf* phyconf) -{ - uint8_t tmp = getPHYCFGR(); - phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; - phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10; -} - -int8_t wizphy_setphypmode(uint8_t pmode) -{ - uint8_t tmp = 0; - tmp = getPHYCFGR(); - if((tmp & PHYCFGR_OPMD)== 0) return -1; - tmp &= ~PHYCFGR_OPMDC_ALLA; - if( pmode == PHY_POWER_DOWN) - tmp |= PHYCFGR_OPMDC_PDOWN; - else - tmp |= PHYCFGR_OPMDC_ALLA; - setPHYCFGR(tmp); - wizphy_reset(); - tmp = getPHYCFGR(); - if( pmode == PHY_POWER_DOWN) - { - if(tmp & PHYCFGR_OPMDC_PDOWN) return 0; - } - else - { - if(tmp & PHYCFGR_OPMDC_ALLA) return 0; - } - return -1; -} -#endif - - -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) -{ - setSHAR(pnetinfo->mac); - setGAR(pnetinfo->gw); - setSUBR(pnetinfo->sn); - setSIPR(pnetinfo->ip); -#if _WIZCHIP_ == 5200 // for W5200 ARP errata - _SUBN_[0] = pnetinfo->sn[0]; - _SUBN_[1] = pnetinfo->sn[1]; - _SUBN_[2] = pnetinfo->sn[2]; - _SUBN_[3] = pnetinfo->sn[3]; -#endif - _DNS_[0] = pnetinfo->dns[0]; - _DNS_[1] = pnetinfo->dns[1]; - _DNS_[2] = pnetinfo->dns[2]; - _DNS_[3] = pnetinfo->dns[3]; - _DHCP_ = pnetinfo->dhcp; -} - -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) -{ - getSHAR(pnetinfo->mac); - getGAR(pnetinfo->gw); - getSUBR(pnetinfo->sn); - getSIPR(pnetinfo->ip); -#if _WIZCHIP_ == 5200 // for W5200 ARP errata - pnetinfo->sn[0] = _SUBN_[0]; - pnetinfo->sn[1] = _SUBN_[1]; - pnetinfo->sn[2] = _SUBN_[2]; - pnetinfo->sn[3] = _SUBN_[3]; -#endif - pnetinfo->dns[0]= _DNS_[0]; - pnetinfo->dns[1]= _DNS_[1]; - pnetinfo->dns[2]= _DNS_[2]; - pnetinfo->dns[3]= _DNS_[3]; - pnetinfo->dhcp = _DHCP_; -} - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -uint8_t *wizchip_getsubn(void) { - return _SUBN_; -} -#endif - -int8_t wizchip_setnetmode(netmode_type netmode) -{ - uint8_t tmp = 0; -#if _WIZCHIP_ != 5500 - if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1; -#else - if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1; -#endif - tmp = getMR(); - tmp |= (uint8_t)netmode; - setMR(tmp); - return 0; -} - -netmode_type wizchip_getnetmode(void) -{ - return (netmode_type) getMR(); -} - -void wizchip_settimeout(wiz_NetTimeout* nettime) -{ - setRCR(nettime->retry_cnt); - setRTR(nettime->time_100us); -} - -void wizchip_gettimeout(wiz_NetTimeout* nettime) -{ - nettime->retry_cnt = getRCR(); - nettime->time_100us = getRTR(); -} diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/wizchip_conf.h b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/wizchip_conf.h deleted file mode 100644 index 4a7a7bd6..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/ethernet/wizchip_conf.h +++ /dev/null @@ -1,554 +0,0 @@ -//***************************************************************************** -// -//! \file wizchip_conf.h -//! \brief WIZCHIP Config Header File. -//! \version 1.0.0 -//! \date 2013/10/21 -//! \par Revision history -//! <2013/10/21> 1st Release -//! \author MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -/** - * @defgroup extra_functions 2. WIZnet Extra Functions - * - * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions. - * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n - * - */ - -#ifndef _WIZCHIP_CONF_H_ -#define _WIZCHIP_CONF_H_ - -#include -/** - * @brief Select WIZCHIP. - * @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n - * ex> #define \_WIZCHIP_ 5500 - */ -#ifndef _WIZCHIP_ -#define _WIZCHIP_ 5200 // 5100, 5200, 5500 -#endif - -#define _WIZCHIP_IO_MODE_NONE_ 0x0000 -#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */ -#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */ -//#define _WIZCHIP_IO_MODE_IIC_ 0x0400 -//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800 -// Add to -// - -#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */ -#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */ - -#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/ -#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/ - - -#if (_WIZCHIP_ == 5100) - #define _WIZCHIP_ID_ "W5100\0" -/** - * @brief Define interface mode. - * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ - */ - -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_ -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ - -#elif (_WIZCHIP_ == 5200) - #define _WIZCHIP_ID_ "W5200\0" -/** - * @brief Define interface mode. - * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ - */ -// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ - #include "w5200/w5200.h" -#elif (_WIZCHIP_ == 5500) - #define _WIZCHIP_ID_ "W5500\0" - -/** - * @brief Define interface mode. \n - * @todo Should select interface mode as chip. - * - @ref \_WIZCHIP_IO_MODE_SPI_ \n - * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n - * - @ref \_WIZCHIP_IO_MODE_BUS_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n - * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n - * - Others will be defined in future. \n\n - * ex> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ - * - */ - //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_ - #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ - #include "w5500/w5500.h" -#else - #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!" -#endif - -#ifndef _WIZCHIP_IO_MODE_ - #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!" -#endif - -/** - * @brief Define I/O base address when BUS IF mode. - * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_, - * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n - * ex> #define \_WIZCHIP_IO_BASE_ 0x00008000 - */ -#define _WIZCHIP_IO_BASE_ 0x00000000 // - -#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS - #ifndef _WIZCHIP_IO_BASE_ - #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map." - #endif -#endif - -#if _WIZCHIP_ > 5100 - #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP -#else - #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP -#endif - - -/******************************************************** -* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC. -*********************************************************/ -/** - * @ingroup DATA_TYPE - * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200 - */ -typedef struct __WIZCHIP -{ - uint16_t if_mode; ///< host interface mode - uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on. - /** - * The set of critical section callback func. - */ - struct _CRIS - { - void (*_enter) (void); ///< crtical section enter - void (*_exit) (void); ///< critial section exit - }CRIS; - /** - * The set of @ref\_WIZCHIP_ select control callback func. - */ - struct _CS - { - void (*_select) (void); ///< @ref \_WIZCHIP_ selected - void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected - }CS; - /** - * The set of interface IO callback func. - */ - union _IF - { - /** - * For BUS interface IO - */ - struct - { - uint8_t (*_read_byte) (uint32_t AddrSel); - void (*_write_byte) (uint32_t AddrSel, uint8_t wb); - }BUS; - /** - * For SPI interface IO - */ - struct - { - void (*_read_bytes) (uint8_t *buf, uint32_t len); - void (*_write_bytes) (const uint8_t *buf, uint32_t len); - }SPI; - // To be added - // - }IF; -}_WIZCHIP; - -extern _WIZCHIP WIZCHIP; - -/** - * @ingroup DATA_TYPE - * WIZCHIP control type enumration used in @ref ctlwizchip(). - */ -typedef enum -{ - CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly - CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t. - CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP - CW_CLR_INTERRUPT, ///< Clears interrupt - CW_SET_INTRMASK, ///< Masks interrupt - CW_GET_INTRMASK, ///< Get interrupt mask - CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt. - CW_GET_ID, ///< Gets WIZCHIP name. - -#if _WIZCHIP_ == 5500 - CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000 - CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000 - CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000 - CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000 - CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000 -#endif - CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal - CW_GET_PHYLINK ///< Get PHY Link status -}ctlwizchip_type; - -/** - * @ingroup DATA_TYPE - * Network control type enumration used in @ref ctlnetwork(). - */ -typedef enum -{ - CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo - CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo - CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode - CN_SET_TIMEOUT, ///< Set network timeout as retry count and time. - CN_GET_TIMEOUT, ///< Get network timeout as retry count and time. -}ctlnetwork_type; - -/** - * @ingroup DATA_TYPE - * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK - * and CW_GET_INTRMASK is used in @ref ctlnetwork(). - * It can be used with OR operation. - */ -typedef enum -{ -#if _WIZCHIP_ > 5200 - IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500. -#endif - - IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected - -#if _WIZCHIP_ != 5200 - IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200 -#endif - - IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred - - IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt - IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt - IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt - IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt -#if _WIZCHIP_ > 5100 - IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100 - IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100 - IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100 - IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100 -#endif - -#if _WIZCHIP_ > 5100 - IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt -#else - IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt -#endif -}intr_kind; - -#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin -#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register -#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting. -#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation -#define PHY_SPEED_10 0 ///< Link Speed 10 -#define PHY_SPEED_100 1 ///< Link Speed 100 -#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex -#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex -#define PHY_LINK_OFF 0 ///< Link Off -#define PHY_LINK_ON 1 ///< Link On -#define PHY_POWER_NORM 0 ///< PHY power normal mode -#define PHY_POWER_DOWN 1 ///< PHY power down mode - - -#if _WIZCHIP_ == 5500 -/** - * @ingroup DATA_TYPE - * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500, - * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n - * Valid only in W5500. - */ -typedef struct wiz_PhyConf_t -{ - uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW - uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO - uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100 - uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL - //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN - //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF - }wiz_PhyConf; -#endif - -/** - * @ingroup DATA_TYPE - * It used in setting dhcp_mode of @ref wiz_NetInfo. - */ -typedef enum -{ - NETINFO_STATIC = 1, ///< Static IP configuration by manually. - NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever -}dhcp_mode; - -/** - * @ingroup DATA_TYPE - * Network Information for WIZCHIP - */ -typedef struct wiz_NetInfo_t -{ - uint8_t mac[6]; ///< Source Mac Address - uint8_t ip[4]; ///< Source IP Address - uint8_t sn[4]; ///< Subnet Mask - uint8_t gw[4]; ///< Gateway IP Address - uint8_t dns[4]; ///< DNS server IP Address - dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP -}wiz_NetInfo; - -/** - * @ingroup DATA_TYPE - * Network mode - */ -typedef enum -{ -#if _WIZCHIP_ == 5500 - NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500 -#endif - NM_WAKEONLAN = (1<<5), ///< Wake On Lan - NM_PINGBLOCK = (1<<4), ///< Block ping-request - NM_PPPOE = (1<<3), ///< PPPoE mode -}netmode_type; - -/** - * @ingroup DATA_TYPE - * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation. - */ -typedef struct wiz_NetTimeout_t -{ - uint8_t retry_cnt; ///< retry count - uint16_t time_100us; ///< time unit 100us -}wiz_NetTimeout; - -/** - *@brief Registers call back function for critical section of I/O functions such as - *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF. - *@param cris_en : callback function for critical section enter. - *@param cris_ex : callback function for critical section exit. - *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions. - *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called. - */ -void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)); - - -/** - *@brief Registers call back function for WIZCHIP select & deselect. - *@param cs_sel : callback function for WIZCHIP select - *@param cs_desel : callback fucntion for WIZCHIP deselect - *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)); - -/** - *@brief Registers call back function for bus interface. - *@param bus_rb : callback function to read byte data using system bus - *@param bus_wb : callback function to write byte data using system bus - *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function - *or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)); - -/** - *@brief Registers call back function for SPI interface. - *@param spi_rb : callback function to read byte usig SPI - *@param spi_wb : callback function to write byte usig SPI - *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function - *or register your functions. - *@note If you do not describe or register, null function is called. - */ -void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)); - -/** - * @ingroup extra_functions - * @brief Controls to the WIZCHIP. - * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto), - * controls interrupt & mask and so on. - * @param cwtype : Decides to the control type - * @param arg : arg type is dependent on cwtype. - * @return 0 : Success \n - * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP - */ -int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg); - -/** - * @ingroup extra_functions - * @brief Controls to network. - * @details Controls to network environment, mode, timeout and so on. - * @param cntype : Input. Decides to the control type - * @param arg : Inout. arg type is dependent on cntype. - * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n - * 0 : Success - */ -int8_t ctlnetwork(ctlnetwork_type cntype, void* arg); - - -/* - * The following functions are implemented for internal use. - * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork(). - */ - -/** - * @ingroup extra_functions - * @brief Reset WIZCHIP by softly. - */ -void wizchip_sw_reset(void); - -/** - * @ingroup extra_functions - * @brief Initializes WIZCHIP with socket buffer size - * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB. - * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB. - * @return 0 : succcess \n - * -1 : fail. Invalid buffer size - */ -int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize); - -/** - * @ingroup extra_functions - * @brief Clear Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_clrinterrupt(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt of WIZCHIP. - * @return @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterrupt(void); - -/** - * @ingroup extra_functions - * @brief Mask or Unmask Interrupt of WIZCHIP. - * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. - */ -void wizchip_setinterruptmask(intr_kind intr); - -/** - * @ingroup extra_functions - * @brief Get Interrupt mask of WIZCHIP. - * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t. - */ -intr_kind wizchip_getinterruptmask(void); - -#if _WIZCHIP_ > 5100 - int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100 - int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100 -#endif - -#if _WIZCHIP_ == 5500 - void wizphy_reset(void); ///< Reset phy. Vailid only in W5500 -/** - * @ingroup extra_functions - * @brief Set the phy information for WIZCHIP without power mode - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_setphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy configuration information. - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_getphyconf(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief Get phy status. - * @param phyconf : @ref wiz_PhyConf - */ - void wizphy_getphystat(wiz_PhyConf* phyconf); - /** - * @ingroup extra_functions - * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200 - * @param pmode Settig value of power down mode. - */ - int8_t wizphy_setphypmode(uint8_t pmode); -#endif - -/** -* @ingroup extra_functions - * @brief Set the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_setnetinfo(wiz_NetInfo* pnetinfo); - -/** - * @ingroup extra_functions - * @brief Get the network information for WIZCHIP - * @param pnetinfo : @ref wizNetInfo - */ -void wizchip_getnetinfo(wiz_NetInfo* pnetinfo); - -#if _WIZCHIP_ == 5200 // for W5200 ARP errata -uint8_t *wizchip_getsubn(void); -#endif - -/** - * @ingroup extra_functions - * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. - * @param pnetinfo Value of network mode. Refer to @ref netmode_type. - */ -int8_t wizchip_setnetmode(netmode_type netmode); - -/** - * @ingroup extra_functions - * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. - * @return Value of network mode. Refer to @ref netmode_type. - */ -netmode_type wizchip_getnetmode(void); - -/** - * @ingroup extra_functions - * @brief Set retry time value(@ref RTR) and retry count(@ref RCR). - * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. - * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_settimeout(wiz_NetTimeout* nettime); - -/** - * @ingroup extra_functions - * @brief Get retry time value(@ref RTR) and retry count(@ref RCR). - * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. - * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. - */ -void wizchip_gettimeout(wiz_NetTimeout* nettime); - -#endif // _WIZCHIP_CONF_H_ diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dhcp/dhcp.c b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dhcp/dhcp.c deleted file mode 100644 index 57475825..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dhcp/dhcp.c +++ /dev/null @@ -1,978 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.c -//! \brief DHCP APIs implement file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Optimize code -//! 2. Add reg_dhcp_cbfunc() -//! 3. Add DHCP_stop() -//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run() -//! 5. Don't care system endian -//! 6. Add comments -//! <2012/12/26> V1.1.1 -//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -//#include "Ethernet/socket.h" -//#include "Internet/DHCP/dhcp.h" -#include "../../Ethernet/socket.h" -#include "dhcp.h" - -/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ - -#ifdef _DHCP_DEBUG_ - #include -#endif - -/* DHCP state machine. */ -#define STATE_DHCP_INIT 0 ///< Initialize -#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER -#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK -#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased -#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP -#define STATE_DHCP_RELEASE 5 ///< No use -#define STATE_DHCP_STOP 6 ///< Stop processing DHCP - -#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG -#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG - -/* DHCP message OP code */ -#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG -#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG - -/* DHCP message type */ -#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG -#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG -#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG -#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG -#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG -#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG -#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use -#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use - -#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG -#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG - -#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG -#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG -#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG - -#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time - -#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG -#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG - -/* - * @brief DHCP option and value (cf. RFC1533) - */ -enum -{ - padOption = 0, - subnetMask = 1, - timerOffset = 2, - routersOnSubnet = 3, - timeServer = 4, - nameServer = 5, - dns = 6, - logServer = 7, - cookieServer = 8, - lprServer = 9, - impressServer = 10, - resourceLocationServer = 11, - hostName = 12, - bootFileSize = 13, - meritDumpFile = 14, - domainName = 15, - swapServer = 16, - rootPath = 17, - extentionsPath = 18, - IPforwarding = 19, - nonLocalSourceRouting = 20, - policyFilter = 21, - maxDgramReasmSize = 22, - defaultIPTTL = 23, - pathMTUagingTimeout = 24, - pathMTUplateauTable = 25, - ifMTU = 26, - allSubnetsLocal = 27, - broadcastAddr = 28, - performMaskDiscovery = 29, - maskSupplier = 30, - performRouterDiscovery = 31, - routerSolicitationAddr = 32, - staticRoute = 33, - trailerEncapsulation = 34, - arpCacheTimeout = 35, - ethernetEncapsulation = 36, - tcpDefaultTTL = 37, - tcpKeepaliveInterval = 38, - tcpKeepaliveGarbage = 39, - nisDomainName = 40, - nisServers = 41, - ntpServers = 42, - vendorSpecificInfo = 43, - netBIOSnameServer = 44, - netBIOSdgramDistServer = 45, - netBIOSnodeType = 46, - netBIOSscope = 47, - xFontServer = 48, - xDisplayManager = 49, - dhcpRequestedIPaddr = 50, - dhcpIPaddrLeaseTime = 51, - dhcpOptionOverload = 52, - dhcpMessageType = 53, - dhcpServerIdentifier = 54, - dhcpParamRequest = 55, - dhcpMsg = 56, - dhcpMaxMsgSize = 57, - dhcpT1value = 58, - dhcpT2value = 59, - dhcpClassIdentifier = 60, - dhcpClientIdentifier = 61, - endOption = 255 -}; - -/* - * @brief DHCP message format - */ -typedef struct { - uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY - uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB - uint8_t hlen; ///< @ref DHCP_HLENETHERNET - uint8_t hops; ///< @ref DHCP_HOPS - uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction. - uint16_t secs; ///< @ref DHCP_SECS - uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST - uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever - uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server - uint8_t siaddr[4]; ///< No use - uint8_t giaddr[4]; ///< No use - uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero - uint8_t sname[64]; ///< No use - uint8_t file[128]; ///< No use - uint8_t OPT[OPT_SIZE]; ///< Option -} RIP_MSG; - - - -uint8_t DHCP_SOCKET; // Socket number for DHCP - -uint8_t DHCP_SIP[4]; // DHCP Server IP address - -// Network information from DHCP Server -uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address -uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP -uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP -uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP -uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP - - -int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state -int8_t dhcp_retry_count = 0; - -uint32_t dhcp_lease_time = INFINITE_LEASETIME; -volatile uint32_t dhcp_tick_1s = 0; // unit 1 second -uint32_t dhcp_tick_next = DHCP_WAIT_TIME ; - -uint32_t DHCP_XID; // Any number - -RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing - -uint8_t HOST_NAME[] = DCHP_HOST_NAME; - -uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address. - -/* The default callback function */ -void default_ip_assign(void); -void default_ip_update(void); -void default_ip_conflict(void); - -/* Callback handler */ -void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */ -void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */ -void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */ - -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - - -/* send DISCOVER message to DHCP server */ -void send_DHCP_DISCOVER(void); - -/* send REQEUST message to DHCP server */ -void send_DHCP_REQUEST(void); - -/* send DECLINE message to DHCP server */ -void send_DHCP_DECLINE(void); - -/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ -int8_t check_DHCP_leasedIP(void); - -/* check the timeout in DHCP process */ -uint8_t check_DHCP_timeout(void); - -/* Intialize to timeout process. */ -void reset_DHCP_timeout(void); - -/* Parse message as OFFER and ACK and NACK from DHCP server.*/ -int8_t parseDHCPCMSG(void); - -/* The default handler of ip assign first */ -void default_ip_assign(void) -{ - setSIPR(DHCP_allocated_ip); - setSUBR(DHCP_allocated_sn); - setGAR (DHCP_allocated_gw); -} - -/* The default handler of ip changed */ -void default_ip_update(void) -{ - /* WIZchip Software Reset */ - setMR(MR_RST); - getMR(); // for delay - default_ip_assign(); - setSHAR(DHCP_CHADDR); -} - -/* The default handler of ip changed */ -void default_ip_conflict(void) -{ - // WIZchip Software Reset - setMR(MR_RST); - getMR(); // for delay - setSHAR(DHCP_CHADDR); -} - -/* register the call back func. */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) -{ - dhcp_ip_assign = default_ip_assign; - dhcp_ip_update = default_ip_update; - dhcp_ip_conflict = default_ip_conflict; - if(ip_assign) dhcp_ip_assign = ip_assign; - if(ip_update) dhcp_ip_update = ip_update; - if(ip_conflict) dhcp_ip_conflict = ip_conflict; -} - -/* make the common DHCP message */ -void makeDHCPMSG(void) -{ - uint8_t bk_mac[6]; - uint8_t* ptmp; - uint8_t i; - getSHAR(bk_mac); - pDHCPMSG->op = DHCP_BOOTREQUEST; - pDHCPMSG->htype = DHCP_HTYPE10MB; - pDHCPMSG->hlen = DHCP_HLENETHERNET; - pDHCPMSG->hops = DHCP_HOPS; - ptmp = (uint8_t*)(&pDHCPMSG->xid); - *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24); - *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16); - *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8); - *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0); - pDHCPMSG->secs = DHCP_SECS; - ptmp = (uint8_t*)(&pDHCPMSG->flags); - *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8); - *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0); - - pDHCPMSG->ciaddr[0] = 0; - pDHCPMSG->ciaddr[1] = 0; - pDHCPMSG->ciaddr[2] = 0; - pDHCPMSG->ciaddr[3] = 0; - - pDHCPMSG->yiaddr[0] = 0; - pDHCPMSG->yiaddr[1] = 0; - pDHCPMSG->yiaddr[2] = 0; - pDHCPMSG->yiaddr[3] = 0; - - pDHCPMSG->siaddr[0] = 0; - pDHCPMSG->siaddr[1] = 0; - pDHCPMSG->siaddr[2] = 0; - pDHCPMSG->siaddr[3] = 0; - - pDHCPMSG->giaddr[0] = 0; - pDHCPMSG->giaddr[1] = 0; - pDHCPMSG->giaddr[2] = 0; - pDHCPMSG->giaddr[3] = 0; - - pDHCPMSG->chaddr[0] = DHCP_CHADDR[0]; - pDHCPMSG->chaddr[1] = DHCP_CHADDR[1]; - pDHCPMSG->chaddr[2] = DHCP_CHADDR[2]; - pDHCPMSG->chaddr[3] = DHCP_CHADDR[3]; - pDHCPMSG->chaddr[4] = DHCP_CHADDR[4]; - pDHCPMSG->chaddr[5] = DHCP_CHADDR[5]; - - for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0; - for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0; - for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0; - - // MAGIC_COOKIE - pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); - pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); - pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8); - pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0; -} - -/* SEND DHCP DISCOVER */ -void send_DHCP_DISCOVER(void) -{ - uint16_t i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DISCOVER; - - // Client identifier - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname - for(i = 0 ; HOST_NAME[i] != 0; i++) - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname - - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x06; // length of request - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - - // send broadcasting packet - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - -#ifdef _DHCP_DEBUG_ - printf("> Send DHCP_DISCOVER\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* SEND DHCP REQUEST */ -void send_DHCP_REQUEST(void) -{ - int i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) - { - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0]; - pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1]; - pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2]; - pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3]; - ip[0] = DHCP_SIP[0]; - ip[1] = DHCP_SIP[1]; - ip[2] = DHCP_SIP[2]; - ip[3] = DHCP_SIP[3]; - } - else - { - ip[0] = 255; - ip[1] = 255; - ip[2] = 255; - ip[3] = 255; - } - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_REQUEST; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) - { - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - } - - // host name - pDHCPMSG->OPT[k++] = hostName; - pDHCPMSG->OPT[k++] = 0; // length of hostname - for(i = 0 ; HOST_NAME[i] != 0; i++) - pDHCPMSG->OPT[k++] = HOST_NAME[i]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname - - pDHCPMSG->OPT[k++] = dhcpParamRequest; - pDHCPMSG->OPT[k++] = 0x08; - pDHCPMSG->OPT[k++] = subnetMask; - pDHCPMSG->OPT[k++] = routersOnSubnet; - pDHCPMSG->OPT[k++] = dns; - pDHCPMSG->OPT[k++] = domainName; - pDHCPMSG->OPT[k++] = dhcpT1value; - pDHCPMSG->OPT[k++] = dhcpT2value; - pDHCPMSG->OPT[k++] = performRouterDiscovery; - pDHCPMSG->OPT[k++] = staticRoute; - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - -#ifdef _DHCP_DEBUG_ - printf("> Send DHCP_REQUEST\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); - -} - -/* SEND DHCP DHCPDECLINE */ -void send_DHCP_DECLINE(void) -{ - int i; - uint8_t ip[4]; - uint16_t k = 0; - - makeDHCPMSG(); - - k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() - - *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); - *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); - - // Option Request Param. - pDHCPMSG->OPT[k++] = dhcpMessageType; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_DECLINE; - - pDHCPMSG->OPT[k++] = dhcpClientIdentifier; - pDHCPMSG->OPT[k++] = 0x07; - pDHCPMSG->OPT[k++] = 0x01; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; - pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - - pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; - pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; - - pDHCPMSG->OPT[k++] = dhcpServerIdentifier; - pDHCPMSG->OPT[k++] = 0x04; - pDHCPMSG->OPT[k++] = DHCP_SIP[0]; - pDHCPMSG->OPT[k++] = DHCP_SIP[1]; - pDHCPMSG->OPT[k++] = DHCP_SIP[2]; - pDHCPMSG->OPT[k++] = DHCP_SIP[3]; - - pDHCPMSG->OPT[k++] = endOption; - - for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; - - //send broadcasting packet - ip[0] = 0xFF; - ip[1] = 0xFF; - ip[2] = 0xFF; - ip[3] = 0xFF; - -#ifdef _DHCP_DEBUG_ - printf("\r\n> Send DHCP_DECLINE\r\n"); -#endif - - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); -} - -/* PARSE REPLY pDHCPMSG */ -int8_t parseDHCPMSG(void) -{ - uint8_t svr_addr[6]; - uint16_t svr_port; - uint16_t len; - - uint8_t * p; - uint8_t * e; - uint8_t type; - uint8_t opt_len; - - if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) - { - len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); - #ifdef _DHCP_DEBUG_ - printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len); - #endif - } - else return 0; - if (svr_port == DHCP_SERVER_PORT) { - // compare mac address - if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) || - (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) || - (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) ) - return 0; - type = 0; - p = (uint8_t *)(&pDHCPMSG->op); - p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) - e = p + (len - 240); - - while ( p < e ) { - - switch ( *p ) { - - case endOption : - p = e; // for break while(p < e) - break; - case padOption : - p++; - break; - case dhcpMessageType : - p++; - p++; - type = *p++; - break; - case subnetMask : - p++; - p++; - DHCP_allocated_sn[0] = *p++; - DHCP_allocated_sn[1] = *p++; - DHCP_allocated_sn[2] = *p++; - DHCP_allocated_sn[3] = *p++; - break; - case routersOnSubnet : - p++; - opt_len = *p++; - DHCP_allocated_gw[0] = *p++; - DHCP_allocated_gw[1] = *p++; - DHCP_allocated_gw[2] = *p++; - DHCP_allocated_gw[3] = *p++; - p = p + (opt_len - 4); - break; - case dns : - p++; - opt_len = *p++; - DHCP_allocated_dns[0] = *p++; - DHCP_allocated_dns[1] = *p++; - DHCP_allocated_dns[2] = *p++; - DHCP_allocated_dns[3] = *p++; - p = p + (opt_len - 4); - break; - case dhcpIPaddrLeaseTime : - p++; - opt_len = *p++; - dhcp_lease_time = *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - dhcp_lease_time = (dhcp_lease_time << 8) + *p++; - #ifdef _DHCP_DEBUG_ - dhcp_lease_time = 10; - #endif - break; - case dhcpServerIdentifier : - p++; - opt_len = *p++; - DHCP_SIP[0] = *p++; - DHCP_SIP[1] = *p++; - DHCP_SIP[2] = *p++; - DHCP_SIP[3] = *p++; - break; - default : - p++; - opt_len = *p++; - p += opt_len; - break; - } // switch - } // while - } // if - return type; -} - -uint8_t DHCP_run(void) -{ - uint8_t type; - uint8_t ret; - - if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED; - - if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) - socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); - - ret = DHCP_RUNNING; - type = parseDHCPMSG(); - - switch ( dhcp_state ) { - case STATE_DHCP_INIT : - DHCP_allocated_ip[0] = 0; - DHCP_allocated_ip[1] = 0; - DHCP_allocated_ip[2] = 0; - DHCP_allocated_ip[3] = 0; - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - case STATE_DHCP_DISCOVER : - if (type == DHCP_OFFER){ -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_OFFER\r\n"); -#endif - DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0]; - DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1]; - DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2]; - DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; - - send_DHCP_REQUEST(); - dhcp_state = STATE_DHCP_REQUEST; - } else ret = check_DHCP_timeout(); - break; - - case STATE_DHCP_REQUEST : - if (type == DHCP_ACK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_ACK\r\n"); -#endif - if (check_DHCP_leasedIP()) { - // Network info assignment from DHCP - dhcp_ip_assign(); - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_LEASED; - } else { - // IP address conflict occurred - reset_DHCP_timeout(); - dhcp_ip_conflict(); - dhcp_state = STATE_DHCP_INIT; - } - } else if (type == DHCP_NAK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_NACK\r\n"); -#endif - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_DISCOVER; - } else ret = check_DHCP_timeout(); - break; - - case STATE_DHCP_LEASED : - ret = DHCP_IP_LEASED; - if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) { - -#ifdef _DHCP_DEBUG_ - printf("> Maintains the IP address \r\n"); -#endif - - type = 0; - OLD_allocated_ip[0] = DHCP_allocated_ip[0]; - OLD_allocated_ip[1] = DHCP_allocated_ip[1]; - OLD_allocated_ip[2] = DHCP_allocated_ip[2]; - OLD_allocated_ip[3] = DHCP_allocated_ip[3]; - - DHCP_XID++; - - send_DHCP_REQUEST(); - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_REREQUEST; - } - break; - - case STATE_DHCP_REREQUEST : - ret = DHCP_IP_LEASED; - if (type == DHCP_ACK) { - dhcp_retry_count = 0; - if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] || - OLD_allocated_ip[1] != DHCP_allocated_ip[1] || - OLD_allocated_ip[2] != DHCP_allocated_ip[2] || - OLD_allocated_ip[3] != DHCP_allocated_ip[3]) - { - ret = DHCP_IP_CHANGED; - dhcp_ip_update(); - #ifdef _DHCP_DEBUG_ - printf(">IP changed.\r\n"); - #endif - - } - #ifdef _DHCP_DEBUG_ - else printf(">IP is continued.\r\n"); - #endif - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_LEASED; - } else if (type == DHCP_NAK) { - -#ifdef _DHCP_DEBUG_ - printf("> Receive DHCP_NACK, Failed to maintain ip\r\n"); -#endif - - reset_DHCP_timeout(); - - dhcp_state = STATE_DHCP_DISCOVER; - } else ret = check_DHCP_timeout(); - break; - default : - break; - } - - return ret; -} - -void DHCP_stop(void) -{ - close(DHCP_SOCKET); - dhcp_state = STATE_DHCP_STOP; -} - -uint8_t check_DHCP_timeout(void) -{ - uint8_t ret = DHCP_RUNNING; - - if (dhcp_retry_count < MAX_DHCP_RETRY) { - if (dhcp_tick_next < dhcp_tick_1s) { - - switch ( dhcp_state ) { - case STATE_DHCP_DISCOVER : -// printf("<> state : STATE_DHCP_DISCOVER\r\n"); - send_DHCP_DISCOVER(); - break; - - case STATE_DHCP_REQUEST : -// printf("<> state : STATE_DHCP_REQUEST\r\n"); - - send_DHCP_REQUEST(); - break; - - case STATE_DHCP_REREQUEST : -// printf("<> state : STATE_DHCP_REREQUEST\r\n"); - - send_DHCP_REQUEST(); - break; - - default : - break; - } - - dhcp_tick_1s = 0; - dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME; - dhcp_retry_count++; - } - } else { // timeout occurred - - switch(dhcp_state) { - case STATE_DHCP_DISCOVER: - dhcp_state = STATE_DHCP_INIT; - ret = DHCP_FAILED; - break; - case STATE_DHCP_REQUEST: - case STATE_DHCP_REREQUEST: - send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; - break; - default : - break; - } - reset_DHCP_timeout(); - } - return ret; -} - -int8_t check_DHCP_leasedIP(void) -{ - uint8_t tmp; - int32_t ret; - - //WIZchip RCR value changed for ARP Timeout count control - tmp = getRCR(); - setRCR(0x03); - - // IP conflict detection : ARP request - ARP reply - // Broadcasting ARP Request for check the IP conflict using UDP sendto() function - ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); - - // RCR value restore - setRCR(tmp); - - if(ret == SOCKERR_TIMEOUT) { - // UDP send Timeout occurred : allocated IP address is unique, DHCP Success - -#ifdef _DHCP_DEBUG_ - printf("\r\n> Check leased IP - OK\r\n"); -#endif - - return 1; - } else { - // Received ARP reply or etc : IP address conflict occur, DHCP Failed - send_DHCP_DECLINE(); - - ret = dhcp_tick_1s; - while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message; - - return 0; - } -} - -void DHCP_init(uint8_t s, uint8_t * buf) -{ - uint8_t zeroip[4] = {0,0,0,0}; - getSHAR(DHCP_CHADDR); - if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00) - { - // assign temporary mac address, you should be set SHAR before call this function. - DHCP_CHADDR[0] = 0x00; - DHCP_CHADDR[1] = 0x08; - DHCP_CHADDR[2] = 0xdc; - DHCP_CHADDR[3] = 0x00; - DHCP_CHADDR[4] = 0x00; - DHCP_CHADDR[5] = 0x00; - setSHAR(DHCP_CHADDR); - } - - DHCP_SOCKET = s; // SOCK_DHCP - pDHCPMSG = (RIP_MSG*)buf; - DHCP_XID = 0x12345678; - - // WIZchip Netinfo Clear - setSIPR(zeroip); - setSIPR(zeroip); - setGAR(zeroip); - - reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_INIT; -} - - -/* Rset the DHCP timeout count and retry count. */ -void reset_DHCP_timeout(void) -{ - dhcp_tick_1s = 0; - dhcp_tick_next = DHCP_WAIT_TIME; - dhcp_retry_count = 0; -} - -void DHCP_time_handler(void) -{ - dhcp_tick_1s++; -} - -void getIPfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_ip[0]; - ip[1] = DHCP_allocated_ip[1]; - ip[2] = DHCP_allocated_ip[2]; - ip[3] = DHCP_allocated_ip[3]; -} - -void getGWfromDHCP(uint8_t* ip) -{ - ip[0] =DHCP_allocated_gw[0]; - ip[1] =DHCP_allocated_gw[1]; - ip[2] =DHCP_allocated_gw[2]; - ip[3] =DHCP_allocated_gw[3]; -} - -void getSNfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_sn[0]; - ip[1] = DHCP_allocated_sn[1]; - ip[2] = DHCP_allocated_sn[2]; - ip[3] = DHCP_allocated_sn[3]; -} - -void getDNSfromDHCP(uint8_t* ip) -{ - ip[0] = DHCP_allocated_dns[0]; - ip[1] = DHCP_allocated_dns[1]; - ip[2] = DHCP_allocated_dns[2]; - ip[3] = DHCP_allocated_dns[3]; -} - -uint32_t getDHCPLeasetime(void) -{ - return dhcp_lease_time; -} - - - - diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dhcp/dhcp.h b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dhcp/dhcp.h deleted file mode 100644 index ee154d50..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dhcp/dhcp.h +++ /dev/null @@ -1,150 +0,0 @@ -//***************************************************************************** -// -//! \file dhcp.h -//! \brief DHCP APIs Header file. -//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/11/18> 1st Release -//! <2012/12/20> V1.1.0 -//! 1. Move unreferenced DEFINE to dhcp.c -//! <2012/12/26> V1.1.1 -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** -#ifndef _DHCP_H_ -#define _DHCP_H_ - -/* - * @brief - * @details If you want to display debug & processing message, Define _DHCP_DEBUG_ - * @note If defined, it depends on - */ - -//#define _DHCP_DEBUG_ - -/* Retry to processing DHCP */ -#define MAX_DHCP_RETRY 2 ///< Maximum retry count -#define DHCP_WAIT_TIME 10 ///< Wait Time 10s - -/* UDP port numbers for DHCP */ -#define DHCP_SERVER_PORT 67 ///< DHCP server port number -#define DHCP_CLIENT_PORT 68 ///< DHCP client port number - -#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number - -#define DCHP_HOST_NAME "WIZnet\0" - -/* - * @brief return value of @ref DHCP_run() - */ -enum -{ - DHCP_FAILED = 0, ///< Processing Fail - DHCP_RUNNING, ///< Processing DHCP protocol - DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) - DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update) - DHCP_IP_LEASED, ///< Stand by - DHCP_STOPPED ///< Stop processing DHCP protocol -}; - -/* - * @brief DHCP client initialization (outside of the main loop) - * @param s - socket number - * @param buf - buffer for processing DHCP message - */ -void DHCP_init(uint8_t s, uint8_t * buf); - -/* - * @brief DHCP 1s Tick Timer handler - * @note SHOULD BE register to your system 1s Tick timer handler - */ -void DHCP_time_handler(void); - -/* - * @brief Register call back function - * @param ip_assign - callback func when IP is assigned from DHCP server first - * @param ip_update - callback func when IP is changed - * @prarm ip_conflict - callback func when the assigned IP is conflict with others. - */ -void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); - -/* - * @brief DHCP client in the main loop - * @return The value is as the follow \n - * @ref DHCP_FAILED \n - * @ref DHCP_RUNNING \n - * @ref DHCP_IP_ASSIGN \n - * @ref DHCP_IP_CHANGED \n - * @ref DHCP_IP_LEASED \n - * @ref DHCP_STOPPED \n - * - * @note This function is always called by you main task. - */ -uint8_t DHCP_run(void); - -/* - * @brief Stop DHCP processing - * @note If you want to restart. call DHCP_init() and DHCP_run() - */ -void DHCP_stop(void); - -/* Get Network information assigned from DHCP server */ -/* - * @brief Get IP address - * @param ip - IP address to be returned - */ -void getIPfromDHCP(uint8_t* ip); -/* - * @brief Get Gateway address - * @param ip - Gateway address to be returned - */ -void getGWfromDHCP(uint8_t* ip); -/* - * @brief Get Subnet mask value - * @param ip - Subnet mask to be returned - */ -void getSNfromDHCP(uint8_t* ip); -/* - * @brief Get DNS address - * @param ip - DNS address to be returned - */ -void getDNSfromDHCP(uint8_t* ip); - -/* - * @brief Get the leased time by DHCP sever - * @return unit 1s - */ -uint32_t getDHCPLeasetime(void); - -#endif /* _DHCP_H_ */ diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dns/dns.c b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dns/dns.c deleted file mode 100644 index c0ad570c..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dns/dns.c +++ /dev/null @@ -1,566 +0,0 @@ -//***************************************************************************** -// -//! \file dns.c -//! \brief DNS APIs Implement file. -//! \details Send DNS query & Receive DNS reponse. \n -//! It depends on stdlib.h & string.h in ansi-c library -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.1.0 -//! 1. Remove secondary DNS server in DNS_run -//! If 1st DNS_run failed, call DNS_run with 2nd DNS again -//! 2. DNS_timerHandler -> DNS_time_handler -//! 3. Remove the unused define -//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c -//! <2013/12/20> V1.1.0 -//! -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#include -#include - -//#include "Ethernet/socket.h" -//#include "Internet/DNS/dns.h" -#include "../../ethernet/socket.h" -#include "dns.h" - -#ifdef _DNS_DEBUG_ - #include -#endif - -#define INITRTT 2000L /* Initial smoothed response time */ -#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */ - -#define TYPE_A 1 /* Host address */ -#define TYPE_NS 2 /* Name server */ -#define TYPE_MD 3 /* Mail destination (obsolete) */ -#define TYPE_MF 4 /* Mail forwarder (obsolete) */ -#define TYPE_CNAME 5 /* Canonical name */ -#define TYPE_SOA 6 /* Start of Authority */ -#define TYPE_MB 7 /* Mailbox name (experimental) */ -#define TYPE_MG 8 /* Mail group member (experimental) */ -#define TYPE_MR 9 /* Mail rename name (experimental) */ -#define TYPE_NULL 10 /* Null (experimental) */ -#define TYPE_WKS 11 /* Well-known sockets */ -#define TYPE_PTR 12 /* Pointer record */ -#define TYPE_HINFO 13 /* Host information */ -#define TYPE_MINFO 14 /* Mailbox information (experimental)*/ -#define TYPE_MX 15 /* Mail exchanger */ -#define TYPE_TXT 16 /* Text strings */ -#define TYPE_ANY 255 /* Matches any type */ - -#define CLASS_IN 1 /* The ARPA Internet */ - -/* Round trip timing parameters */ -#define AGAIN 8 /* Average RTT gain = 1/8 */ -#define LAGAIN 3 /* Log2(AGAIN) */ -#define DGAIN 4 /* Mean deviation gain = 1/4 */ -#define LDGAIN 2 /* log2(DGAIN) */ - -/* Header for all domain messages */ -struct dhdr -{ - uint16_t id; /* Identification */ - uint8_t qr; /* Query/Response */ -#define QUERY 0 -#define RESPONSE 1 - uint8_t opcode; -#define IQUERY 1 - uint8_t aa; /* Authoratative answer */ - uint8_t tc; /* Truncation */ - uint8_t rd; /* Recursion desired */ - uint8_t ra; /* Recursion available */ - uint8_t rcode; /* Response code */ -#define NO_ERROR 0 -#define FORMAT_ERROR 1 -#define SERVER_FAIL 2 -#define NAME_ERROR 3 -#define NOT_IMPL 4 -#define REFUSED 5 - uint16_t qdcount; /* Question count */ - uint16_t ancount; /* Answer count */ - uint16_t nscount; /* Authority (name server) count */ - uint16_t arcount; /* Additional record count */ -}; - - -uint8_t* pDNSMSG; // DNS message buffer -uint8_t DNS_SOCKET; // SOCKET number for DNS -uint16_t DNS_MSGID; // DNS message ID - -extern uint32_t HAL_GetTick(void); -uint32_t hal_sys_tick; - -/* converts uint16_t from network buffer to a host byte order integer. */ -uint16_t get16(uint8_t * s) -{ - uint16_t i; - i = *s++ << 8; - i = i + *s; - return i; -} - -/* copies uint16_t to the network buffer with network byte order. */ -uint8_t * put16(uint8_t * s, uint16_t i) -{ - *s++ = i >> 8; - *s++ = i; - return s; -} - - -/* - * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM - * - * Description : This function converts a compressed domain name to the human-readable form - * Arguments : msg - is a pointer to the reply message - * compressed - is a pointer to the domain name in reply message. - * buf - is a pointer to the buffer for the human-readable form name. - * len - is the MAX. size of buffer. - * Returns : the length of compressed message - */ -int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len) -{ - uint16_t slen; /* Length of current segment */ - uint8_t * cp; - int clen = 0; /* Total length of compressed name */ - int indirect = 0; /* Set if indirection encountered */ - int nseg = 0; /* Total number of segments in name */ - - cp = compressed; - - for (;;) - { - slen = *cp++; /* Length of this segment */ - - if (!indirect) clen++; - - if ((slen & 0xc0) == 0xc0) - { - if (!indirect) - clen++; - indirect = 1; - /* Follow indirection */ - cp = &msg[((slen & 0x3f)<<8) + *cp]; - slen = *cp++; - } - - if (slen == 0) /* zero length == all done */ - break; - - len -= slen + 1; - - if (len < 0) return -1; - - if (!indirect) clen += slen; - - while (slen-- != 0) *buf++ = (char)*cp++; - *buf++ = '.'; - nseg++; - } - - if (nseg == 0) - { - /* Root name; represent as single dot */ - *buf++ = '.'; - len--; - } - - *buf++ = '\0'; - len--; - - return clen; /* Length of compressed message */ -} - -/* - * PARSE QUESTION SECTION - * - * Description : This function parses the question record of the reply message. - * Arguments : msg - is a pointer to the reply message - * cp - is a pointer to the question record. - * Returns : a pointer the to next record. - */ -uint8_t * dns_question(uint8_t * msg, uint8_t * cp) -{ - int len; - char name[MAXCNAME]; - - len = parse_name(msg, cp, name, MAXCNAME); - - - if (len == -1) return 0; - - cp += len; - cp += 2; /* type */ - cp += 2; /* class */ - - return cp; -} - - -/* - * PARSE ANSER SECTION - * - * Description : This function parses the answer record of the reply message. - * Arguments : msg - is a pointer to the reply message - * cp - is a pointer to the answer record. - * Returns : a pointer the to next record. - */ -uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns) -{ - int len, type; - char name[MAXCNAME]; - - len = parse_name(msg, cp, name, MAXCNAME); - - if (len == -1) return 0; - - cp += len; - type = get16(cp); - cp += 2; /* type */ - cp += 2; /* class */ - cp += 4; /* ttl */ - cp += 2; /* len */ - - - switch (type) - { - case TYPE_A: - /* Just read the address directly into the structure */ - ip_from_dns[0] = *cp++; - ip_from_dns[1] = *cp++; - ip_from_dns[2] = *cp++; - ip_from_dns[3] = *cp++; - break; - case TYPE_CNAME: - case TYPE_MB: - case TYPE_MG: - case TYPE_MR: - case TYPE_NS: - case TYPE_PTR: - /* These types all consist of a single domain name */ - /* convert it to ASCII format */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - break; - case TYPE_HINFO: - len = *cp++; - cp += len; - - len = *cp++; - cp += len; - break; - case TYPE_MX: - cp += 2; - /* Get domain name of exchanger */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - break; - case TYPE_SOA: - /* Get domain name of name server */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - - /* Get domain name of responsible person */ - len = parse_name(msg, cp, name, MAXCNAME); - if (len == -1) return 0; - - cp += len; - - cp += 4; - cp += 4; - cp += 4; - cp += 4; - cp += 4; - break; - case TYPE_TXT: - /* Just stash */ - break; - default: - /* Ignore */ - break; - } - - return cp; -} - -/* - * PARSE THE DNS REPLY - * - * Description : This function parses the reply message from DNS server. - * Arguments : dhdr - is a pointer to the header for DNS message - * buf - is a pointer to the reply message. - * len - is the size of reply message. - * Returns : -1 - Domain name length is too big - * 0 - Fail (Timeout or parse error) - * 1 - Success, - */ -int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns) -{ - uint16_t tmp; - uint16_t i; - uint8_t * msg; - uint8_t * cp; - - msg = pbuf; - memset(pdhdr, 0, sizeof(*pdhdr)); - - pdhdr->id = get16(&msg[0]); - tmp = get16(&msg[2]); - if (tmp & 0x8000) pdhdr->qr = 1; - - pdhdr->opcode = (tmp >> 11) & 0xf; - - if (tmp & 0x0400) pdhdr->aa = 1; - if (tmp & 0x0200) pdhdr->tc = 1; - if (tmp & 0x0100) pdhdr->rd = 1; - if (tmp & 0x0080) pdhdr->ra = 1; - - pdhdr->rcode = tmp & 0xf; - pdhdr->qdcount = get16(&msg[4]); - pdhdr->ancount = get16(&msg[6]); - pdhdr->nscount = get16(&msg[8]); - pdhdr->arcount = get16(&msg[10]); - - - /* Now parse the variable length sections */ - cp = &msg[12]; - - /* Question section */ - for (i = 0; i < pdhdr->qdcount; i++) - { - cp = dns_question(msg, cp); - if(!cp) - { -#ifdef _DNS_DEBUG_ - printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); -#endif - return -1; - } - } - - /* Answer section */ - for (i = 0; i < pdhdr->ancount; i++) - { - cp = dns_answer(msg, cp, ip_from_dns); - if(!cp) - { -#ifdef _DNS_DEBUG_ - printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); -#endif - return -1; - } - - } - - /* Name server (authority) section */ - for (i = 0; i < pdhdr->nscount; i++) - { - ; - } - - /* Additional section */ - for (i = 0; i < pdhdr->arcount; i++) - { - ; - } - - if(pdhdr->rcode == 0) return 1; // No error - else return 0; -} - - -/* - * MAKE DNS QUERY MESSAGE - * - * Description : This function makes DNS query message. - * Arguments : op - Recursion desired - * name - is a pointer to the domain name. - * buf - is a pointer to the buffer for DNS message. - * len - is the MAX. size of buffer. - * Returns : the pointer to the DNS message. - */ -int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len) -{ - uint8_t *cp; - char *cp1; - char sname[MAXCNAME]; - char *dname; - uint16_t p; - uint16_t dlen; - - cp = buf; - - DNS_MSGID++; - cp = put16(cp, DNS_MSGID); - p = (op << 11) | 0x0100; /* Recursion desired */ - cp = put16(cp, p); - cp = put16(cp, 1); - cp = put16(cp, 0); - cp = put16(cp, 0); - cp = put16(cp, 0); - - strcpy(sname, name); - dname = sname; - dlen = strlen(dname); - for (;;) - { - /* Look for next dot */ - cp1 = strchr(dname, '.'); - - if (cp1 != NULL) len = cp1 - dname; /* More to come */ - else len = dlen; /* Last component */ - - *cp++ = len; /* Write length of component */ - if (len == 0) break; - - /* Copy component up to (but not including) dot */ - memcpy(cp, dname, len); - cp += len; - if (cp1 == NULL) - { - *cp++ = 0; /* Last one; write null and finish */ - break; - } - dname += len+1; - dlen -= len+1; - } - - cp = put16(cp, 0x0001); /* type */ - cp = put16(cp, 0x0001); /* class */ - - return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf))); -} - -/* - * CHECK DNS TIMEOUT - * - * Description : This function check the DNS timeout - * Arguments : None. - * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur - * Note : timeout : retry count and timer both over. - */ - -int8_t check_DNS_timeout(void) -{ - static uint8_t retry_count; - - uint32_t tick = HAL_GetTick(); - if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000) - { - hal_sys_tick = tick; - if(retry_count >= MAX_DNS_RETRY) { - retry_count = 0; - return -1; // timeout occurred - } - retry_count++; - return 0; // timer over, but no timeout - } - - return 1; // no timer over, no timeout occur -} - - - -/* DNS CLIENT INIT */ -void DNS_init(uint8_t s, uint8_t * buf) -{ - DNS_SOCKET = s; // SOCK_DNS - pDNSMSG = buf; // User's shared buffer - DNS_MSGID = DNS_MSG_ID; -} - -/* DNS CLIENT RUN */ -int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns) -{ - int8_t ret; - struct dhdr dhp; - uint8_t ip[4]; - uint16_t len, port; - int8_t ret_check_timeout; - - hal_sys_tick = HAL_GetTick(); - - // Socket open - WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0); - -#ifdef _DNS_DEBUG_ - printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); -#endif - - len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE); - WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); - - while (1) - { - if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0) - { - if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE; - len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port); - #ifdef _DNS_DEBUG_ - printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len); - #endif - ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns); - break; - } - // Check Timeout - ret_check_timeout = check_DNS_timeout(); - if (ret_check_timeout < 0) { - -#ifdef _DNS_DEBUG_ - printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); -#endif - return 0; // timeout occurred - } - else if (ret_check_timeout == 0) { - -#ifdef _DNS_DEBUG_ - printf("> DNS Timeout\r\n"); -#endif - WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); - } - } - WIZCHIP_EXPORT(close)(DNS_SOCKET); - // Return value - // 0 > : failed / 1 - success - return ret; -} diff --git a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dns/dns.h b/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dns/dns.h deleted file mode 100644 index de003951..00000000 --- a/MicroPython_BUILD/components/micropython/drivers/wiznet5k/internet/dns/dns.h +++ /dev/null @@ -1,96 +0,0 @@ -//***************************************************************************** -// -//! \file dns.h -//! \brief DNS APIs Header file. -//! \details Send DNS query & Receive DNS reponse. -//! \version 1.1.0 -//! \date 2013/11/18 -//! \par Revision history -//! <2013/10/21> 1st Release -//! <2013/12/20> V1.1.0 -//! 1. Remove secondary DNS server in DNS_run -//! If 1st DNS_run failed, call DNS_run with 2nd DNS again -//! 2. DNS_timerHandler -> DNS_time_handler -//! 3. Move the no reference define to dns.c -//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c -//! <2013/12/20> V1.1.0 -//! -//! \author Eric Jung & MidnightCow -//! \copyright -//! -//! Copyright (c) 2013, WIZnet Co., LTD. -//! All rights reserved. -//! -//! Redistribution and use in source and binary forms, with or without -//! modification, are permitted provided that the following conditions -//! are met: -//! -//! * Redistributions of source code must retain the above copyright -//! notice, this list of conditions and the following disclaimer. -//! * Redistributions in binary form must reproduce the above copyright -//! notice, this list of conditions and the following disclaimer in the -//! documentation and/or other materials provided with the distribution. -//! * Neither the name of the nor the names of its -//! contributors may be used to endorse or promote products derived -//! from this software without specific prior written permission. -//! -//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -//! THE POSSIBILITY OF SUCH DAMAGE. -// -//***************************************************************************** - -#ifndef _DNS_H_ -#define _DNS_H_ - -#include -/* - * @brief Define it for Debug & Monitor DNS processing. - * @note If defined, it depends on - */ - -//#define _DNS_DEBUG_ - -#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ -/* - * @brief Maximum length of your queried Domain name - * @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1) - * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack. - */ -#define MAX_DOMAIN_NAME 32 // for example "www.google.com" - -#define MAX_DNS_RETRY 2 ///< Requery Count -#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s. - -#define IPPORT_DOMAIN 53 ///< DNS server port number - -#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number -/* - * @brief DNS process initialize - * @param s : Socket number for DNS - * @param buf : Buffer for DNS message - */ -void DNS_init(uint8_t s, uint8_t * buf); - -/* - * @brief DNS process - * @details Send DNS query and receive DNS response - * @param dns_ip : DNS server ip address - * @param name : Domain name to be queried - * @param ip_from_dns : IP address from DNS server - * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n - * 0 : failed (Timeout or Parse error)\n - * 1 : success - * @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME - */ -int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns); - -#endif /* _DNS_H_ */ diff --git a/MicroPython_BUILD/components/micropython/esp32/bluetooth_le.c b/MicroPython_BUILD/components/micropython/esp32/bluetooth_le.c index 87d7a6cc..17d7b8f3 100644 --- a/MicroPython_BUILD/components/micropython/esp32/bluetooth_le.c +++ b/MicroPython_BUILD/components/micropython/esp32/bluetooth_le.c @@ -41,11 +41,11 @@ #include "py/runtime0.h" // IDF -#include "bt.h" -#include "esp_bt_main.h" -#include "esp_gap_ble_api.h" -#include "esp_gatts_api.h" -#include "esp_gattc_api.h" +#include "esp_bt.h" +#include "api/esp_bt_main.h" +#include "api/esp_gap_ble_api.h" +#include "api/esp_gatts_api.h" +#include "api/esp_gattc_api.h" //extern bool bluetooth_enabled; @@ -438,8 +438,8 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT: { PRINT_STATUS(param->adv_data_cmpl.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", rssi = %d, bda = %02X:%02X:%02X:%02X:%02X:%02X", + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", rssi = %d, bda = %02X:%02X:%02X:%02X:%02X:%02X", param->read_rssi_cmpl.rssi, param->read_rssi_cmpl.remote_addr[0], param->read_rssi_cmpl.remote_addr[1], @@ -453,7 +453,7 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t case ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT: { PRINT_STATUS(param->adv_data_cmpl.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( + NETWORK_BLUETOOTH_DEBUG_PRINTF( ", wl_opration = %s", param->update_whitelist_cmpl.wl_opration == ESP_BLE_WHITELIST_ADD ? "ADD" : "REMOVE"); diff --git a/MicroPython_BUILD/components/micropython/esp32/gccollect.c b/MicroPython_BUILD/components/micropython/esp32/gccollect.c index 8b6e570a..d8f0f333 100644 --- a/MicroPython_BUILD/components/micropython/esp32/gccollect.c +++ b/MicroPython_BUILD/components/micropython/esp32/gccollect.c @@ -38,28 +38,67 @@ #include "soc/cpu.h" #include "xtensa/hal.h" +static int n_marked; -static void gc_collect_inner(int level) { +static void gc_collect_inner(int level, int flag) +{ if (level < XCHAL_NUM_AREGS / 8) { - gc_collect_inner(level + 1); + gc_collect_inner(level + 1, flag); if (level != 0) { return; } } if (level == XCHAL_NUM_AREGS / 8) { - // get the sp + n_marked = MP_STATE_MEM(gc_marked); + + // get the stack pointer volatile uint32_t sp = (uint32_t)get_sp(); - gc_collect_root((void**)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); + gc_collect_root((void**)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); + + if ((flag) && ((MP_STATE_MEM(gc_marked) - n_marked) > 0)) printf("gc_collect: marked on stack: %d (%p - %p)\n", MP_STATE_MEM(gc_marked) - n_marked, (void *)sp, (void *)MP_STATE_THREAD(stack_top)); return; } - // trace root pointers from any threads - mp_thread_gc_others(); + // Trace root pointers from other threads + int n_marked = MP_STATE_MEM(gc_marked); + + mp_thread_gc_others(flag); + + if ((flag) && ((MP_STATE_MEM(gc_marked) - n_marked) > 0)) printf("gc_collect: marked on others: %d\n", MP_STATE_MEM(gc_marked) - n_marked); } -void gc_collect(void) { - gc_collect_start(); - gc_collect_inner(0); - gc_collect_end(); +//----------------------- +void gc_collect(int flag) +{ + char *th_name = NULL; + if (flag) { + char thname[THREAD_NAME_MAX_SIZE+1]; + th_name = thname; + mp_thread_getSelfname(th_name); + } + if (flag > 1) gc_dump_alloc_table(); + + // Trace root pointers. + gc_collect_start(); + if (flag) printf("gc_collect: marked on START: %d (th='%s')\n", MP_STATE_MEM(gc_marked), th_name); + + // ---- Collect inner ------------------------------------------------------- + gc_collect_inner(0, flag); + + if (flag > 1) { + mp_thread_mutex_unlock(&(mp_state_ctx.mem.gc_mutex)); + gc_dump_alloc_table(); + mp_thread_mutex_lock(&(mp_state_ctx.mem.gc_mutex), 1); + } + + n_marked = MP_STATE_MEM(gc_marked); + + gc_collect_end(); + + if (flag) { + if ((MP_STATE_MEM(gc_marked) - n_marked) > 0) printf("gc_collect: marked on end: %d\n", MP_STATE_MEM(gc_marked) - n_marked); + printf("gc_collect: marked total: %d; collected: %d\n", MP_STATE_MEM(gc_marked), MP_STATE_MEM(gc_collected)); + } + if (flag > 1) gc_dump_alloc_table(); } diff --git a/MicroPython_BUILD/components/micropython/esp32/gccollect.h b/MicroPython_BUILD/components/micropython/esp32/gccollect.h index d8b49bbe..7d3e1fe0 100644 --- a/MicroPython_BUILD/components/micropython/esp32/gccollect.h +++ b/MicroPython_BUILD/components/micropython/esp32/gccollect.h @@ -40,4 +40,4 @@ extern uint32_t _bss_end; extern uint32_t _heap_start; extern uint32_t _heap_end; -void gc_collect(void); +void gc_collect(int flag); diff --git a/MicroPython_BUILD/components/micropython/esp32/help.c b/MicroPython_BUILD/components/micropython/esp32/help.c index 7751797a..e7fe4067 100644 --- a/MicroPython_BUILD/components/micropython/esp32/help.c +++ b/MicroPython_BUILD/components/micropython/esp32/help.c @@ -1,11 +1,12 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * Development of the code in this file was sponsored by Microbric Pty Ltd * * The MIT License (MIT) * * Copyright (c) 2013-2016 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,36 +28,24 @@ */ #include "py/builtin.h" -#include "sdkconfig.h" const char esp32_help_text[] = -#if CONFIG_SPIRAM_SUPPORT -"Welcome to LoBo MicroPython on the ESP32 with psRAM!\n" -#else -"Welcome to LoBo MicroPython on the ESP32!\n" -#endif +"Welcome to LoBo MicroPython for the ESP32\n" "\n" -"For online documentation please visit:\nhttps://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki\n" +"For online documentation please visit the Wiki pages:\n" +"https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki\n" "\n" -"For access to the hardware use the 'machine' module:\n" +"Based on official MicroPython, this port brings many new features:\n" "\n" -"import machine\n" -"pin12 = machine.Pin(12, machine.Pin.OUT)\n" -"pin12.value(1)\n" -"pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)\n" -"print(pin13.value())\n" -"i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))\n" -"i2c.scan()\n" -"i2c.writeto(addr, b'1234')\n" -"i2c.readfrom(addr, 4)\n" -"\n" -"Basic WiFi configuration:\n" -"\n" -"import network\n" -"sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n" -"sta_if.scan() # Scan for available access points\n" -"sta_if.connect(\"\", \"\") # Connect to an AP\n" -"sta_if.isconnected() # Check for successful connection\n" +" - support for two cores and 4MB SPIRAM (psRAM)\n" +" - improved 'network' module\n" +" - greatly improved thread support\n" +" - support for 3 different internal file systems on top of ESP32 VFS\n" +" - ESP32 native support for SD Card\n" +" - built-in FTP & Telnet servers\n" +" - support for OTA updates\n" +" - many new and improved hardware access modules implemented in C\n" +" and many more...\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/curl_mail.c b/MicroPython_BUILD/components/micropython/esp32/libs/curl_mail.c new file mode 100644 index 00000000..d95f0980 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/curl_mail.c @@ -0,0 +1,658 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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 "sdkconfig.h" + +#if defined(CONFIG_MICROPY_USE_CURL) + +#include "libs/curl_mail.h" +#include +#include +#include +#include +#include +#include +#include + +#include "esp_log.h" +#include "libs/espcurl.h" +#include "py/mpthread.h" + +#define CRLF "\r\n" +#define CRLFLENGTH 2 + +#define MIME_LINE_MAX_WIDTH 992 + +// Constants defining the email send state +#define SEND_MAIL_STATE_INITIALIZE 0 +#define SEND_MAIL_STATE_HEADER 1 +#define SEND_MAIL_STATE_BODY 2 +#define SEND_MAIL_STATE_BODY_DONE 3 +#define SEND_MAIL_STATE_ATTACHMENT 4 +#define SEND_MAIL_STATE_END 5 +#define SEND_MAIL_STATE_DONE 6 + +static const char* default_mime_type = "text/plain"; +static const char *MAIL_TAG = "[Curl_mail]"; +static const char* MEMORY_ALLOCATION_ERROR = "Error allocating memory"; +// ---- Base64 Encoding/Decoding Table --- +static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +//--------------- +struct progress { + double lastruntime; + CURL *curl; +}; + +//----------------------- +struct email_attachment { + char* filename; + char* mimetype; + FILE *handle; +}; + +//------------------------ +struct email_info_struct { + int state; + time_t timestamp; + char *from; + char *to; + char *cc; + char *bcc; + char *subject; + char *header; + char *body; + struct email_attachment* attachment[CURLMAIL_MAX_ATTACHMENTS]; + int num_attach; + char *buf; + int buflen; + char *boundary_body; + char *boundary_attach; +}; + + +//----------------------------------------- +static char* populate_boundary (char* data) +{ + //replace all 0s in string with random digits + char* p = data; + while (*p) { + if (*p == '0') *p = '0' + rand() % 10; + p++; + } + return data; +} + +//--------------------------------------------------------- +char* append_to_string (char** in_str, const char* app_str) +{ + //append a string to the end of an existing string + int len = (*in_str ? strlen(*in_str) : 0); + char *p = (char*)realloc(*in_str, len + strlen(app_str) + 1); + if (p == NULL) { + free(p); + ESP_LOGE(MAIL_TAG, "%s", MEMORY_ALLOCATION_ERROR); + return NULL; + } + *in_str = p; + strcpy(*in_str + len, app_str); + return *in_str; +} + +//-------------------------------------------------------------- +curl_mail curlmail_create(const char* from, const char* subject) +{ + struct email_info_struct* mail_object; + if ((mail_object = (struct email_info_struct*)malloc(sizeof(struct email_info_struct))) == NULL) { + ESP_LOGE(MAIL_TAG, "%s", MEMORY_ALLOCATION_ERROR); + return NULL; + } + + mail_object->state = 0; + mail_object->timestamp = time(NULL); + mail_object->from = NULL; + if (from) { + append_to_string(&mail_object->from, "<"); + append_to_string(&mail_object->from, from); + append_to_string(&mail_object->from, ">"); + } + mail_object->to = NULL; + mail_object->cc = NULL; + mail_object->bcc = NULL; + mail_object->subject = (subject ? strdup(subject) : NULL); + mail_object->header = NULL; + mail_object->body = NULL; + for (int n=0; n < CURLMAIL_MAX_ATTACHMENTS; n++) { + mail_object->attachment[n] = NULL; + } + mail_object->num_attach = 0; + mail_object->buf = NULL; + mail_object->buflen = 0; + mail_object->boundary_body = NULL; + mail_object->boundary_attach = NULL; + + srand(time(NULL)); + return mail_object; +} + +//------------------------------------------------------------------ +static void curlmail_free_attachment(curl_mail mail_object, int idx) +{ + if (mail_object->attachment[idx]) { + if (mail_object->attachment[idx]->filename) { + free(mail_object->attachment[idx]->filename); + mail_object->attachment[idx]->filename = NULL; + } + if (mail_object->attachment[idx]->mimetype) { + free(mail_object->attachment[idx]->mimetype); + mail_object->attachment[idx]->mimetype = NULL; + } + free(mail_object->attachment[idx]); + mail_object->attachment[idx] = NULL; + } +} + +//------------------------------------------ +void curlmail_destroy(curl_mail mail_object) +{ + if (mail_object->from) free(mail_object->from); + if (mail_object->to) free(mail_object->to); + if (mail_object->cc) free(mail_object->cc); + if (mail_object->bcc) free(mail_object->bcc); + if (mail_object->subject) free(mail_object->subject); + if (mail_object->header) free(mail_object->header); + if (mail_object->body) free(mail_object->body); + if (mail_object->buf) free(mail_object->buf); + if (mail_object->boundary_body) free(mail_object->boundary_body); + if (mail_object->boundary_attach) free(mail_object->boundary_attach); + for (int n=0; n < mail_object->num_attach; n++) { + curlmail_free_attachment(mail_object, n); + } + free(mail_object); +} + +//---------------------------------------------------------------- +void curlmail_add_to(curl_mail mail_object, const char* mail_addr) +{ + if ((mail_addr == NULL) || (*mail_addr == '\0')) return; + if (mail_object->to) { + append_to_string(&mail_object->to, ", <"); + } + else { + append_to_string(&mail_object->to, "<"); + } + append_to_string(&mail_object->to, mail_addr); + append_to_string(&mail_object->to, ">"); +} + +//---------------------------------------------------------------- +void curlmail_add_cc(curl_mail mail_object, const char* mail_addr) +{ + if ((mail_addr == NULL) || (*mail_addr == '\0')) return; + if (mail_object->cc) { + append_to_string(&mail_object->cc, ", <"); + } + else { + append_to_string(&mail_object->cc, "<"); + } + append_to_string(&mail_object->cc, mail_addr); + append_to_string(&mail_object->cc, ">"); +} + +//----------------------------------------------------------------- +void curlmail_add_bcc(curl_mail mail_object, const char* mail_addr) +{ + if ((mail_addr == NULL) || (*mail_addr == '\0')) return; + if (mail_object->bcc) { + append_to_string(&mail_object->bcc, ", <"); + } + else { + append_to_string(&mail_object->bcc, "<"); + } + append_to_string(&mail_object->bcc, mail_addr); + append_to_string(&mail_object->bcc, ">"); +} + +//------------------------------------------------------------------- +void curlmail_set_subject(curl_mail mail_object, const char* subject) +{ + if (mail_object->subject) free(mail_object->subject); + mail_object->subject = (subject ? strdup(subject) : NULL); +} + +//--------------------------------------------------------------------- +void curlmail_add_header(curl_mail mail_object, const char* headerline) +{ + append_to_string(&mail_object->header, headerline); + append_to_string(&mail_object->header, CRLF); +} + +//--------------------------------------------------------------- +void curlmail_set_body (curl_mail mail_object, const char* body) +{ + if (mail_object->body) free(mail_object->body); + mail_object->body = (body ? strdup(body) : NULL); +} + +//---------------------------------------------------------------------------------------------- +void curlmail_add_attachment_file(curl_mail mail_object, const char* path, const char* mimetype) +{ + if (mail_object->num_attach >= CURLMAIL_MAX_ATTACHMENTS) return; + + mail_object->attachment[mail_object->num_attach] = (struct email_attachment*)malloc(sizeof(struct email_attachment)); + if (mail_object->attachment[mail_object->num_attach]) { + mail_object->attachment[mail_object->num_attach]->handle = NULL; + + mail_object->attachment[mail_object->num_attach]->filename = malloc(strlen(path)+1); + if (mail_object->attachment[mail_object->num_attach]->filename == NULL) { + free(mail_object->attachment[mail_object->num_attach]); + return; + } + strcpy(mail_object->attachment[mail_object->num_attach]->filename, path); + if (mimetype) { + mail_object->attachment[mail_object->num_attach]->mimetype = malloc(strlen(mimetype)+1); + if (mail_object->attachment[mail_object->num_attach]->mimetype == NULL) { + free(mail_object->attachment[mail_object->num_attach]->filename); + free(mail_object->attachment[mail_object->num_attach]); + return; + } + strcpy(mail_object->attachment[mail_object->num_attach]->mimetype, mimetype); + } + else mail_object->attachment[mail_object->num_attach]->mimetype = NULL; + mail_object->num_attach++; + } +} + +//------------------------------------------------- +static const char *file_base_name(const char *path) +{ + // get base filename + const char* basename = path + strlen(path); + while (basename != path) { + basename--; + if (*basename == '/') { + basename++; + break; + } + } + return basename; +} + +//-------------------------------------------------------------------------------- +static size_t curlmail_get_data(void* ptr, size_t size, size_t nmemb, void* userp) +{ + struct email_info_struct* mail_object = (struct email_info_struct*)userp; + + // Exit if no data is requested + if (size * nmemb == 0) + return 0; + + // Do some initialization on first run + if (mail_object->state == SEND_MAIL_STATE_INITIALIZE) { + if (mail_object->buf) free(mail_object->buf); + mail_object->buf = NULL; + mail_object->buflen = 0; + if (mail_object->boundary_body) free(mail_object->boundary_body); + mail_object->boundary_body = NULL; + if (mail_object->boundary_attach) free(mail_object->boundary_attach); + mail_object->boundary_attach = NULL; + mail_object->state++; // -> SEND_MAIL_STATE_HEADER + } + + // Check if partial data is pending + while (mail_object->buflen == 0) { + // ** No partial data is pending, process current part of mail + //------------------------------------------------------------------------------- + if (mail_object->buflen == 0 && mail_object->state == SEND_MAIL_STATE_HEADER) { + // === HEADER, generate header part === + char** p = &mail_object->buf; + append_to_string(p, "User-Agent: MicroPython_ESP32_mail v1.0" CRLF); + if (mail_object->timestamp != 0) { + char timestamptext[32]; + //format timestamp + if (strftime(timestamptext, sizeof(timestamptext), "%a, %d %b %Y %H:%M:%S %z", localtime(&mail_object->timestamp))) { + append_to_string(p, "Date: "); + append_to_string(p, timestamptext); + append_to_string(p, CRLF); + } + } + if (mail_object->from && *mail_object->from) { + append_to_string(p, "From: "); + append_to_string(p, mail_object->from); + append_to_string(p, CRLF); + } + if (mail_object->to && *mail_object->to) { + append_to_string(p, "To: "); + append_to_string(p, mail_object->to); + append_to_string(p, CRLF); + } + if (mail_object->cc && *mail_object->cc) { + append_to_string(p, "Cc: "); + append_to_string(p, mail_object->cc); + append_to_string(p, CRLF); + } + if (mail_object->bcc && *mail_object->bcc) { + append_to_string(p, "Bcc: "); + append_to_string(p, mail_object->bcc); + append_to_string(p, CRLF); + } + if (mail_object->subject) { + append_to_string(p, "Subject: "); + append_to_string(p, mail_object->subject); + append_to_string(p, CRLF); + } + if (mail_object->header) { + append_to_string(p, mail_object->header); + } + if (mail_object->num_attach > 0) { + append_to_string(p, "MIME-Version: 1.0" CRLF); + mail_object->boundary_attach = populate_boundary(strdup("=PART_SEPARATOR_0000_0000_0000_0000_0000_0000")); + append_to_string(p, "Content-Type: multipart/mixed; boundary=\""); + append_to_string(p, mail_object->boundary_attach); + append_to_string(p, "\"" CRLF CRLF "This is a multipart message in MIME format." CRLF CRLF "--"); + append_to_string(p, mail_object->boundary_attach); + append_to_string(p, CRLF); + } + if (mail_object->body) { + mail_object->boundary_body = populate_boundary(strdup("=BODY_SEPARATOR_0000_0000_0000_0000_0000_0000")); + append_to_string(p, "Content-Type: multipart/alternative; boundary=\""); + append_to_string(p, mail_object->boundary_body); + append_to_string(p, "\"" CRLF); + } + mail_object->buflen = (mail_object->buf ? strlen(mail_object->buf) : 0); + mail_object->state++; // -> SEND_MAIL_STATE_BODY + } + + //----------------------------------------------------------------------------- + if (mail_object->buflen == 0 && mail_object->state == SEND_MAIL_STATE_BODY) { + if (mail_object->body) { + // === BODY === + // generate body header + if (mail_object->boundary_body) { + mail_object->buf = append_to_string(&mail_object->buf, CRLF "--"); + mail_object->buf = append_to_string(&mail_object->buf, mail_object->boundary_body); + mail_object->buf = append_to_string(&mail_object->buf, CRLF); + } + mail_object->buf = append_to_string(&mail_object->buf, "Content-Type: "); + mail_object->buf = append_to_string(&mail_object->buf, default_mime_type); + mail_object->buf = append_to_string(&mail_object->buf, CRLF "Content-Transfer-Encoding: 8bit" CRLF "Content-Disposition: inline" CRLF CRLF); + // append body + mail_object->buf = append_to_string(&mail_object->buf, mail_object->body); + mail_object->buflen = (mail_object->buf ? strlen(mail_object->buf) : 0); + } + mail_object->state++; // --> SEND_MAIL_STATE_BODY_DONE + } + + //---------------------------------------------------------------------------------- + if (mail_object->buflen == 0 && mail_object->state == SEND_MAIL_STATE_BODY_DONE) { + if (mail_object->body) { + // === BODY DONE === + mail_object->buf = NULL; + if (mail_object->boundary_body) { + mail_object->buf = append_to_string(&mail_object->buf, CRLF "--"); + mail_object->buf = append_to_string(&mail_object->buf, mail_object->boundary_body); + mail_object->buf = append_to_string(&mail_object->buf, "--" CRLF); + mail_object->buflen = strlen(mail_object->buf); + free(mail_object->boundary_body); + mail_object->boundary_body = NULL; + } + } + mail_object->state++; // -> SEND_MAIL_STATE_ATTACHMENT + } + + //----------------------------------------------------------------------------------- + if (mail_object->buflen == 0 && mail_object->state == SEND_MAIL_STATE_ATTACHMENT) { + // === ATTACHMENT === + if ((mail_object->num_attach > 0) && (mail_object->attachment[mail_object->num_attach-1])) { + if (!mail_object->attachment[mail_object->num_attach-1]->handle) { + //open file to attach + mail_object->attachment[mail_object->num_attach-1]->handle = fopen(mail_object->attachment[mail_object->num_attach-1]->filename, "rb"); + if (mail_object->attachment[mail_object->num_attach-1]->handle) { + //generate attachment header + mail_object->buf = NULL; + if (mail_object->boundary_attach) { + mail_object->buf = append_to_string(&mail_object->buf, CRLF "--"); + mail_object->buf = append_to_string(&mail_object->buf, mail_object->boundary_attach); + mail_object->buf = append_to_string(&mail_object->buf, CRLF); + } + mail_object->buf = append_to_string(&mail_object->buf, "Content-Type: "); + mail_object->buf = append_to_string(&mail_object->buf, + (mail_object->attachment[mail_object->num_attach-1]->mimetype ? mail_object->attachment[mail_object->num_attach-1]->mimetype : "application/octet-stream")); + mail_object->buf = append_to_string(&mail_object->buf, "; Name=\""); + mail_object->buf = append_to_string(&mail_object->buf, + (mail_object->attachment[mail_object->num_attach-1]->filename ? file_base_name(mail_object->attachment[mail_object->num_attach-1]->filename) : "ATTACHMENT")); + mail_object->buf = append_to_string(&mail_object->buf, "\"" CRLF "Content-Disposition: attachment; filename=\""); + mail_object->buf = append_to_string(&mail_object->buf, + (mail_object->attachment[mail_object->num_attach-1]->filename ? file_base_name(mail_object->attachment[mail_object->num_attach-1]->filename) : "ATTACHMENT")); + mail_object->buf = append_to_string(&mail_object->buf, "\"" CRLF "Content-Transfer-Encoding: base64" CRLF CRLF); + mail_object->buflen = strlen(mail_object->buf); + } + } + else { + //generate next line of attachment data + size_t n = 0, file_data = 0; + int mimelinepos = 0; + unsigned char igroup[3] = {0, 0, 0}; + unsigned char ogroup[4]; + mail_object->buflen = 0; + if ((mail_object->buf = (char*)malloc(MIME_LINE_MAX_WIDTH + CRLFLENGTH + 1)) == NULL) { + ESP_LOGE(MAIL_TAG, "%s", MEMORY_ALLOCATION_ERROR); + n = 0; + } + else { + while ((mimelinepos < MIME_LINE_MAX_WIDTH) && (n = fread(igroup, 1, 3, mail_object->attachment[mail_object->num_attach-1]->handle))) { + // Encode data to base64 + ogroup[0] = base64[igroup[0] >> 2]; + ogroup[1] = base64[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; + ogroup[2] = base64[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; + ogroup[3] = base64[igroup[2] & 0x3F]; + file_data += n; + //pad with "=" characters if less than 3 characters were read + if (n < 3) { + ogroup[3] = '='; + if (n < 2) ogroup[2] = '='; + } + memcpy(mail_object->buf + mimelinepos, ogroup, 4); + mail_object->buflen += 4; + mimelinepos += 4; + } + if (mimelinepos > 0) { + memcpy(mail_object->buf + mimelinepos, CRLF, CRLFLENGTH); + mail_object->buflen += CRLFLENGTH; + } + } + if (n <= 0) { + //end of file + fclose(mail_object->attachment[mail_object->num_attach-1]->handle); + mail_object->attachment[mail_object->num_attach-1]->handle = NULL; + mail_object->state++; // -> SEND_MAIL_STATE_END + } + } + } + else mail_object->state = SEND_MAIL_STATE_DONE; + } + + //---------------------------------------------------------------------------- + if (mail_object->buflen == 0 && mail_object->state == SEND_MAIL_STATE_END) { + if ((mail_object->num_attach > 0) && (mail_object->attachment[mail_object->num_attach-1])) { + mail_object->buf = NULL; + mail_object->buflen = 0; + curlmail_free_attachment(mail_object, mail_object->num_attach-1); + mail_object->num_attach--; + if (mail_object->num_attach > 0) { + // Send the next attachment + mail_object->state--; // -> SEND_MAIL_STATE_ATTACHMENT + } + else { + if (mail_object->boundary_attach) { + // The last attachment was sent + mail_object->buf = append_to_string(&mail_object->buf, CRLF "--"); + mail_object->buf = append_to_string(&mail_object->buf, mail_object->boundary_attach); + mail_object->buf = append_to_string(&mail_object->buf, "--" CRLF); + mail_object->buflen = strlen(mail_object->buf); + } + free(mail_object->boundary_attach); + mail_object->boundary_attach = NULL; + mail_object->state++; // -> SEND_MAIL_STATE_DONE + } + } + else mail_object->state = SEND_MAIL_STATE_DONE; + } + + if (mail_object->buflen == 0 && mail_object->state == SEND_MAIL_STATE_DONE) { + break; + } + } // while (mail_object->buflen == 0) + + + // ----------------------------------------------- + // Send any pending data from mail object's buffer + // ----------------------------------------------- + if (mail_object->buflen > 0) { + int len = ((mail_object->buflen > (size * nmemb)) ? size * nmemb : mail_object->buflen); + memcpy(ptr, mail_object->buf, len); + if (len < mail_object->buflen) { + // some data are still in buffer + mail_object->buf = memmove(mail_object->buf, mail_object->buf + len, mail_object->buflen - len); + mail_object->buflen -= len; + } + else { + // Add data from buffer are sent, free the buffer + free(mail_object->buf); + mail_object->buf = NULL; + mail_object->buflen = 0; + } + return len; + } + + //if (mail_object->state != SEND_MAIL_STATE_DONE) + // ** this should never be reached + mail_object->state = 0; + return 0; +} + +//------------------------------------------------------------------------------------------------------ +static int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + struct progress *myp = (struct progress *)p; + CURL *curl = myp->curl; + double curtime = 0; + + curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime); + + /* under certain circumstances it may be desirable for certain functionality + to only run every N seconds, in order to do this the transaction time can + be used */ + if ((curl_verbose) && ((curtime - myp->lastruntime) >= curl_progress)) { + if (myp->lastruntime == 0) mp_printf(&mp_plat_print, "\n"); + myp->lastruntime = curtime; + mp_printf(&mp_plat_print, "TIME: %0.1f UP: %" CURL_FORMAT_CURL_OFF_T"\r", curtime, ulnow); + } + return 0; +} + +//---------------------------------------------------------------------------------------------------------------------------------------------------------------- +const char* curlmail_protocol_send(curl_mail mail_object, const char* smtpserver, unsigned int smtpport, int protocol, const char* username, const char* password) +{ + // Curl based send mail + CURL *curl; + CURLcode result = CURLE_FAILED_INIT; + struct progress prog; + + curl = curl_easy_init(); + if (curl == NULL) return curl_easy_strerror(result); + + prog.lastruntime = 0; + prog.curl = curl; + + struct curl_slist *recipients = NULL; + + //set destination URL + char* addr; + size_t len = strlen(smtpserver) + 14; + if ((addr = (char*)malloc(len)) == NULL) { + ESP_LOGE(MAIL_TAG, "Error allocating memory"); + return MEMORY_ALLOCATION_ERROR; + } + snprintf(addr, len, "%s://%s:%u", (protocol == CURLMAIL_PROTOCOL_SMTPS ? "smtps" : "smtp"), smtpserver, smtpport); + curl_easy_setopt(curl, CURLOPT_URL, addr); + free(addr); + + // Try using Transport Layer Security (TLS), but continue anyway if it fails + curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); + //don't fail if the TLS/SSL a certificate could not be verified + //alternative: add the issuer certificate (or the host certificate if + //the certificate is self-signed) to the set of certificates that are + //known to libcurl using CURLOPT_CAINFO and/or CURLOPT_CAPATH + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + //set authentication credentials if provided + if (username && *username) curl_easy_setopt(curl, CURLOPT_USERNAME, username); + if (password) curl_easy_setopt(curl, CURLOPT_PASSWORD, password); + + //set from value for envelope reverse-path + if (mail_object->from && *mail_object->from) curl_easy_setopt(curl, CURLOPT_MAIL_FROM, mail_object->from); + + //set recipient + recipients = curl_slist_append(recipients, mail_object->to); + + if (mail_object->cc) recipients = curl_slist_append(recipients, mail_object->cc); + if (mail_object->bcc) recipients = curl_slist_append(recipients, mail_object->bcc); + + curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); + //set callback function for getting message body + curl_easy_setopt(curl, CURLOPT_READFUNCTION, curlmail_get_data); + curl_easy_setopt(curl, CURLOPT_READDATA, mail_object); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); //set CURLOPT_UPLOAD to 1 to not use VRFY and other unneeded commands + + //enable debugging if requested + curl_easy_setopt(curl, CURLOPT_VERBOSE, curl_verbose); + + curl_easy_setopt(curl, CURLOPT_TIMEOUT, curl_timeout); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); + + // pass the struct pointer into the xferinfo function, note that this is an alias to CURLOPT_PROGRESSDATA + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog); + if (curl_progress) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1L); + + curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 2048); + + //send the message + MP_THREAD_GIL_EXIT(); + result = curl_easy_perform(curl); + MP_THREAD_GIL_ENTER(); + + if (curl_verbose) mp_printf(&mp_plat_print, "\n"); + //free the list of recipients and clean up + curl_slist_free_all(recipients); + curl_easy_cleanup(curl); + + return (result == CURLE_OK ? NULL : curl_easy_strerror(result)); +} + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/curl_mail.h b/MicroPython_BUILD/components/micropython/esp32/libs/curl_mail.h new file mode 100644 index 00000000..747f3f33 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/curl_mail.h @@ -0,0 +1,79 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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 _CURL_MAIL_H +#define _CURL_MAIL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdkconfig.h" + +#if defined(CONFIG_MICROPY_USE_CURL) + +#define CURLMAIL_PROTOCOL_SMTP 1 +#define CURLMAIL_PROTOCOL_SMTPS 2 +#define CURLMAIL_PROTOCOL_IMAP 3 +#define CURLMAIL_PROTOCOL_IMAPS 4 + +#define CURLMAIL_MAX_ATTACHMENTS 4 + + +typedef struct email_info_struct* curl_mail; + + +curl_mail curlmail_create (const char* from, const char* subject); + +void curlmail_destroy (curl_mail mail_object); + +void curlmail_set_from (curl_mail mail_object, const char* from); + +void curlmail_add_to (curl_mail mail_object, const char* mail_addr); + +void curlmail_add_cc (curl_mail mail_object, const char* mail_addr); + +void curlmail_add_bcc (curl_mail mail_object, const char* mail_addr); + +void curlmail_set_subject (curl_mail mail_object, const char* subject); + +void curlmail_add_header (curl_mail mail_object, const char* headerline); + +void curlmail_set_body (curl_mail mail_object, const char* body); + +void curlmail_add_attachment_file(curl_mail mail_object, const char* path, const char* mimetype); + +const char* curlmail_protocol_send (curl_mail mail_object, const char* smtpserver, unsigned int smtpport, int protocol, const char* username, const char* password); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif //_CURL_MAIL_H diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c index 46aac88f..f892d6b9 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c @@ -30,6 +30,7 @@ #if defined(CONFIG_MICROPY_USE_CURL) || defined(CONFIG_MICROPY_USE_SSH) #include +#include #include "freertos/FreeRTOS.h" #include "libs/espcurl.h" #include "libs/libGSM.h" @@ -46,25 +47,11 @@ #include "esp_wifi_types.h" #include "tcpip_adapter.h" +#include "modnetwork.h" +#include "modmachine.h" #include "py/mpthread.h" #include "py/nlr.h" -//-------------------- -void checkConnection() -{ - tcpip_adapter_ip_info_t info; - tcpip_adapter_get_ip_info(WIFI_IF_STA, &info); - if (info.ip.addr == 0) { - #ifdef CONFIG_MICROPY_USE_GSM - if (ppposStatus() != GSM_STATE_CONNECTED) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "No Internet connection")); - } - #else - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "No Internet connection")); - #endif - } -} - #ifdef CONFIG_MICROPY_USE_CURL const char *CURL_TAG = "[Curl]"; @@ -77,14 +64,6 @@ uint32_t curl_maxbytes = 300000; // limit download length uint8_t curl_initialized = 0; uint8_t curl_nodecode = 0; // if set to 1, do not use compression in http transfers -#if CONFIG_SPIRAM_SUPPORT -int hdr_maxlen = 1024; -int body_maxlen = 4096; -#else -int hdr_maxlen = 512; -int body_maxlen = 1024; -#endif - static uint8_t curl_sim_fs = 0; struct curl_Transfer { @@ -135,7 +114,7 @@ static size_t curlWrite(void *buffer, size_t size, size_t nmemb, void *userdata) if ((s->status == 0) && ((size*nmemb) > 0)) { for (int i=0; i<(size*nmemb); i++) { if (s->len < (s->maxlen-2)) { - if (((buf[i] == 0x0a) || (buf[i] == 0x0d)) || ((buf[i] >= 0x20) && (buf[i] >= 0x20))) s->ptr[s->len] = buf[i]; + if ((buf[i] == 0x0a) || (buf[i] == 0x0d) || (buf[i] == 0x09) || (buf[i] >= 0x20)) s->ptr[s->len] = buf[i]; else s->ptr[s->len] = '.'; s->len++; s->ptr[s->len] = '\0'; @@ -387,6 +366,164 @@ int Curl_GET(char *url, char *fname, char *hdr, char *body, int hdrlen, int body return err; } +// Converts an integer value to its hex character +//----------------------------- +static char to_hex(char code) { + static char hex[] = "0123456789abcdef"; + return hex[code & 15]; +} + +//------------------------------------------------------------ +/* Returns a url encoded version of str + * IMPORTANT: be sure to free() the returned string after use + */ +//================================= +char *url_encode(const char *str) { + const char *pstr = str; + char *buf = malloc(strlen(str) * 3 + 1); + char *pbuf = buf; + while (*pstr) { + if (*pstr == ' ') { + *pbuf++ = '%'; + *pbuf++ = to_hex(*pstr >> 4); + *pbuf++ = to_hex(*pstr & 15); + } + else { + *pbuf++ = *pstr; + } + pstr++; + } + *pbuf = '\0'; + return buf; +} + +//========================================================================================================================================================================================================= +int Curl_IMAP_GET(const char *opts, char *fname, char *hdr, char *body, int hdrlen, int bodylen, const char* imapserver, unsigned int imapport, const char* username, const char* password, char *cust_req) +{ + CURL *curl = NULL; + CURLcode res = 0; + FILE* file = NULL; + int err = 0; + + if ((hdr) && (hdrlen < MIN_HDR_BUF_LEN)) { + err = -1; + goto exit; + } + if ((body) && (bodylen < MIN_BODY_BUF_LEN)) { + err = -2; + goto exit; + } + + struct curl_Transfer get_data; + struct curl_Transfer get_header; + + if (!curl_initialized) { + res = curl_global_init(CURL_GLOBAL_DEFAULT); + if (res) { + err = -3; + goto exit; + } + curl_initialized = 1; + } + + // Create a curl curl + curl = curl_easy_init(); + if (curl == NULL) { + err = -4; + goto exit; + } + + init_curl_Transfer(curl, &get_data, body, bodylen, NULL); + init_curl_Transfer(curl, &get_header, hdr, hdrlen, NULL); + + if (fname) { + if (strcmp(fname, "simulate") == 0) { + get_data.tofile = 1; + curl_sim_fs = 1; + } + else { + file = fopen(fname, "wb"); + if (file == NULL) { + err = -5; + goto exit; + } + get_data.file = file; + get_data.tofile = 1; + curl_sim_fs = 0; + } + } + + //set destination URL + char* url; + char *opts_out = url_encode(opts); + int opts_len = strlen(opts_out); + size_t len = strlen(imapserver) + opts_len + 16; + if ((url = (char*)malloc(len)) == NULL) { + free(opts_out); + ESP_LOGE(CURL_TAG, "Error allocating memory"); + err = -6; + goto exit; + } + + sprintf(url, "imaps://%s:%u/%s", imapserver, imapport, opts_out); + free(opts_out); + + curl_easy_setopt(curl, CURLOPT_URL, url); + printf("=== URL=[%s]\n", url); + free(url); + + _set_default_options(curl); + + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlWrite); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, &get_header); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWrite); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &get_data); + + // Try using Transport Layer Security (TLS), but continue anyway if it fails + curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY); + + //set authentication credentials if provided + if (username && *username) curl_easy_setopt(curl, CURLOPT_USERNAME, username); + if (password) curl_easy_setopt(curl, CURLOPT_PASSWORD, password); + + if (cust_req) { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, cust_req); + } + // Only allow IMAPS, we do not want this to work when unencrypted. + curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_IMAPS); + + // Perform the request, res will get the return code + res = curl_easy_perform(curl); + + if (res != CURLE_OK) { + if (curl_verbose) { + ESP_LOGE(CURL_TAG, "curl_easy_perform failed: %s", curl_easy_strerror(res)); + } + if (body) snprintf(body, bodylen, "%s", curl_easy_strerror(res)); + err = -7; + goto exit; + } + + if (get_data.tofile) { + if (curl_progress) { + double curtime = 0; + curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime); + ESP_LOGI(CURL_TAG, "* Download: received %d B; time=%0.1f s; speed=%0.1f KB/sec", get_data.len, curtime, (float)(((get_data.len*10)/curtime) / 10240.0)); + } + if (body) { + if (strcmp(fname, "simulate") == 0) snprintf(body, bodylen, "SIMULATED save to file; size=%d", get_data.len); + else snprintf(body, bodylen, "Saved to file %s, size=%d", fname, get_data.len); + } + } + +exit: + // Cleanup + if (file) fclose(file); + if (curl) curl_easy_cleanup(curl); + + return err; +} //======================================================================= int Curl_POST(char *url , char *hdr, char *body, int hdrlen, int bodylen) @@ -472,6 +609,7 @@ int Curl_POST(char *url , char *hdr, char *body, int hdrlen, int bodylen) return err; } +//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #ifdef CONFIG_MICROPY_USE_CURLFTP //=================================================================================================================== @@ -651,13 +789,6 @@ uint16_t ssh2_session_trace = 0; uint8_t ssh2_session_timeout = 8; uint32_t ssh2_maxbytes = 300000; // limit download length -#if CONFIG_SPIRAM_SUPPORT -int ssh2_hdr_maxlen = 1024; -int ssh2_body_maxlen = 4096; -#else -int ssh2_hdr_maxlen = 512; -int ssh2_body_maxlen = 1024; -#endif // ==== LIBSSH2 functions ==== diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.h b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.h index 0cafabd9..c33bee85 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.h @@ -47,6 +47,8 @@ #define GMAIL_SMTP "smtp.gmail.com" #define GMAIL_PORT 465 +#define GMAIL_IMAP "imap.gmail.com" +#define GMAIL_IMAP_PORT 993 struct curl_httppost *formpost; struct curl_httppost *lastptr; @@ -58,8 +60,6 @@ extern uint16_t curl_timeout; // curl operations timeout in seconds extern uint32_t curl_maxbytes; // limit download length extern uint8_t curl_initialized; extern uint8_t curl_nodecode; -extern int hdr_maxlen; -extern int body_maxlen; /* * ---------------------------------------------------------- @@ -84,6 +84,10 @@ extern int body_maxlen; int Curl_GET(char *url, char *fname, char *hdr, char *body, int hdrlen, int bodylen); +//========================================================================================================================================================================================================== +int Curl_IMAP_GET(const char *opts, char *fname, char *hdr, char *body, int hdrlen, int bodylen, const char* imapserver, unsigned int imapport, const char* username, const char* password, char *cust_req); + + /* * ----------------------------------------------------- * int res = Curl_POST(url, hdr, body, hdrlen, bodylen); @@ -162,8 +166,9 @@ int ssh_SCP(uint8_t type, char *server, char *port, char * scppath, char *user, #endif // CONFIG_MICROPY_USE_SSH -//===================== -void checkConnection(); + +//================================ +char *url_encode(const char *str); #endif // defined(CONFIG_MICROPY_USE_CURL) || defined(CONFIG_MICROPY_USE_SSH) diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8.h b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8.h index 2aed4222..59991ed5 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8.h @@ -1,37 +1,43 @@ /* -@file FT8.h -@brief Contains FT80x/FT81x API definitions -@version 3.2 -@date 2017-04-08 -@author Rudolph Riedel + * This file is part of the ESP32 MicroPython project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * Contains Functions for using the FT8xx + * === Ported from https://github.com/RudolphRiedel/FT800-FT813 === + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Rudolph Riedel + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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. + */ -@section History -2.1 -- changes to this header - -2.2 -- commented out "#define DISPLAY() ((0UL<<24))" as it collides with a define in the Arduino IDE - the whole section of "macros" needs a rework... - -3.0 -- renamed from FT800.h to FT8.h -- changed FT_ prefixes to FT8_ -- switched to standard-C compliant comment-style -- changed FT81x register definitions from decimal to hex -- verified all FT81x register definitions -- moved FT81x registers marked as "reserved" to an #if 0 block +#ifndef _FT8_H_ +#define _FT8_H_ -3.1 -- moved several undocumented commands to an #if 0 block +#include "sdkconfig.h" -3.2 -- moved CMD_CRC to the block of undocumented commands as well -*/ +#if CONFIG_MICROPY_USE_EVE #include "FT8_commands.h" -#ifndef _FT8_H_ -#define _FT8_H_ #define DL_CLEAR 0x26000000UL /* requires OR'd arguments */ @@ -415,8 +421,11 @@ #define VERTEX2II(x,y,handle,cell) ((2UL<<30)|(((x)&511UL)<<21)|(((y)&511UL)<<12)|(((handle)&31UL)<<7)|(((cell)&127UL)<<0)) +#define REG_ID_FT81X 0x302000UL +#define REG_ID_FT80X 0x102400UL + /* specific for FT80x */ -#ifndef FT8_81X_ENABLE +#ifdef CONFIG_EVE_CHIP_TYPE0 #define FT8_CHIPID 0x00010008UL @@ -733,4 +742,508 @@ #endif + +/* The following predifined configurations are available + ----------------------------------------------------- + #define FT8_VM800B35A + #define FT8_VM800B43A + #define FT8_VM800B50A + #define FT8_VM810C + #define FT8_ME812A + #define FT8_ME813A + #define FT8_FT810CB_HY50HD + #define FT8_FT811CB_HY50HD + #define FT8_ET07 + #define FT8_RVT70AQ + #define FT8_EVE2_29 + #define FT8_EVE2_35 + #define FT8_EVE2_35G + #define FT8_EVE2_38 + #define FT8_EVE2_38G + #define FT8_EVE2_43 + #define FT8_EVE2_43G + #define FT8_EVE2_50 + #define FT8_EVE2_50G + #define FT8_EVE2_70 + #define FT8_EVE2_70G + #define FT8_NHD_35 + #define FT8_NHD_43 + #define FT8_NHD_50 + #define FT8_NHD_70 + #define FT8_ADAM101 +*/ + + +/* + * ================================= + * display timing parameters below + * ================================= +*/ + +/* VM800B35A: FT800 320x240 3.5" FTDI */ +#if defined (CONFIG_FT8_VM800B35A) +#define FT8_HSIZE (320L) /* Thd Length of visible part of line (in PCLKs) - display width */ +#define FT8_VSIZE (240L) /* Tvd Number of visible lines (in lines) - display height */ + +#define FT8_VSYNC0 (0L) /* Tvf Vertical Front Porch */ +#define FT8_VSYNC1 (2L) /* Tvf + Tvp Vertical Front Porch plus Vsync Pulse width */ +#define FT8_VOFFSET (13L) /* Tvf + Tvp + Tvb Number of non-visible lines (in lines) */ +#define FT8_VCYCLE (263L) /* Tv Total number of lines (visible and non-visible) (in lines) */ +#define FT8_HSYNC0 (0L) /* Thf Horizontal Front Porch */ +#define FT8_HSYNC1 (10L) /* Thf + Thp Horizontal Front Porch plus Hsync Pulse width */ +#define FT8_HOFFSET (70L) /* Thf + Thp + Thb Length of non-visible part of line (in PCLK cycles) */ +#define FT8_HCYCLE (408L) /* Th Total length of line (visible and non-visible) (in PCLKs) */ +#define FT8_PCLKPOL (0L) /* PCLK polarity (0 = rising edge, 1 = falling edge) */ +#define FT8_SWIZZLE (2L) /* Defines the arrangement of the RGB pins of the FT800 */ +#define FT8_PCLK (8L) /* 48MHz / REG_PCLK = PCLK frequency */ +#define FT8_CSPREAD (1L) /* helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */ +#define FT8_TOUCH_RZTHRESH (1200L) /* touch-sensitivity */ +#define FT8_HAS_CRYSTAL /* use external crystal or internal oscillator? */ +#endif + + +/* FTDI/BRT EVE modules VM800B43A and VM800B50A FT800 480x272 4.3" and 5.0" */ +#if defined (CONFIG_FT8_VM800B43A) || defined (FT8_VM800B50A) +#define FT8_HSIZE (480L) +#define FT8_VSIZE (272L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (10L) +#define FT8_VOFFSET (12L) +#define FT8_VCYCLE (292L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (41L) +#define FT8_HOFFSET (43L) +#define FT8_HCYCLE (548L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (5L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL +#endif + + +/* untested */ +/* FTDI/BRT EVE2 modules VM810C50A-D, ME812A-WH50R and ME813A-WH50C, 800x480 5.0" */ +#if defined (CONFIG_FT8_VM810C) || defined (FT8_ME812A) || defined (FT8_ME813A) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (3L) +#define FT8_VOFFSET (32L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (48L) +#define FT8_HOFFSET (88L) +#define FT8_HCYCLE (928L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (0L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL +#endif + + +/* FT810CB-HY50HD: FT810 800x480 5.0" HAOYU */ +#if defined (CONFIG_FT8_FT810CB_HY50HD) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (2L) +#define FT8_VOFFSET (13L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (20L) +#define FT8_HOFFSET (64L) +#define FT8_HCYCLE (952L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (0L) +#define FT8_TOUCH_RZTHRESH (2000L) /* touch-sensitivity */ +#define FT8_HAS_CRYSTAL +#endif + + +/* FT811CB-HY50HD: FT811 800x480 5.0" HAOYU */ +#if defined (CONFIG_FT8_FT811CB_HY50HD) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (2L) +#define FT8_VOFFSET (13L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (20L) +#define FT8_HOFFSET (64L) +#define FT8_HCYCLE (952L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) /* touch-sensitivity */ +#define FT8_HAS_CRYSTAL +#endif + + +/* untested */ +/* G-ET0700G0DM6 800x480 7.0" Glyn */ +#if defined (CONFIG_FT8_ET07) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (2L) +#define FT8_VOFFSET (35L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (128L) +#define FT8_HOFFSET (203L) +#define FT8_HCYCLE (1056L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL 0 /* no idea if these come with a crystal populated or not */ +#endif + + +/* RVT70AQxxxxxx 800x480 7.0" Riverdi, various options, FT812/FT813, tested with RVT70UQFNWC0x */ +#if defined (CONFIG_FT8_RVT70AQ) +#define FT8_HSIZE (800L) /* Thd Length of visible part of line (in PCLKs) - display width */ +#define FT8_VSIZE (480L) /* Tvd Number of visible lines (in lines) - display height */ + +#define FT8_VSYNC0 (0L) /* Tvf Vertical Front Porch */ +#define FT8_VSYNC1 (10L) /* Tvf + Tvp Vertical Front Porch plus Vsync Pulse width */ +#define FT8_VOFFSET (23L) /* Tvf + Tvp + Tvb Number of non-visible lines (in lines) */ +#define FT8_VCYCLE (525L) /* Tv Total number of lines (visible and non-visible) (in lines) */ +#define FT8_HSYNC0 (0L) /* Thf Horizontal Front Porch */ +#define FT8_HSYNC1 (10L) /* Thf + Thp Horizontal Front Porch plus Hsync Pulse width */ +#define FT8_HOFFSET (46L) /* Thf + Thp + Thb Length of non-visible part of line (in PCLK cycles) */ +#define FT8_HCYCLE (1056L) /* Th Total length of line (visible and non-visible) (in PCLKs) */ +#define FT8_PCLKPOL (1L) /* PCLK polarity (0 = rising edge, 1 = falling edge) */ +#define FT8_SWIZZLE (0L) /* Defines the arrangement of the RGB pins of the FT800 */ +#define FT8_PCLK (2L) /* 60MHz / REG_PCLK = PCLK frequency 30 MHz */ +#define FT8_CSPREAD (1L) /* helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */ +#define FT8_TOUCH_RZTHRESH (1800L) /* touch-sensitivity */ +#endif + + +/* untested */ +/* EVE2-29A 320x102 2.9" 1U Matrix Orbital, non-touch, FT812 */ +#if defined (CONFIG_FT8_EVE2_29) +#define FT8_HSIZE (320L) +#define FT8_VSIZE (102L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (2L) +#define FT8_VOFFSET (156L) +#define FT8_VCYCLE (262L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (10L) +#define FT8_HOFFSET (70L) +#define FT8_HCYCLE (408L) +#define FT8_PCLKPOL (0L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (8L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#endif + + +/* EVE2-35A 320x240 3.5" Matrix Orbital, resistive, or non-touch, FT812 */ +#if defined (CONFIG_FT8_EVE2_35) +#define FT8_HSIZE (320L) +#define FT8_VSIZE (240L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (2L) +#define FT8_VOFFSET (18L) +#define FT8_VCYCLE (262L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (10L) +#define FT8_HOFFSET (70L) +#define FT8_HCYCLE (408L) +#define FT8_PCLKPOL (0L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (8L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#endif + + +/* EVE2-35G 320x240 3.5" Matrix Orbital, capacitive touch, FT813 */ +#if defined (CONFIG_FT8_EVE2_35G) +#define FT8_HSIZE (320L) +#define FT8_VSIZE (240L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (2L) +#define FT8_VOFFSET (18L) +#define FT8_VCYCLE (262L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (10L) +#define FT8_HOFFSET (70L) +#define FT8_HCYCLE (408L) +#define FT8_PCLKPOL (0L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (8L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_GT911 /* special treatment required for out-of-spec touch-controller */ +#endif + + +/* EVE2-38A 480x116 3.8" 1U Matrix Orbital, resistive touch, FT812 */ +#if defined (CONFIG_FT8_EVE2_38) +#define FT8_HSIZE (480L) +#define FT8_VSIZE (272L) + +#define FT8_VSYNC0 (152L) +#define FT8_VSYNC1 (10L) +#define FT8_VOFFSET (12L) +#define FT8_VCYCLE (292L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (41L) +#define FT8_HOFFSET (43L) +#define FT8_HCYCLE (548L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (5L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#endif + + +/* EVE2-38G 480x116 3.8" 1U Matrix Orbital, capacitive touch, FT813 */ +#if defined (CONFIG_FT8_EVE2_38G) +#define FT8_HSIZE (480L) +#define FT8_VSIZE (272L) + +#define FT8_VSYNC0 (152L) +#define FT8_VSYNC1 (10L) +#define FT8_VOFFSET (12L) +#define FT8_VCYCLE (292L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (41L) +#define FT8_HOFFSET (43L) +#define FT8_HCYCLE (548L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (5L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_GT911 /* special treatment required for out-of-spec touch-controller */ +#endif + + +/* untested */ +/* EVE2-43A 480x272 4.3" Matrix Orbital, resistive or no touch, FT812 */ +#if defined (CONFIG_FT8_EVE2_43) +#define FT8_HSIZE (480L) +#define FT8_VSIZE (272L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (10L) +#define FT8_VOFFSET (12L) +#define FT8_VCYCLE (292L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (41L) +#define FT8_HOFFSET (43L) +#define FT8_HCYCLE (548L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (5L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#endif + + +/* EVE2-43G 480x272 4.3" Matrix Orbital, capacitive touch, FT813 */ +#if defined (CONFIG_FT8_EVE2_43G) +#define FT8_HSIZE (480L) +#define FT8_VSIZE (272L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (10L) +#define FT8_VOFFSET (12L) +#define FT8_VCYCLE (292L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (41L) +#define FT8_HOFFSET (43L) +#define FT8_HCYCLE (548L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (5L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_GT911 /* special treatment required for out-of-spec touch-controller */ +#endif + + +/* untested */ +/* Matrix Orbital EVE2 modules EVE2-50A, EVE2-70A : 800x480 5.0" and 7.0" resistive, or no touch, FT812 */ +#if defined (CONFIG_FT8_EVE2_50) || defined (FT8_EVE2_70) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (3L) +#define FT8_VOFFSET (32L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (48L) +#define FT8_HOFFSET (88L) +#define FT8_HCYCLE (928L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (0L) +#define FT8_TOUCH_RZTHRESH (1200L) +#endif + + +/* Matrix Orbital EVE2 modules EVE2-50G, EVE2-70G : 800x480 5.0" and 7.0" capacitive touch, FT813 */ +#if defined (CONFIG_FT8_EVE2_50G) || defined (FT8_EVE2_70G) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (3L) +#define FT8_VOFFSET (32L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (48L) +#define FT8_HOFFSET (88L) +#define FT8_HCYCLE (928L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (0L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_GT911 /* special treatment required for out-of-spec touch-controller */ +#endif + + +/* NHD-3.5-320240FT-CxXx-xxx 320x240 3.5" Newhaven, resistive or capacitive, FT81x */ +#if defined (CONFIG_FT8_NHD_35) +#define FT8_HSIZE (320L) +#define FT8_VSIZE (240L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (2L) +#define FT8_VOFFSET (13L) +#define FT8_VCYCLE (263L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (10L) +#define FT8_HOFFSET (70L) +#define FT8_HCYCLE (408L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (2L) +#define FT8_PCLK (6L) +#define FT8_CSPREAD (0L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL +#endif + + +/* untested */ +/* NHD-4.3-480272FT-CxXx-xxx 480x272 4.3" Newhaven, resistive or capacitive, FT81x */ +#if defined (CONFIG_FT8_NHD_43) +#define FT8_HSIZE (480L) +#define FT8_VSIZE (272L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (10L) +#define FT8_VOFFSET (12L) +#define FT8_VCYCLE (292L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (41L) +#define FT8_HOFFSET (43L) +#define FT8_HCYCLE (548L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (5L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL +#endif + + +/* untested */ +/* NHD-5.0-800480FT-CxXx-xxx 800x480 5.0" Newhaven, resistive or capacitive, FT81x */ +#if defined (CONFIG_FT8_NHD_50) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (3L) +#define FT8_VOFFSET (32L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (48L) +#define FT8_HOFFSET (88L) +#define FT8_HCYCLE (928L) +#define FT8_PCLKPOL (0L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL +#endif + + +/* untested */ +/* NHD-7.0-800480FT-CxXx-xxx 800x480 7.0" Newhaven, resistive or capacitive, FT81x */ +#if defined (CONFIG_FT8_NHD_70) +#define FT8_HSIZE (800L) +#define FT8_VSIZE (480L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (3L) +#define FT8_VOFFSET (32L) +#define FT8_VCYCLE (525L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (48L) +#define FT8_HOFFSET (88L) +#define FT8_HCYCLE (928L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL +#endif + + +/* ADAM101-LCP-SWVGA-NEW 1024x600 10.1" Glyn, capacitive, FT813 */ +#if defined (CONFIG_FT8_ADAM101) +#define FT8_HSIZE (1024L) +#define FT8_VSIZE (600L) + +#define FT8_VSYNC0 (0L) +#define FT8_VSYNC1 (1L) +#define FT8_VOFFSET (1L) +#define FT8_VCYCLE (720L) +#define FT8_HSYNC0 (0L) +#define FT8_HSYNC1 (1L) +#define FT8_HOFFSET (1L) +#define FT8_HCYCLE (1100L) +#define FT8_PCLKPOL (1L) +#define FT8_SWIZZLE (0L) +#define FT8_PCLK (2L) +#define FT8_CSPREAD (1L) +#define FT8_TOUCH_RZTHRESH (1200L) +#define FT8_HAS_CRYSTAL +#endif + + +#endif //CONFIG_MICROPY_USE_EVE + #endif /* _FT8_H_ */ diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c index 8c9989d3..502adb6b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.c @@ -34,59 +34,367 @@ #if CONFIG_MICROPY_USE_EVE #include +#include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_log.h" #include "FT8.h" -#include "tft/spi_master_lobo.h" +#include "driver/spi_master_utils.h" +#include "mphalport.h" + +uint16_t eve_chip_id = 0; + +static const char TAG[] = "[EveDrv]"; // FT8xx Memory Commands - use with FT8_memWritexx and FT8_memReadxx -#define MEM_WRITE 0x80 // FT8xx Host Memory Write -#define MEM_READ 0x00 // FT8xx Host Memory Read +#define MEM_WRITE 0x80 // FT8xx Host Memory Write +#define MEM_READ 0x00 // FT8xx Host Memory Read + +#define MIN_FIFO_FREE 256 uint16_t eve_cmdOffset = 0x0000; // used to navigate command ring buffer static uint8_t cmd_burst = 0; // flag to indicate cmd-burst is active -spi_lobo_device_handle_t eve_spi = NULL; - -//--------------------------------------------------------------------------------------------------- -static void IRAM_ATTR _spi_transfer_start(spi_lobo_device_handle_t spi_dev, int wrbits, int rdbits) { - // Load send buffer - spi_dev->host->hw->user.usr_mosi_highpart = 0; - spi_dev->host->hw->mosi_dlen.usr_mosi_dbitlen = wrbits-1; - spi_dev->host->hw->user.usr_mosi = 1; - if (rdbits) { - spi_dev->host->hw->miso_dlen.usr_miso_dbitlen = rdbits; - spi_dev->host->hw->user.usr_miso = 1; +uint8_t eve_spibus_is_init = 0; +uint8_t spi_is_init = 0; +uint8_t ft8_full_cs = 1; +exspi_device_handle_t *eve_spi = NULL; +uint32_t ft8_ramg_ptr = FT8_RAM_G; +FT8_Fifo_t ft8_stFifo = {0}; +//FT8_Fifo_t *ft8_pFifo = &ft8_stFifo; + + +#ifdef CONFIG_EVE_CHIP_TYPE1 +// FT811 / FT813 binary-blob from FTDIs AN_336 to patch the touch-engine for Goodix GT911 / GT9271 touch controllers +const uint16_t FT8_GT911_len = 1184; +const uint8_t FT8_GT911_data[1184] = +{ + 26,255,255,255,32,32,48,0,4,0,0,0,2,0,0,0, + 34,255,255,255,0,176,48,0,120,218,237,84,221,111,84,69,20,63,51,179,93,160,148,101,111,76,5,44,141,123,111,161,11,219,154,16,9,16,17,229,156,75,26,11,13,21,227,3,16,252,184,179, + 45,219,143,45,41,125,144,72,67,100,150,71,189,113,18,36,17,165,100,165,198,16,32,17,149,196,240,128,161,16,164,38,54,240,0,209,72,130,15,38,125,48,66,82,30,76,19,31,172,103,46, + 139,24,255,4,227,157,204,156,51,115,102,206,231,239,220,5,170,94,129,137,75,194,216,98,94,103,117,115,121,76,131,177,125,89,125,82,123,60,243,58,142,242,204,185,243,188,118,156, + 227,155,203,238,238,195,251,205,229,71,92,28,169,190,184,84,143,113,137,53,244,103,181,237,87,253,113,137,233,48,12,198,165,181,104,139,25,84,253,155,114,74,191,0,54,138,163, + 12,62,131,207,129,23,217,34,91,31,128,65,246,163,175,213,8,147,213,107,35,203,94,108,3,111,40,171,83,24,15,165,177,222,116,97,23,188,140,206,150,42,102,181,87,78,86,182,170,134, + 215,241,121,26,243,252,2,76,115,217,139,222,206,173,136,132,81,61,35,185,39,113,23,46,199,76,178,54,151,183,224,0,40,189,28,149,182,58,131,79,152,30,76,34,98,234,162,216,133,141, + 102,39,170,40,192,101,53,201,146,191,37,77,44,177,209,74,211,5,206,187,5,6,216,47,53,96,123,22,50,103,251,192,84,17,74,227,185,56,106,51,91,161,96,182,163,48,171,141,139,65,152, + 66,66,11,102,43,158,75,36,80,147,184,147,139,112,17,235,216,103,111,239,245,92,10,175,194,40,44,58,125,5,59,112,50,103,245,4,78,192,5,156,194,51,60,191,134,75,110,173,237,46,192, + 121,156,192,115,184,218,120,67,63,115,46,11,102,10,97,232,50,235,114,182,148,118,178,41,188,12,135,77,202,124,12,96,238,35,161,234,189,129,23,249,212,139,230,25,53,48,205,52,93, + 163,117,53,154,170,81,85,163,178,70,69,66,167,241,14,46,241,1,226,136,152,179,197,59,184,148,254,49,132,48,15,176,137,192,76,131,196,105,104,162,86,81,160,165,255,26,173,162,137, + 86,145,210,183,192,55,175,194,211,60,91,120,230,184,174,27,41,131,155,40,224,29,87,179,232,16,55,55,7,165,147,81,23,165,49,101,54,224,75,180,81,108,18,29,226,69,225,110,175,224, + 42,212,25,47,130,193,110,234,192,215,252,56,74,162,24,46,251,174,54,106,68,245,14,9,155,160,22,120,207,104,240,29,90,178,140,28,24,220,47,166,112,61,251,208,192,111,56,239,238, + 93,255,251,62,99,32,193,75,61,190,235,123,229,110,218,194,85,79,225,59,98,20,238,227,235,220,11,221,149,25,180,116,194,159,111,96,192,24,213,59,139,179,156,215,69,230,19,24,35, + 135,117,206,171,206,162,67,129,234,61,235,11,104,103,84,64,223,167,254,40,163,101,92,84,43,150,46,249,219,205,7,116,11,91,104,61,57,75,223,8,48,25,28,119,252,222,113,49,86,249, + 74,180,211,156,181,61,215,168,157,7,251,199,150,242,250,91,58,132,94,121,7,53,151,139,98,6,165,153,69,214,32,110,211,100,101,31,89,45,81,98,23,205,205,197,209,109,186,198,35, + 141,191,249,25,60,132,223,153,251,98,20,239,146,139,20,217,250,41,250,137,58,177,90,57,79,51,108,233,20,253,194,187,49,222,205,114,141,96,48,175,219,107,54,111,138,22,154,103, + 108,79,58,252,179,178,79,164,195,2,153,36,39,170,199,201,167,197,85,106,8,59,177,81,46,56,2,230,75,114,17,55,112,188,65,208,137,77,114,10,115,55,58,208,197,173,122,87,6,140, + 110,42,208,124,163,70,108,241,104,18,245,98,214,187,134,53,42,221,22,182,133,211,116,148,177,194,209,192,85,90,199,58,55,203,2,229,19,137,187,161,228,154,112,203,145,125,244, + 188,220,118,228,41,201,181,41,195,144,215,183,51,80,250,21,217,16,217,200,235,109,227,188,122,218,142,60,170,224,112,240,184,130,229,224,113,5,223,148,163,80,165,183,130,187, + 132,116,64,238,161,85,220,115,139,205,98,227,244,29,102,125,7,37,243,123,223,11,26,92,63,243,116,61,191,138,123,244,160,84,186,74,31,5,174,247,119,135,199,248,253,135,242,97, + 102,145,190,144,14,85,238,221,231,193,158,48,205,25,120,248,15,220,29,158,9,70,185,30,103,229,33,254,23,237,160,172,62,193,90,222,224,232,14,200,56,90,104,142,227,120,110,6, + 21,211,203,65,150,99,151,220,247,87,164,50,159,49,239,234,58,142,0,109,108,123,18,79,227,36,100,248,222,205,96,127,120,26,171,228,69,63,36,17,252,200,17,116,242,187,227,88,143, + 247,2,75,191,6,130,59,188,11,55,240,31,243,122,152,226,183,207,154,73,188,39,219,43,105,222,87,41,143,141,140,175,73,112,184,252,61,184,16,90,250,35,168,82,119,176,57,116,94, + 200,150,22,190,179,44,104,12,235,84,149,102,252,89,154,193,99,228,106,242,125,248,64,194,255,223,127,242,83,11,255,2,70,214,226,128,0,0 +}; +#endif + +//--------------------------- +static esp_err_t eve_select() +{ + if (ft8_full_cs) return spi_device_select(eve_spi, 0); + else { + gpio_set_level(eve_spi->cs, 0); + return ESP_OK; + } +} + +//----------------------------- +static esp_err_t eve_deselect() +{ + if (ft8_full_cs) return spi_device_deselect(eve_spi); + else { + gpio_set_level(eve_spi->cs, 1); + return ESP_OK; + } +} + +#ifdef CONFIG_EVE_CHIP_TYPE1 + +//----------------------------------------------- +static int FT8_Fifo_write_file_block(int blksize) +{ + int bytesread, write_parc, write_remain, size, total=0; + //uint32_t old_wp = ft8_stFifo.fifo_wp; + + // repeat sending in maximum file buffer sizes + while (blksize > 0) { + size = (blksize > ft8_stFifo.fbuff_size) ? ft8_stFifo.fbuff_size : blksize; + // read block from file + bytesread = fread(ft8_stFifo.g_scratch, 1, size, ft8_stFifo.pFile); + if (bytesread <= 0) { + ft8_stFifo.file_remain = 0; + break; + } + total += bytesread; + + if ((ft8_stFifo.fifo_wp+bytesread) <= ft8_stFifo.fifo_len) { + // the whole block fits into mediafifo buffer + FT8_memWrite_flash_buffer(ft8_stFifo.fifo_buff + ft8_stFifo.fifo_wp, ft8_stFifo.g_scratch, bytesread, true); + // adjust the write pointer + ft8_stFifo.fifo_wp += bytesread; + if (ft8_stFifo.fifo_wp >= ft8_stFifo.fifo_len) ft8_stFifo.fifo_wp = 0; // wrap to the buffer start + } + else { + // wp will wrap the mediafifo buffer, write in two parts + write_parc = ft8_stFifo.fifo_len - ft8_stFifo.fifo_wp; // until the end of buffer + FT8_memWrite_flash_buffer(ft8_stFifo.fifo_buff + ft8_stFifo.fifo_wp, ft8_stFifo.g_scratch, write_parc, true); + ft8_stFifo.fifo_wp = 0; + write_remain = bytesread-write_parc; // from buffer start write remaining + FT8_memWrite_flash_buffer(ft8_stFifo.fifo_buff + ft8_stFifo.fifo_wp, ft8_stFifo.g_scratch+write_parc, write_remain, true); + // adjust the write pointer + ft8_stFifo.fifo_wp += write_remain; + } + + // adjust remaining file size + if (bytesread < size) { + ft8_stFifo.file_remain = 0; // the whole file written + blksize = 0; + } + else { + ft8_stFifo.file_remain -= bytesread; + blksize -= size; + } + } + + //ESP_LOGD(TAG, "Write block (%d) at wp=%d (new wp=%d), remaining_in_file=%d", total, old_wp, ft8_stFifo.fifo_wp, ft8_stFifo.file_remain); + return total; +} + +//-------------------- +void FT8_Fifo_deinit() +{ + if (ft8_stFifo.g_scratch) free(ft8_stFifo.g_scratch); + memset((void *)&ft8_stFifo, 0, sizeof(FT8_Fifo_t)); +} + +//---------------------------- +int FT8_Fifo_init(FILE *fhndl) +{ + int err = 0; + ESP_LOGD(TAG, "=== MEDIAFIFO Init"); + // check if there is enough space in EVE RAM_G + // minimum of 16KB is required + ft8_stFifo.fifo_len = FT8_RAM_G_SIZE - ft8_ramg_ptr; + if (ft8_stFifo.fifo_len < 16348) { err=-1; goto errexit; } + + ft8_stFifo.fifo_len = (ft8_stFifo.fifo_len / 16384) * 16384; + if (ft8_stFifo.fifo_len > 65536) ft8_stFifo.fifo_len = 65536; + + // set the buffer start address + ft8_stFifo.fifo_buff = FT8_RAM_G_SIZE-ft8_stFifo.fifo_len; + + ft8_stFifo.fifo_rp = 0; + ft8_stFifo.fifo_wp = 0; + ft8_stFifo.max_free = 0; + ft8_stFifo.min_free = ft8_stFifo.fifo_len; + + // get file size + ft8_stFifo.pFile = fhndl; + if (fseek(ft8_stFifo.pFile,0,SEEK_END)) { err=-2; goto errexit; } + ft8_stFifo.file_size = ftell(ft8_stFifo.pFile); + if (ft8_stFifo.file_size < 0) return -2; + if (fseek(ft8_stFifo.pFile,0,SEEK_SET)) { err=-2; goto errexit; } + if (ft8_stFifo.file_size == 0) { err=-2; goto errexit; } + ft8_stFifo.file_remain = ft8_stFifo.file_size; + + // Allocate file read buffer of minimum 512 bytes + ft8_stFifo.fbuff_size = 8192; + ft8_stFifo.g_scratch = NULL; + while (ft8_stFifo.g_scratch == NULL){ + ft8_stFifo.fbuff_size /= 2; + if (ft8_stFifo.fbuff_size < 512) break; + ft8_stFifo.g_scratch = malloc(ft8_stFifo.fbuff_size); + } + if (ft8_stFifo.g_scratch == NULL) { err=-3; goto errexit; } + ESP_LOGD(TAG, " mediafifo buffer at %d, size=%d, file_buff_size=%d", ft8_stFifo.fifo_buff, ft8_stFifo.fifo_len, ft8_stFifo.fbuff_size); + + // === Fill mediafifo buffer from the file === + FT8_Fifo_write_file_block(ft8_stFifo.fifo_len - ft8_stFifo.fbuff_size); + ESP_LOGD(TAG, " buffer_filled=%d, remaining_in_file: %d", ft8_stFifo.fifo_wp, ft8_stFifo.file_remain); + + // Execute CMD_MEDIAFIFO, set mediafifo parameters + FT8_start_cmd(CMD_MEDIAFIFO); + FT8_send_long(ft8_stFifo.fifo_buff, ft8_stFifo.fifo_len, 0, 2); + + if (!FT8_cmd_execute(250)) err = -8; + else return 0; + +errexit: + ESP_LOGE(TAG, " Fifo init: error %d", err); + FT8_Fifo_deinit(); + return err; +} + +//-------------------- +int FT8_Fifo_service() +{ + if (ft8_stFifo.file_remain <= 0) { + // === Complete file was sent to mediafifo, wait until processed === + ESP_LOGD(TAG, "Service: file completed"); + ft8_stFifo.fifo_rp = FT8_memRead32(REG_MEDIAFIFO_READ); // get the read pointer + + uint64_t tmo = mp_hal_ticks_ms(); + uint8_t res = FT8_busy(); + while (res == 1) { + mp_hal_reset_wdt(); + res = FT8_busy(); + if ((res == 1) && ((mp_hal_ticks_ms()-tmo) > 250)) res = 2; + } + + // wait until all data are precessed + while (ft8_stFifo.fifo_rp < ft8_stFifo.fifo_wp) { + ft8_stFifo.fifo_rp = FT8_memRead32(REG_MEDIAFIFO_READ); + res++; + if ((mp_hal_ticks_ms()-tmo) > 100) { + ESP_LOGW(TAG, "Mediafifo processing timeout (ft8_stFifo.fifo_rp=%d < wp=%d)", ft8_stFifo.fifo_rp, ft8_stFifo.fifo_wp); + if (cmd_burst) eve_select(); + return -1; + } + } + ESP_LOGD(TAG, "Service: finished"); + if (cmd_burst) eve_select(); + return 0; + } + + // === Still some data to send === + uint32_t fifo_free, written=0; + + // Get the read pointer + ft8_stFifo.fifo_rp = FT8_memRead32(REG_MEDIAFIFO_READ); + // and calculate the free fifo space + if (ft8_stFifo.fifo_rp < ft8_stFifo.fifo_wp) fifo_free = (ft8_stFifo.fifo_len - ft8_stFifo.fifo_wp) + ft8_stFifo.fifo_rp; + else fifo_free = ft8_stFifo.fifo_rp - ft8_stFifo.fifo_wp; + // keep minimum of 256 free buffer + if (fifo_free >= MIN_FIFO_FREE) fifo_free -= MIN_FIFO_FREE; + if (fifo_free > ft8_stFifo.max_free) ft8_stFifo.max_free = fifo_free; + if (fifo_free < ft8_stFifo.min_free) ft8_stFifo.min_free = fifo_free; + + if (fifo_free >= MIN_FIFO_FREE) { + // send file block + written = FT8_Fifo_write_file_block(fifo_free); + if (written > 0) FT8_memWrite32(REG_MEDIAFIFO_WRITE, ft8_stFifo.fifo_wp); + } + + //if (written > 0) { + // ESP_LOGD(TAG, "Service: free=%d, written: %d, rd=%d, wp=%d", fifo_free, written, ft8_stFifo.fifo_rp, ft8_stFifo.fifo_wp); + //} + //if (cmd_burst) eve_select(); + return 1; +} + +//------------------------------------------------------------------------------------- +int FT8_sendDataViaMediafifo(FILE *pFile, uint32_t ptr, uint32_t options, uint8_t type) +{ + if (type == 0) { + ESP_LOGD(TAG, "=== Load image"); + FT8_start_cmd(CMD_LOADIMAGE); + FT8_send_long(ptr, options, 0, 2); + eve_deselect(); + FT8_cmd_start(); + } + else if (type == 1) { + ESP_LOGD(TAG, "==== Play video"); + FT8_start_cmd(CMD_PLAYVIDEO); + FT8_send_long(options, 0, 0, 1); + eve_deselect(); + FT8_cmd_start(); + } + else if (type == 2) { + ESP_LOGD(TAG, "=== Start video"); + + FT8_cmd_dl(CMD_VIDEOSTART); + //FT8_send_long(options, 0, 0, 1); + FT8_cmd_execute(250); + ESP_LOGD(TAG, " VIDEOSTART executed"); } else { - spi_dev->host->hw->miso_dlen.usr_miso_dbitlen = 0; - spi_dev->host->hw->user.usr_miso = 0; + ESP_LOGE(TAG, "=== Unknown type"); + return -9; + } + + // update the read and write pointers of mediafifo + FT8_memWrite32(REG_MEDIAFIFO_READ, 0); + FT8_memWrite32(REG_MEDIAFIFO_WRITE, ft8_stFifo.fifo_wp); + + if (type < 2) { + int res, rdptr=0; + uint64_t tmo = mp_hal_ticks_ms(); + mp_hal_set_wdt_tmo(); + // Execute the service to send the whole file + do { + res = FT8_Fifo_service(); + if (res < 0) return -9; + mp_hal_reset_wdt(); + if (rdptr == ft8_stFifo.fifo_rp) { + if ((mp_hal_ticks_ms()-tmo) > 250) { + // read pointer does not advance + ESP_LOGE(TAG, "Mediafifo processing timeout (rdptr=%d < wp=%d)", rdptr, ft8_stFifo.fifo_wp); + FT8_CP_reset(); + return -10; + } + } + else tmo = mp_hal_ticks_ms(); + rdptr = ft8_stFifo.fifo_rp; + } while (res); + + tmo = mp_hal_ticks_ms(); + res = FT8_busy(); + while (res == 1) { + if ((mp_hal_ticks_ms()-tmo) > 250) { + res = 2; + break; + } + mp_hal_reset_wdt(); + res = FT8_busy(); + } + if (res != 0) { + ESP_LOGE(TAG, "Error executing"); + FT8_CP_reset(); + } + + ESP_LOGD(TAG, "Finished"); + return ft8_stFifo.file_remain; } - // Start transfer - spi_dev->host->hw->cmd.usr = 1; - // Wait for SPI bus ready - while (spi_dev->host->hw->cmd.usr); + + return 0; } +#endif +// ==== Basic SPI commands ==== +// Send command to FT8xx, only used in Init function //----------------------------- void FT8_cmdWrite(uint8_t data) { - if (spi_lobo_device_select(eve_spi, 0)) return; - eve_spi->host->hw->data_buf[0] = (uint32_t)data; - _spi_transfer_start(eve_spi, 8, 0); - spi_lobo_device_deselect(eve_spi); + if (eve_select()) return; + eve_spi->handle->host->hw->data_buf[0] = (uint32_t)data; + _spi_transfer_start(eve_spi, 24, 0); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + eve_deselect(); } +// ==== Memory read/write ======================================================================== + +// Prepare 32-bit address to be sent to FT8xx //---------------------------------------------------- uint32_t FT8_address(uint32_t ftAddress, uint8_t mask) { - uint32_t wd = (ftAddress >> 16) & 0x3F; // Memory Write plus high address byte - wd |= ftAddress & 0x0000FF00; // middle address byte - wd |= (ftAddress << 16) & 0x00FF0000; // low address byte & dummy byte + uint32_t wd = ((ftAddress&0x00FF0000) >> 16) | mask; // Memory Write plus high address byte + wd |= (ftAddress & 0x0000FF00); // middle address byte + wd |= ((ftAddress & 0xFF) << 16); // low address byte & dummy byte return wd; } @@ -95,13 +403,14 @@ uint8_t FT8_memRead8(uint32_t ftAddress) { uint8_t ftData8 = 0; - if (spi_lobo_device_select(eve_spi, 0)) return 0; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_READ); - eve_spi->host->hw->data_buf[1] = 0; + if (eve_select()) return 0; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_READ); + eve_spi->handle->host->hw->data_buf[1] = 0; _spi_transfer_start(eve_spi, 40, 40); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready - ftData8 = (uint8_t)eve_spi->host->hw->data_buf[1]; - spi_lobo_device_deselect(eve_spi); + ftData8 = (uint8_t)eve_spi->handle->host->hw->data_buf[1]; + eve_deselect(); return ftData8; // return byte read } @@ -111,15 +420,16 @@ uint16_t FT8_memRead16(uint32_t ftAddress) { uint16_t ftData16 = 0; - if (spi_lobo_device_select(eve_spi, 0)) return 0; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_READ); - eve_spi->host->hw->data_buf[1] = 0; + if (eve_select()) return 0; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_READ); + eve_spi->handle->host->hw->data_buf[1] = 0; _spi_transfer_start(eve_spi, 48, 48); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready - ftData16 = (uint16_t)eve_spi->host->hw->data_buf[1]; - spi_lobo_device_deselect(eve_spi); + ftData16 = (uint16_t)eve_spi->handle->host->hw->data_buf[1]; + eve_deselect(); - return ftData16; // return integer read + return ftData16; // return 16-bit integer read } //---------------------------------------- @@ -127,87 +437,167 @@ uint32_t FT8_memRead32(uint32_t ftAddress) { uint32_t ftData32= 0; - if (spi_lobo_device_select(eve_spi, 0)) return 0; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_READ); - eve_spi->host->hw->data_buf[1] = 0; - _spi_transfer_start(eve_spi, 56, 56); + if (eve_select()) return 0; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_READ); + eve_spi->handle->host->hw->data_buf[1] = 0; + _spi_transfer_start(eve_spi, 64, 64); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready - ftData32 = eve_spi->host->hw->data_buf[1]; - spi_lobo_device_deselect(eve_spi); + ftData32 = eve_spi->handle->host->hw->data_buf[1]; + eve_deselect(); - return ftData32; // return long read + return ftData32; // return 32-bit long read +} + +//---------------------------------------------------------------------- +void FT8_memRead_buffer(uint32_t ftAddress, uint8_t *data, uint16_t len) +{ + spi_transaction_t t; + memset(&t, 0, sizeof(t)); //Zero out the transaction + memset(data, 0, len); + + if (eve_select()) return; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_READ); + _spi_transfer_start(eve_spi, 32, 32); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + + t.length = len * 8; + t.tx_buffer = data; + t.rxlength = len * 8; + t.rx_buffer = data; + + spi_transfer_data_nodma(eve_spi, &t); // Send using direct mode + eve_deselect(); } //----------------------------------------------------- void FT8_memWrite8(uint32_t ftAddress, uint8_t ftData8) { - if (spi_lobo_device_select(eve_spi, 0)) return; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE) | (uint32_t)(ftData8 << 24); + if (eve_select()) return; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE) | (uint32_t)((uint32_t)ftData8 << 24); _spi_transfer_start(eve_spi, 32, 32); - spi_lobo_device_deselect(eve_spi); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + eve_deselect(); } //-------------------------------------------------------- void FT8_memWrite16(uint32_t ftAddress, uint16_t ftData16) { - if (spi_lobo_device_select(eve_spi, 0)) return; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE) | (uint32_t)(ftData16 << 24); - eve_spi->host->hw->data_buf[1] = (uint32_t)(ftData16 >> 8); + if (eve_select()) return; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE) | (uint32_t)((uint32_t)ftData16 << 24); + eve_spi->handle->host->hw->data_buf[1] = (uint32_t)(ftData16 >> 8); // high byte _spi_transfer_start(eve_spi, 40, 40); - spi_lobo_device_deselect(eve_spi); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + eve_deselect(); } //-------------------------------------------------------- void FT8_memWrite32(uint32_t ftAddress, uint32_t ftData32) { - if (spi_lobo_device_select(eve_spi, 0)) return; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE) | ftData32 << 24; - uint32_t wd = ((ftData32 >> 8) & 0xFF) | ((ftData32 >> 16) & 0xFF) | ((ftData32 >> 24) & 0xFF); - eve_spi->host->hw->data_buf[1] = wd; + if (eve_select()) return; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE) | (ftData32 << 24); + eve_spi->handle->host->hw->data_buf[1] = (ftData32 >> 8); _spi_transfer_start(eve_spi, 56, 56); - spi_lobo_device_deselect(eve_spi); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + eve_deselect(); } -//---------------------------------------------------- -static void FT8_send_data(uint8_t *data, uint32_t len) +//----------------------------------------------------------------------- +static int FT8_send_data(uint8_t *data, int data_len, bool check_padding) { - spi_lobo_transaction_t t; - memset(&t, 0, sizeof(t)); //Zero out the transaction - - t.length = len * 8; - t.tx_buffer = data; - t.rxlength = 0; - t.rx_buffer = NULL; + uint8_t padding = 0; + if (check_padding) { + // ensure 4-byte alignment + padding = data_len % 4; + if (padding) padding = 4 - padding; + } - spi_lobo_transfer_data(eve_spi, &t); // Send using direct mode + if ((data_len + padding) <= 64) { + // === Send length <= 64, send directly === + memset((uint8_t *)eve_spi->handle->host->hw->data_buf, 0, 64); + int bits = 0; + int idx = 0; + uint32_t wd = 0; + for (int i=0; ihandle->host->hw->data_buf[idx] = wd; + bits = 0; + idx++; + wd = 0; + } + } + if (bits) eve_spi->handle->host->hw->data_buf[idx] = wd; + _spi_transfer_start(eve_spi, (data_len + padding) * 8, 0); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + } + else { + // === Send length > 64, send using block transfer function === + spi_transaction_t t; + memset(&t, 0, sizeof(t)); //Zero out the transaction + + t.length = data_len * 8; + t.tx_buffer = data; + t.rxlength = 0; + t.rx_buffer = NULL; + + spi_transfer_data_nodma(eve_spi, &t); // Send using direct mode + + if (padding) { + // send padding bytes + eve_spi->handle->host->hw->data_buf[0] = 0; + _spi_transfer_start(eve_spi, padding * 8, 0); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + } + } + return (data_len + padding); } -//----------------------------------------------------------------------------------- -void FT8_memWrite_flash_buffer(uint32_t ftAddress, const uint8_t *data, uint16_t len) +//------------------------------------------------------------------------------------------------------ +int FT8_memWrite_flash_buffer(uint32_t ftAddress, const uint8_t *data, uint16_t len, bool check_padding) { - if (spi_lobo_device_select(eve_spi, 0)) return; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); + if (eve_select()) return 0; + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); _spi_transfer_start(eve_spi, 24, 24); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready - len = (len + 3)&(~3); + int res = FT8_send_data((uint8_t *)data, len, check_padding); - FT8_send_data((uint8_t *)data, len); - - spi_lobo_device_deselect(eve_spi); + eve_deselect(); + return res; } +//----------------- +void FT8_CP_reset() +{ + FT8_memWrite8(REG_CPURESET, 1); // hold co-processor engine in the reset condition + FT8_memWrite16(REG_CMD_READ, 0); // set REG_CMD_READ to 0 + FT8_memWrite16(REG_CMD_WRITE, 0); // set REG_CMD_WRITE to 0 + eve_cmdOffset = 0; // reset eve_cmdOffset + FT8_memWrite8(REG_CPURESET, 0); // set REG_CMD_WRITE to 0 to restart the co-processor engine +} // Check if the graphics processor completed executing the current command list. -// This is the case when REG_CMD_READ matches eve_cmdOffset, indicating that all commands have been executed. +// This is the case when REG_CMD_READ matches REG_CMD_WRITE (eve_cmdOffset), +// indicating that all commands have been executed. //-------------------- uint8_t FT8_busy(void) { - uint16_t cmdBufferRead; + uint16_t cmdBufferRead, cmdBufferWrite; cmdBufferRead = FT8_memRead16(REG_CMD_READ); // read the graphics processor read pointer + cmdBufferWrite = FT8_memRead16(REG_CMD_WRITE); // read the graphics processor write pointer - if (eve_cmdOffset != cmdBufferRead) return 1; - else return 0; + if (cmdBufferRead == 0xFFF) { + // EVE co-processor engine fault + FT8_CP_reset(); + ESP_LOGE(TAG, "EVE co-processor fault"); + return 2; + } + + if (cmdBufferWrite != cmdBufferRead) return 1; + else return 0; } //------------------------------ @@ -216,11 +606,12 @@ uint32_t FT8_get_touch_tag(void) uint32_t value; value = FT8_memRead32(REG_TOUCH_TAG); - return value; + return (value & 0xFF); } -// Order the command coprocessor to start processing its FIFO queue and do not wait for completion +// Order the command coprocessor to start processing its FIFO queue +// do not wait for completion ! //---------------------- void FT8_cmd_start(void) { @@ -229,12 +620,23 @@ void FT8_cmd_start(void) } -/// Order the command coprocessor to start processing its FIFO queue and wait for completion -//------------------------ -void FT8_cmd_execute(void) +// Order the command coprocessor to start processing its FIFO queue +// Wait for completion ! +//------------------------------ +bool FT8_cmd_execute(int tmo_ms) { FT8_cmd_start(); - while (FT8_busy()); + uint64_t tmo = mp_hal_ticks_ms(); + uint8_t res = FT8_busy(); + while (res == 1) { + mp_hal_reset_wdt(); + res = FT8_busy(); + if ((res == 1) && ((mp_hal_ticks_ms()-tmo) > tmo_ms)) { + FT8_CP_reset(); + res = 2; + } + } + return (res == 0); } //-------------------------- @@ -243,6 +645,14 @@ void FT8_get_cmdoffset(void) eve_cmdOffset = FT8_memRead16(REG_CMD_WRITE); } +// make current value of cmdOffset available while limiting access to that var to the FT8_commands module +//--------------------------------- +uint16_t FT8_report_cmdoffset(void) +{ + return (eve_cmdOffset); +} + + //---------------------------------------- void FT8_inc_cmdoffset(uint16_t increment) { @@ -251,10 +661,12 @@ void FT8_inc_cmdoffset(uint16_t increment) } +// ==== Write to EVE command FIFO ============================================================================ /* -These eliminate the overhead of transmitting the command fifo address with every single command, just wrap a sequence of commands -with these and the address is only transmitted once at the start of the block. -Be careful to not use any functions in the sequence that do not address the command-fifo as for example any FT8_mem...() function. +These eliminate the overhead of transmitting the command fifo address with every single command, +just wrap a sequence of commands with these and the address is only transmitted once at the start of the block. +Be careful to not use any functions in the sequence that do not address the command-fifo, +as for example any FT8_mem...() function. */ //---------------------------- void FT8_start_cmd_burst(void) @@ -263,16 +675,30 @@ void FT8_start_cmd_burst(void) cmd_burst = 42; ftAddress = FT8_RAM_CMD + eve_cmdOffset; - if (spi_lobo_device_select(eve_spi, 0)) return; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); + if (eve_select()) return; + + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); _spi_transfer_start(eve_spi, 24, 24); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready } //-------------------------- void FT8_end_cmd_burst(void) { cmd_burst = 0; - spi_lobo_device_deselect(eve_spi); + eve_deselect(); +} + +// Write a string to coprocessor memory in context of a command +// no chip-select, just plain spi-transfers +//------------------------------------- +void FT8_write_string(const char *text) +{ + size_t textlen = strlen(text); + // sent string must be terminated with null character (ASCII 0) + int res = FT8_send_data((uint8_t *)text, textlen+1, true); + + FT8_inc_cmdoffset(res); } // Begin a coprocessor command @@ -281,20 +707,18 @@ void FT8_start_cmd(uint32_t command) { uint32_t ftAddress; - uint32_t wd = command & 0xff; - wd |= (uint32_t)((command >> 8) & 0xff); - wd |= (uint32_t)((command >> 16) & 0xff); - wd |= (uint32_t)((command >> 24) & 0xff); + if (eve_select()) return; - if (cmd_burst == 0) { + if (cmd_burst == 0) { ftAddress = FT8_RAM_CMD + eve_cmdOffset; - if (spi_lobo_device_select(eve_spi, 0)) return; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); - _spi_transfer_start(eve_spi, 24, 24); // send address + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); + _spi_transfer_start(eve_spi, 24, 24); // send address + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready } - eve_spi->host->hw->data_buf[0] = wd; + eve_spi->handle->host->hw->data_buf[0] = command; _spi_transfer_start(eve_spi, 32, 32); + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready FT8_inc_cmdoffset(4); // update the command-ram pointer } @@ -314,104 +738,51 @@ void FT8_start_cmd(uint32_t command) void FT8_cmd_dl(uint32_t command) { FT8_start_cmd(command); - if (cmd_burst == 0) { - spi_lobo_device_deselect(eve_spi); - } -} - - -// Write a string to coprocessor memory in context of a command -// no chip-select, just plain spi-transfers -//------------------------------------- -void FT8_write_string(const char *text) -{ - uint8_t textlen = strlen(text); - uint8_t padding = 0; - - spi_lobo_transaction_t t; - memset(&t, 0, sizeof(t)); //Zero out the transaction - - t.length = textlen * 8; - t.tx_buffer = text; - t.rxlength = 0; - t.rx_buffer = NULL; - - spi_lobo_transfer_data(eve_spi, &t); // Send using direct mode - - padding = strlen(text) % 4; /* 0, 1, 2 or 3 */ - padding = 4-padding; /* 4, 3, 2, 1 */ - - eve_spi->host->hw->data_buf[0] = 0; - _spi_transfer_start(eve_spi, padding * 8, 0); - - FT8_inc_cmdoffset(textlen + padding); + if (cmd_burst == 0) eve_deselect(); } // ============================================ // ==== Commands to draw graphics objects: ==== // ============================================ +// Send number of 16-bit parameters +// 'len' can have the value 2, 4, 6 or 8 //------------------------------------------------------------------------------------------------------------------------------------------- static void FT8_send_params(int16_t p1, int16_t p2, int16_t p3, uint16_t p4, uint16_t p5, uint16_t p6, uint16_t p7, uint16_t p8, uint8_t len) { - uint32_t wd = (uint32_t)(p1 & 0xFF); - wd |= (uint32_t)(p1 & 0xFF00); - wd |= (uint32_t)((p2 & 0xFF) << 16); - wd |= (uint32_t)((p2 & 0xFF00) << 16); - eve_spi->host->hw->data_buf[0] = wd; + eve_spi->handle->host->hw->data_buf[0] = ((uint32_t)p1 | (uint32_t)p2 << 16); if (len < 4) goto send; - wd = (uint32_t)(p3 & 0xFF); - wd |= (uint32_t)(p3 & 0xFF00); - wd |= (uint32_t)((p4 & 0xFF) << 16); - wd |= (uint32_t)((p4 & 0xFF00) << 16); - eve_spi->host->hw->data_buf[1] = wd; + eve_spi->handle->host->hw->data_buf[1] = ((uint32_t)p3 | (uint32_t)p4 << 16); if (len < 6) goto send; - wd = (uint32_t)(p5 & 0xFF); - wd |= (uint32_t)(p5 & 0xFF00); - wd |= (uint32_t)((p6 & 0xFF) << 16); - wd |= (uint32_t)((p6 & 0xFF00) << 16); - eve_spi->host->hw->data_buf[2] = wd; + eve_spi->handle->host->hw->data_buf[2] = ((uint32_t)p5 | (uint32_t)p6 << 16); if (len < 8) goto send; - wd = (uint32_t)(p7 & 0xFF); - wd |= (uint32_t)(p7 & 0xFF00); - wd |= (uint32_t)((p8 & 0xFF) << 16); - wd |= (uint32_t)((p8 & 0xFF00) << 16); - eve_spi->host->hw->data_buf[2] = wd; + eve_spi->handle->host->hw->data_buf[3] = ((uint32_t)p7 | (uint32_t)p8 << 16); send: _spi_transfer_start(eve_spi, len*16, len*16); // send + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready FT8_inc_cmdoffset(len * 2); } -//--------------------------------------------------------------------------------- -static void FT8_send_long(uint32_t val1, uint32_t val2, uint32_t val3, uint8_t len) +// Send number of 32-bit longs +//-------------------------------------------------------------------------- +void FT8_send_long(uint32_t val1, uint32_t val2, uint32_t val3, uint8_t len) { - uint32_t wd = (uint32_t)(val1 & 0xFF); - wd |= (uint32_t)((val1 >> 8) & 0xFF); - wd |= (uint32_t)((val1 >> 16) & 0xFF); - wd |= (uint32_t)((val1 >> 24) & 0xFF); - eve_spi->host->hw->data_buf[0] = wd; + eve_spi->handle->host->hw->data_buf[0] = val1; if (len < 2) goto send; - wd = (uint32_t)(val2 & 0xFF); - wd |= (uint32_t)((val2 >> 8) & 0xFF); - wd |= (uint32_t)((val2 >> 16) & 0xFF); - wd |= (uint32_t)((val2 >> 24) & 0xFF); - eve_spi->host->hw->data_buf[1] = wd; + eve_spi->handle->host->hw->data_buf[1] = val2; if (len < 3) goto send; - wd = (uint32_t)(val3 & 0xFF); - wd |= (uint32_t)((val3 >> 8) & 0xFF); - wd |= (uint32_t)((val3 >> 16) & 0xFF); - wd |= (uint32_t)((val3 >> 24) & 0xFF); - eve_spi->host->hw->data_buf[2] = wd; + eve_spi->handle->host->hw->data_buf[2] = val3; send: _spi_transfer_start(eve_spi, len*32, len*32); // send + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready FT8_inc_cmdoffset(len * 4); } @@ -424,7 +795,7 @@ void FT8_cmd_text(int16_t x0, int16_t y0, int16_t font, uint16_t options, const FT8_send_params(x0, y0, font, options, 0, 0, 0, 0, 4); FT8_write_string(text); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } // Draw a button with text @@ -435,7 +806,7 @@ void FT8_cmd_button(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t font FT8_send_params(x0, y0, w0, h0, font, options, 0, 0, 6); FT8_write_string(text); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } // Draw a clock @@ -445,7 +816,7 @@ void FT8_cmd_clock(int16_t x0, int16_t y0, int16_t r0, uint16_t options, uint16_ FT8_start_cmd(CMD_CLOCK); FT8_send_params(x0, y0, r0, options, hours, minutes, seconds, millisecs, 8); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //---------------------------------- @@ -454,7 +825,7 @@ void FT8_cmd_bgcolor(uint32_t color) FT8_start_cmd(CMD_BGCOLOR); FT8_send_long(color, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //---------------------------------- @@ -463,7 +834,7 @@ void FT8_cmd_fgcolor(uint32_t color) FT8_start_cmd(CMD_FGCOLOR); FT8_send_long(color, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //------------------------------------ @@ -472,7 +843,7 @@ void FT8_cmd_gradcolor(uint32_t color) FT8_start_cmd(CMD_GRADCOLOR); FT8_send_long(color, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //------------------------------------------------------------------------------------------------------------------------------------ @@ -481,16 +852,19 @@ void FT8_cmd_gauge(int16_t x0, int16_t y0, int16_t r0, uint16_t options, uint16_ FT8_start_cmd(CMD_GAUGE); FT8_send_params(x0, y0, r0, options, major, minor, val, range, 8); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //------------------------------------------------------------------------------------------------- void FT8_cmd_gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1) { FT8_start_cmd(CMD_GRADIENT); - FT8_send_params(x0, y0, (uint16_t)rgb0, (uint16_t)(rgb0 >> 16), x1, y1, (uint16_t)rgb1, (uint16_t)(rgb1 >> 16), 8); + FT8_send_params(x0, y0, 0, 0, 0, 0, 0, 0, 2); + FT8_send_long(rgb0, 0, 0, 1); + FT8_send_params(x1, y1, 0, 0, 0, 0, 0, 0, 2); + FT8_send_long(rgb1, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //----------------------------------------------------------------------------------------------------------------- @@ -501,7 +875,7 @@ void FT8_cmd_keys(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t font, FT8_send_params(x0, y0, w0, h0, font, options, 0, 0, 6); FT8_write_string(text); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //------------------------------------------------------------------------------------------------------------------- @@ -510,7 +884,7 @@ void FT8_cmd_progress(int16_t x0, int16_t y0, int16_t w0, int16_t h0, uint16_t o FT8_start_cmd(CMD_PROGRESS); FT8_send_params(x0, y0, w0, h0, options, val, range, 0, 8); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //----------------------------------------------------------------------------------------------------------------------------------- @@ -519,16 +893,16 @@ void FT8_cmd_scrollbar(int16_t x0, int16_t y0, int16_t w0, int16_t h0, uint16_t FT8_start_cmd(CMD_SCROLLBAR); FT8_send_params(x0, y0, w0, h0, options, val, size, range, 8); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } - +//----------------------------------------------------------------------------------------------------------------- void FT8_cmd_slider(int16_t x1, int16_t y1, int16_t w1, int16_t h1, uint16_t options, uint16_t val, uint16_t range) { FT8_start_cmd(CMD_SLIDER); FT8_send_params(x1, y1, w1, h1, options, val, range, 0, 8); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //----------------------------------------------------------------------------------- @@ -537,7 +911,7 @@ void FT8_cmd_dial(int16_t x0, int16_t y0, int16_t r0, uint16_t options, uint16_t FT8_start_cmd(CMD_DIAL); FT8_send_params(x0, y0, r0, options, val, 0, 0, 0, 6); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //----------------------------------------------------------------------------------------------------------------------- @@ -547,91 +921,84 @@ void FT8_cmd_toggle(int16_t x0, int16_t y0, int16_t w0, int16_t font, uint16_t o FT8_send_params(x0, y0, w0, font, options, state, 0, 0, 6); FT8_write_string(text); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } - -#ifdef FT8_81X_ENABLE +#ifdef CONFIG_EVE_CHIP_TYPE1 //--------------------------------- void FT8_cmd_setbase(uint32_t base) { FT8_start_cmd(CMD_SETBASE); - FT8_send_params((uint16_t)base, (uint16_t)(base >> 16), 0, 0, 0, 0, 0, 0, 2); + FT8_send_long(base, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //---------------------------------------------------------------------------------- void FT8_cmd_setbitmap(uint32_t addr, uint16_t fmt, uint16_t width, uint16_t height) { FT8_start_cmd(CMD_SETBITMAP); - FT8_send_params((uint16_t)addr, (uint16_t)(addr >> 16), fmt, width, height, 0, 0, 0, 6); + FT8_send_long(addr, 0, 0, 1); + FT8_send_params(fmt, width, height, 0, 0, 0, 0, 0, 4); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } #endif +//------------------------------------------- +void FT8_cmd_bitmapXY(uint16_t x, uint16_t y) +{ + FT8_cmd_dl(DL_BEGIN | FT8_BITMAPS); + FT8_cmd_dl(VERTEX2F(x*16, y*16)); + FT8_cmd_dl(DL_END); +} + //----------------------------------------------------------------------------------------- void FT8_cmd_number(int16_t x0, int16_t y0, int16_t font, uint16_t options, int32_t number) { FT8_start_cmd(CMD_NUMBER); - FT8_send_params(x0, y0, font, options, (uint16_t)number, (uint16_t)(number >> 16), 0, 0, 6); + FT8_send_params(x0, y0, font, options, 0, 0, 0, 0, 4); + FT8_send_long(number, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } // ======================================== // ==== Commands to operate on memory: ==== // ======================================== +//---------------------------------------------- void FT8_cmd_memzero(uint32_t ptr, uint32_t num) { FT8_start_cmd(CMD_MEMZERO); FT8_send_long(ptr, num, 0, 2); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } - +//------------------------------------------------------------ void FT8_cmd_memset(uint32_t ptr, uint8_t value, uint32_t num) { FT8_start_cmd(CMD_MEMSET); FT8_send_long(ptr, (uint32_t)value, num, 3); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } - -/* -void FT8_cmd_memwrite(uint32_t dest, uint32_t num, const uint8_t *data) +// Write bytes into memory +// If the number of bytes is not a multiple of 4, then 1, 2 or 3 bytes should be +// appended to ensure 4-byte alignment of the next command +//--------------------------------------------------------------------- +void FT8_cmd_memwrite(uint32_t dest, const uint8_t *data, uint32_t num) { FT8_start_cmd(CMD_MEMWRITE); - spi_transmit((uint8_t)(dest)); - spi_transmit((uint8_t)(dest >> 8)); - spi_transmit((uint8_t)(dest >> 16)); - spi_transmit((uint8_t)(dest >> 24)); - - spi_transmit((uint8_t)(num)); - spi_transmit((uint8_t)(num >> 8)); - spi_transmit((uint8_t)(num >> 16)); - spi_transmit((uint8_t)(num >> 24)); - - num = (num + 3)&(~3); + FT8_send_long(dest, num, 0, 2); + int res = FT8_send_data((uint8_t *)data, num, true); + FT8_inc_cmdoffset(res); - for(count=0;count 0) - { - block_len = bytes_left>4000 ? 4000:bytes_left; - - ftAddress = FT8_RAM_CMD + eve_cmdOffset; - spi_lobo_device_select(eve_spi, 0); + uint8_t * buff = NULL; - eve_spi->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); - _spi_transfer_start(eve_spi, 24, 24); // send address - - spi_flash_write(data, block_len); - spi_lobo_device_deselect(eve_spi); - - data += block_len; - bytes_left -= block_len; - FT8_cmd_execute(); - } + if (type == 1) { + FT8_start_cmd(CMD_LOADIMAGE); + FT8_send_long(ptr, options, 0, 2); + eve_deselect(); } + else if (type == 2) { + FT8_start_cmd(CMD_INFLATE); + FT8_send_long(ptr, 0, 0, 1); + eve_deselect(); + } + + if (fhndl == NULL) return -2; + buff = malloc(1024); + if (buff == NULL) return -3; + + bytes_sent = 0; + bytes_left = len; + + while (bytes_left > 0) { + // read block from file + block_len = (bytes_left > 1024) ? 1024 : bytes_left; + block_len = fread(buff, 1, block_len, fhndl); + if (block_len <= 0) { + ESP_LOGE(TAG, "File read error [%d]: sent=%d, remaining=%d", block_len, bytes_sent, bytes_left); + break; + } + + if (type < 3) { + // sending via command buffer + ftAddress = FT8_RAM_CMD + eve_cmdOffset; + eve_select(); + + eve_spi->handle->host->hw->data_buf[0] = FT8_address(ftAddress, MEM_WRITE); + _spi_transfer_start(eve_spi, 24, 24); // send address + while (eve_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + + // Send data block (alligned to 4 bytes) + res = FT8_send_data(buff, block_len, true); + FT8_inc_cmdoffset(res); + eve_deselect(); + + bytes_left -= block_len; + bytes_sent += res; + if (!FT8_cmd_execute(250)) { + free(buff); + ESP_LOGE(TAG, "Execute error: sent=%d, remaining=%d", bytes_sent, bytes_left); + return (bytes_sent * -1); + } + } + else { + // send directly to RAM_G + res = FT8_memWrite_flash_buffer(ptr + bytes_sent, buff, block_len, true); + + bytes_left -= block_len; + bytes_sent += res; + } + } + free(buff); + return bytes_sent; } -#ifdef FT8_81X_ENABLE +#ifdef CONFIG_EVE_CHIP_TYPE1 // this is meant to be called outside display-list building, // does not support cmd-burst //------------------------------------------------- @@ -722,7 +1119,16 @@ void FT8_cmd_mediafifo(uint32_t ptr, uint32_t size) FT8_start_cmd(CMD_MEDIAFIFO); FT8_send_long(ptr, size, 0, 2); - spi_lobo_device_deselect(eve_spi); + eve_deselect(); +} + +//------------------------------------ +void FT8_cmd_videoframe(uint32_t addr) +{ + FT8_start_cmd(CMD_VIDEOFRAME); + FT8_send_long(addr, ft8_stFifo.fifo_buff-4, 0, 2); + + if (cmd_burst == 0) eve_deselect(); } #endif @@ -737,7 +1143,7 @@ void FT8_cmd_translate(int32_t tx, int32_t ty) FT8_start_cmd(CMD_TRANSLATE); FT8_send_long(tx, ty, 0, 2); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //---------------------------------------- @@ -746,7 +1152,7 @@ void FT8_cmd_scale(int32_t sx, int32_t sy) FT8_start_cmd(CMD_SCALE); FT8_send_long(sx, sy, 0, 2); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //------------------------------ @@ -755,9 +1161,16 @@ void FT8_cmd_rotate(int32_t ang) FT8_start_cmd(CMD_ROTATE); FT8_send_long(ang, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } +//---------------------- +void FT8_cmd_setmatrix() +{ + FT8_start_cmd(CMD_SETMATRIX); + + if (cmd_burst == 0) eve_deselect(); +} /* * the description in the programmers guide is strange for this function @@ -774,7 +1187,7 @@ void FT8_cmd_getmatrix(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, in FT8_send_long(a, b, c, 3); FT8_send_long(d, e, f, 3); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } @@ -788,7 +1201,7 @@ void FT8_cmd_calibrate(void) FT8_start_cmd(CMD_CALIBRATE); FT8_send_long(0, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //--------------------------------- @@ -797,67 +1210,76 @@ void FT8_cmd_interrupt(uint32_t ms) FT8_start_cmd(CMD_INTERRUPT); FT8_send_long(ms, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } -#ifdef FT8_81X_ENABLE +#ifdef CONFIG_EVE_CHIP_TYPE1 //--------------------------------------------------- void FT8_cmd_romfont(uint32_t font, uint32_t romslot) { FT8_start_cmd(CMD_ROMFONT); FT8_send_long(font, romslot & 0xFFFF, 0, 2); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } -#endif -//----------------------------------------------- -void FT8_cmd_setfont(uint32_t font, uint32_t ptr) -{ - FT8_start_cmd(CMD_SETFONT); - FT8_send_long(font, ptr, 0, 2); - - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); -} - - -#ifdef FT8_81X_ENABLE //-------------------------------------------------------------------- void FT8_cmd_setfont2(uint32_t font, uint32_t ptr, uint32_t firstchar) { - FT8_start_cmd(CMD_SETFONT2); - FT8_send_long(font, ptr, firstchar, 3); + FT8_start_cmd(CMD_SETFONT2); + FT8_send_long(font, ptr, firstchar, 3); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //-------------------------------- void FT8_cmd_setrotate(uint32_t r) { - FT8_start_cmd(CMD_SETROTATE); - FT8_send_long(r, 0, 0, 1); + FT8_start_cmd(CMD_SETROTATE); + FT8_send_long(r, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //-------------------------------------- void FT8_cmd_setscratch(uint32_t handle) { - FT8_start_cmd(CMD_SETSCRATCH); - FT8_send_long(handle, 0, 0, 1); + FT8_start_cmd(CMD_SETSCRATCH); + FT8_send_long(handle, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } + +//------------------------------------------------------------------------------------------------ +void FT8_cmd_snapshot2(uint32_t fmt, uint32_t ptr, int16_t x0, int16_t y0, int16_t w0, int16_t h0) +{ + FT8_start_cmd(CMD_SNAPSHOT2); + FT8_send_long(fmt, ptr, 0, 2); + FT8_send_params(x0, y0, w0, h0, 0, 0, 0, 0, 4); + + if (cmd_burst == 0) eve_deselect(); +} + #endif +//----------------------------------------------- +void FT8_cmd_setfont(uint32_t font, uint32_t ptr) +{ + FT8_start_cmd(CMD_SETFONT); + FT8_send_long(font, ptr, 0, 2); + + if (cmd_burst == 0) eve_deselect(); +} + //-------------------------------------------------------------------------------------------------- void FT8_cmd_sketch(int16_t x0, int16_t y0, uint16_t w0, uint16_t h0, uint32_t ptr, uint16_t format) { FT8_start_cmd(CMD_SKETCH); - FT8_send_params(x0, y0, w0, h0, (uint16_t)ptr, (uint16_t)(ptr >> 16), 0, 0, 8); + FT8_send_params(x0, y0, w0, h0, 0, 0, 0, 0, 4); + FT8_send_long(ptr, (uint32_t)format, 0, 2); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //--------------------------------- @@ -866,20 +1288,8 @@ void FT8_cmd_snapshot(uint32_t ptr) FT8_start_cmd(CMD_SNAPSHOT); FT8_send_long(ptr, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); -} - - -#ifdef FT8_81X_ENABLE -//------------------------------------------------------------------------------------------------ -void FT8_cmd_snapshot2(uint32_t fmt, uint32_t ptr, int16_t x0, int16_t y0, int16_t w0, int16_t h0) -{ - FT8_start_cmd(CMD_SNAPSHOT2); - FT8_send_params((uint16_t)fmt, (uint16_t)(fmt >> 16), (uint16_t)ptr, (uint16_t)(ptr >> 16), x0, y0, w0, h0, 8); - - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } -#endif //-------------------------------------------------------------------------- void FT8_cmd_spinner(int16_t x0, int16_t y0, uint16_t style, uint16_t scale) @@ -887,7 +1297,7 @@ void FT8_cmd_spinner(int16_t x0, int16_t y0, uint16_t style, uint16_t scale) FT8_start_cmd(CMD_SPINNER); FT8_send_params(x0, y0, style, scale, 0, 0, 0, 0, 4); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //----------------------------------------------------------------------------- @@ -896,7 +1306,7 @@ void FT8_cmd_track(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t tag) FT8_start_cmd(CMD_TRACK); FT8_send_params(x0, y0, w0, h0, tag, 0, 0, 0, 6); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } @@ -904,25 +1314,25 @@ void FT8_cmd_track(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t tag) // ==== Commands that return values by writing to the command-fifo ==== // ==================================================================== - /* * This is handled by having this functions return the offset address on the command-fifo from * which the results can be fetched after execution: FT8_memRead32(FT8_RAM_CMD + offset) * - * Note: yes, these are different than the functions in the Programmers Guide from FTDI, + * Note: these are different than the functions in the Programmers Guide from FTDI, this is because I have no idea why anyone would want to pass "result" as an actual argument to these functions - when this only marks the offset the command-processor is writing to, - it may even be okay to not transfer anything at all, - just advance the offset by 4 bytes + when this only marks the offset the command-processor is writing to. + It may even be okay to not transfer anything at all, just advance the offset by 4 bytes * Example of using FT8_cmd_memcrc: offset = FT8_cmd_memcrc(my_ptr_to_some_memory_region, some_amount_of_bytes); - FT8_cmd_execute(); + FT8_cmd_execute(250); crc32 = FT8_memRead32(FT8_RAM_CMD + offset); */ +// Compute a CRC-32 for memory segment +// returns offset pointing to the CRC value //------------------------------------------------- uint16_t FT8_cmd_memcrc(uint32_t ptr, uint32_t num) { @@ -932,11 +1342,12 @@ uint16_t FT8_cmd_memcrc(uint32_t ptr, uint32_t num) FT8_send_long(ptr, num, 0, 3); offset = eve_cmdOffset - 4; - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); return offset; } +// Get the end memory address of data inflated by CMD_INFLATE //--------------------------- uint16_t FT8_cmd_getptr(void) { @@ -946,11 +1357,12 @@ uint16_t FT8_cmd_getptr(void) FT8_send_long(0, 0, 0, 1); offset = eve_cmdOffset - 4; - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); return offset; } +// Read a register value, returns offset pointing to the register value //------------------------------------ uint16_t FT8_cmd_regread(uint32_t ptr) { @@ -960,43 +1372,42 @@ uint16_t FT8_cmd_regread(uint32_t ptr) FT8_send_long(ptr, 0, 0, 2); offset = eve_cmdOffset - 4; - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); return offset; } - /* + * Get the image properties decompressed by CMD_LOADIMAGE + * * Be aware that this returns the first offset pointing to "width", - * in order to also read "height" you need to: + * in order to also read "height" you need to execute: offset = FT8_cmd_getprops(my_last_picture_pointer); - FT8_cmd_execute(); + FT8_cmd_execute(250); width = FT8_memRead32(FT8_RAM_CMD + offset); offset += 4; offset &= 0x0fff; height = FT8_memRead32(FT8_RAM_CMD + offset); */ - //------------------------------------- uint16_t FT8_cmd_getprops(uint32_t ptr) { uint16_t offset; - FT8_start_cmd(CMD_REGREAD); + FT8_start_cmd(CMD_GETPROPS); FT8_send_long(ptr, 0, 0, 3); offset = eve_cmdOffset - 8; - eve_cmdOffset -= 4; - eve_cmdOffset &= 0x0fff; - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); return offset; } -// ======================================================================================================================================== -// ==== meta-commands, sequences of several display-list entries condensed into simpler to use functions at the price of some overhead ==== -// ======================================================================================================================================== +// =============================================================================== +// ==== meta-commands, sequences of several display-list entries ==== +// ==== condensed into simpler to use functions at the price of some overhead ==== +// =============================================================================== //------------------------------------------------------- void FT8_cmd_point(int16_t x0, int16_t y0, uint16_t size) @@ -1009,7 +1420,7 @@ void FT8_cmd_point(int16_t x0, int16_t y0, uint16_t size) calc2 = VERTEX2F(x0 * 16, y0 * 16); FT8_send_long(calc1, calc2, DL_END, 3); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); } //------------------------------------------------------------------------------- @@ -1025,7 +1436,27 @@ void FT8_cmd_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t width FT8_send_long(calc1, calc2, calc3, 3); FT8_send_long(DL_END, 0, 0, 1); - if (cmd_burst == 0) spi_lobo_device_deselect(eve_spi); + if (cmd_burst == 0) eve_deselect(); +} + +//------------------------------------------------------------------------------- +void FT8_cmd_strip(uint16_t *data, uint16_t length, uint8_t type, uint16_t width) +{ + if ((type < FT8_LINE_STRIP) || (type > FT8_EDGE_STRIP_B)) return; + + uint32_t calc, lwidth; + + FT8_start_cmd((DL_BEGIN | type)); + + lwidth = LINE_WIDTH(width * 16); + FT8_send_long(lwidth, 0, 0, 1); + for (int i=0; imiso); + gpio_pad_select_gpio(dconfig->mosi); + gpio_pad_select_gpio(dconfig->sck); + + gpio_set_direction(dconfig->miso, GPIO_MODE_INPUT); + gpio_set_pull_mode(dconfig->miso, GPIO_PULLUP_ONLY); + gpio_set_direction(dconfig->mosi, GPIO_MODE_OUTPUT); + gpio_set_direction(dconfig->sck, GPIO_MODE_OUTPUT); + } + + gpio_pad_select_gpio(dconfig->cs); + gpio_set_direction(dconfig->cs, GPIO_MODE_OUTPUT); + gpio_set_level(dconfig->cs, 1); + + if (dconfig->pd >= 0) { + gpio_pad_select_gpio(dconfig->pd); + gpio_set_direction(dconfig->pd, GPIO_MODE_OUTPUT); + gpio_set_level(dconfig->pd, 0); + } + eve_spibus_is_init = 1; +} + +//------------------------------------------------- +static esp_err_t EVE_spiInit(eve_config_t *dconfig) { - uint8_t gpio; - uint8_t chipid; - uint8_t timeout = 0; + esp_err_t ret; - //FT8_pdn_set(); - vTaskDelay(10 / portTICK_RATE_MS); // minimum time for power-down is 5ms - //FT8_pdn_clear(); - vTaskDelay(21 / portTICK_RATE_MS); // minimum time to allow from rising PD_N to first access is 20ms - - // FT8_cmdWrite(FT8_CORERST); // reset, only required for warmstart if PowerDown line is not used + /*int used_spi = spi_host_used_by_sdspi(); + if ((used_spi != 0) && (used_spi == dconfig->host)) { + // change spi host + if (used_spi == VSPI_HOST) eve_spi->spihost = HSPI_HOST; + else eve_spi->spihost = VSPI_HOST; + ESP_LOGW(TAG, "spi bus changed (%d -> %d)", used_spi, eve_spi->spihost); + } + else eve_spi->spihost = dconfig->host;*/ + + eve_spi->spihost = dconfig->host; + ESP_LOGD(TAG, "Using spi bus %d", eve_spi->spihost); + eve_spi->buscfg = SPIbus_configs[eve_spi->spihost]; + if (eve_spi->buscfg == NULL) { + ESP_LOGE(TAG, "spi bus %d not available ", eve_spi->spihost); + return ESP_ERR_INVALID_ARG; + } + + eve_spi->dma_channel = 1; + eve_spi->curr_clock = 8000000; // for initialization set the clock to 8MHz + eve_spi->handle = NULL; + eve_spi->cs = dconfig->cs; + eve_spi->dc = 0; + eve_spi->selected = 0; + + eve_spi->buscfg->miso_io_num = dconfig->miso; // set SPI MISO pin + eve_spi->buscfg->mosi_io_num = dconfig->mosi; // set SPI MOSI pin + eve_spi->buscfg->sclk_io_num = dconfig->sck; // set SPI CLK pin + eve_spi->buscfg->quadwp_io_num = -1; + eve_spi->buscfg->quadhd_io_num = -1; + eve_spi->buscfg->max_transfer_sz = 6*1024; + + eve_spi->devcfg.clock_speed_hz = eve_spi->curr_clock; // Initial clock + eve_spi->devcfg.duty_cycle_pos = 128; // 50% duty cycle + eve_spi->devcfg.mode = 0; // SPI mode 0 + eve_spi->devcfg.spics_io_num = -1; // we will use external CS pin + eve_spi->devcfg.queue_size = 1; // we need only one transaction + eve_spi->devcfg.flags = 0; // ALWAYS SET to FULL DUPLEX MODE for EVE display spi + + // ================================================================== + // ==== Initialize the SPI bus and attach the LCD to the SPI bus ==== + ret = add_extspi_device(eve_spi); + if (ret != ESP_OK) { + return ret; + } + + ESP_LOGD(TAG, "SPI bus configured (%d)", eve_spi->spihost); + spi_is_init = 1; - if (FT8_HAS_CRYSTAL != 0) FT8_cmdWrite(FT8_CLKEXT); // setup FT8xx for external clock - else FT8_cmdWrite(FT8_CLKINT); // setup FT8xx for internal clock + // ==== Test select/deselect ==== + ret = spi_device_select(eve_spi, 1); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error selecting display device"); + } + vTaskDelay(10 / portTICK_RATE_MS); + ret = spi_device_deselect(eve_spi); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error deselecting display device"); + } - FT8_cmdWrite(FT8_ACTIVE); // start FT8xx + ESP_LOGI(TAG, "Attached display device, speed=%u", spi_get_speed(eve_spi)); + ESP_LOGI(TAG, "Bus uses native pins: %s", spi_uses_native_pins(eve_spi->handle) ? "true" : "false"); - chipid = FT8_memRead8(REG_ID); // Read ID register - // if chip id is not 0x7c, continue to read it until it is, - // FT81x may need a moment for it's power on self test - while(chipid != 0x7C) { - chipid = FT8_memRead8(REG_ID); - vTaskDelay(2 / portTICK_RATE_MS); - timeout++; - if (timeout > 100) return 0; + return ESP_OK; +} + +//---------------------------------------- +static bool _ft8xx_detect(uint32_t reg_id) +{ + uint8_t chipid = 0; + uint8_t timeout = 0; + // if chip id is not 0x7c, continue to read it until it is, + // FT81x may need a moment for it's power on self test + while (chipid != 0x7C) { + chipid = FT8_memRead8(reg_id); + vTaskDelay(1 / portTICK_RATE_MS); + timeout++; + if (timeout > 200) return false; + } + return true; +} +//============================================================================ +esp_err_t FT8_init(eve_config_t *dconfig, exspi_device_handle_t *disp_spi_dev) +{ + uint32_t chip_type = 0; + esp_err_t ret; + + eve_spi = disp_spi_dev; + if (spi_is_init == 0) { + EVE_PinsInit(dconfig); + ret = EVE_spiInit(dconfig); + if (ret != ESP_OK) { + eve_spi->handle = NULL; + eve_spi = NULL; + return ret; + } + } + + vTaskDelay(6 / portTICK_RATE_MS); + if (dconfig->pd >= 0) { + gpio_set_level(dconfig->pd, 0); + vTaskDelay(7 / portTICK_RATE_MS); // minimum time for power-down is 5ms + gpio_set_level(dconfig->pd, 1); + vTaskDelay(25 / portTICK_RATE_MS); // minimum time to allow from rising PD_N to first access is 20ms + } + else { + FT8_cmdWrite(FT8_CORERST); // reset, only required for warm start if PowerDown line is not used + vTaskDelay(25 / portTICK_RATE_MS); // minimum time to allow from rising PD_N to first access is 20ms } - FT8_memWrite8(REG_PCLK, 0x00); // set PCLK to zero - don't clock the LCD until later - FT8_memWrite8(REG_PWM_DUTY, 10); // turn off backlight - - // *** Initialize Display - FT8_memWrite16(REG_HSIZE, FT8_HSIZE); // active display width - FT8_memWrite16(REG_HCYCLE, FT8_HCYCLE); // total number of clocks per line, including front/back porch - FT8_memWrite16(REG_HOFFSET, FT8_HOFFSET); // start of active line - FT8_memWrite16(REG_HSYNC0, FT8_HSYNC0); // start of horizontal sync pulse - FT8_memWrite16(REG_HSYNC1, FT8_HSYNC1); // end of horizontal sync pulse - FT8_memWrite16(REG_VSIZE, FT8_VSIZE); // active display height - FT8_memWrite16(REG_VCYCLE, FT8_VCYCLE); // total number of lines per screen, incl pre/post - FT8_memWrite16(REG_VOFFSET, FT8_VOFFSET); // start of active screen - FT8_memWrite16(REG_VSYNC0, FT8_VSYNC0); // start of vertical sync pulse - FT8_memWrite16(REG_VSYNC1, FT8_VSYNC1); // end of vertical sync pulse - FT8_memWrite8(REG_SWIZZLE, FT8_SWIZZLE); // FT8xx output to LCD - pin order - FT8_memWrite8(REG_PCLK_POL, FT8_PCLKPOL); /// LCD data is clocked in on this PCLK edge - // Don't set PCLK yet - wait for just after the first display list + #if defined (FT8_ADAM101) + FT8_memWrite8(REG_PWM_DUTY, 0x80); // turn off backlight for Glyn ADAM101 module, it uses inverted values + #else + FT8_memWrite8(REG_PWM_DUTY, 0); // turn off backlight for any other module + #endif + + // Setup FT8xx for external or internal clock + if (dconfig->disp_config.has_crystal != 0) FT8_cmdWrite(FT8_CLKEXT); + else FT8_cmdWrite(FT8_CLKINT); + + // Start FT8xx + FT8_cmdWrite(FT8_ACTIVE); + + // Detect EVE chip + if (!_ft8xx_detect(REG_ID)) { + #ifdef CONFIG_EVE_CHIP_TYPE1 + if (_ft8xx_detect(REG_ID_FT80X)) { + ESP_LOGE(TAG, "EVE module configured for FT81x but FT80x detected"); + } + else { + ESP_LOGE(TAG, "EVE chip not detected (timeout)"); + } + #else + if (_ft8xx_detect(REG_ID_FT81X)) { + ESP_LOGE(TAG, "EVE module configured for FT80x but FT81x detected"); + } + else { + ESP_LOGE(TAG, "EVE chip not detected (timeout)"); + } + #endif + eve_chip_id = 0; + return ESP_FAIL; + } - // ** Configure Touch - FT8_memWrite8(REG_TOUCH_MODE, FT8_TMODE_CONTINUOUS); // enable touch - FT8_memWrite16(REG_TOUCH_RZTHRESH, FT8_TOUCH_RZTHRESH); // eliminate any false touches + // Get chip model + chip_type = FT8_memRead32(FT8_ROM_CHIPID); + eve_chip_id = ((chip_type & 0xFF) << 8) | ((chip_type & 0xFF00) >> 8); + if (((eve_chip_id >= 0x800) && (eve_chip_id <= 0x801)) || ((eve_chip_id >= 0x810) && (eve_chip_id <= 0x813))) { + ESP_LOGD(TAG, "EVE chip detected: FT%4x", eve_chip_id); + } + else { + ESP_LOGE(TAG, "EVE chip not detected (wrong ID)"); + eve_chip_id = 0; + return ESP_FAIL; + } - // ** Configure Audio - not used, so disable it - FT8_memWrite8(REG_VOL_PB, 0x00); // turn recorded audio volume down - // FT8_memWrite8(REG_VOL_SOUND, 0xff); // turn synthesizer volume on - FT8_memWrite8(REG_VOL_SOUND, 0x00); // turn synthesizer volume off - FT8_memWrite16(REG_SOUND, 0x6000); // set synthesizer to mute + #ifdef CONFIG_EVE_CHIP_TYPE1 + // If we have a display with a Goodix GT911 / GT9271 touch-controller on it, we need to patch our FT811 or FT813 according to AN_336 + if (dconfig->disp_config.has_GT911) { + uint32_t ftAddress; - FT8_memWrite32(FT8_RAM_DL, DL_CLEAR_RGB); - FT8_memWrite32(FT8_RAM_DL + 4, (DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG)); - FT8_memWrite32(FT8_RAM_DL + 8, DL_DISPLAY); // end of display list - FT8_memWrite32(REG_DLSWAP, FT8_DLSWAP_FRAME); + FT8_get_cmdoffset(); + ftAddress = FT8_RAM_CMD + eve_cmdOffset; - // nothing is being displayed yet... the pixel clock is still 0x00 + FT8_memWrite_flash_buffer(ftAddress, FT8_GT911_data, FT8_GT911_len, true); - gpio = FT8_memRead8(REG_GPIO_DIR); - // set DISP to Output although it always is output, set GPIO1 to Output - Audio Enable on VM800B - gpio |= 0x82; - FT8_memWrite8(REG_GPIO_DIR, gpio); + FT8_cmd_execute(250); - gpio = FT8_memRead8(REG_GPIO); // read the FT8xx GPIO register for a read/modify/write operation - // gpio |= 0x82; // set bit 7 of FT8xx GPIO register (DISP), set GPIO1 to High to enable Audio - others are inputs - gpio |= 0x80; // set bit 7 of FT8xx GPIO register (DISP), others are inputs - FT8_memWrite8(REG_GPIO, gpio); // enable the DISP signal to the LCD panel - FT8_memWrite8(REG_PCLK, FT8_PCLK); // now start clocking data to the LCD panel + FT8_memWrite8(REG_TOUCH_OVERSAMPLE, 0x0f); // setup oversample to 0x0f as "hidden" in binary-blob for AN_336 + FT8_memWrite16(REG_TOUCH_CONFIG, 0x05D0); // write magic cookie as requested by AN_336 - FT8_memWrite8(REG_PWM_DUTY, 70); // turn on backlight + // specific to the EVE2 modules from Matrix-Orbital we have to use GPIO3 to reset GT911 + FT8_memWrite16(REG_GPIOX_DIR,0x8008); // Reset-Value is 0x8000, adding 0x08 sets GPIO3 to output, default-value for REG_GPIOX is 0x8000 -> Low output on GPIO3 + vTaskDelay(2 / portTICK_RATE_MS); // wait more than 100µs + FT8_memWrite8(REG_CPURESET, 0x00); // clear all resets + vTaskDelay(57 / portTICK_RATE_MS); // wait more than 55ms + FT8_memWrite16(REG_GPIOX_DIR,0x8000); // setting GPIO3 back to input + } + #endif + + //FT8_memWrite8(REG_PCLK, 0x00); // set PCLK to zero - don't clock the LCD until later + + // === Initialize the display timings === + FT8_memWrite16(REG_HSIZE, dconfig->disp_config.hsize); // active display width + FT8_memWrite16(REG_HCYCLE, dconfig->disp_config.hcycle); // total number of clocks per line, including front/back porch + FT8_memWrite16(REG_HOFFSET, dconfig->disp_config.hoffset); // start of active line + FT8_memWrite16(REG_HSYNC0, dconfig->disp_config.hsync0); // start of horizontal sync pulse + FT8_memWrite16(REG_HSYNC1, dconfig->disp_config.hsync1); // end of horizontal sync pulse + FT8_memWrite16(REG_VSIZE, dconfig->disp_config.vsize); // active display height + FT8_memWrite16(REG_VCYCLE, dconfig->disp_config.vcycle); // total number of lines per screen, incl pre/post + FT8_memWrite16(REG_VOFFSET, dconfig->disp_config.voffset); // start of active screen + FT8_memWrite16(REG_VSYNC0, dconfig->disp_config.vsync0); // start of vertical sync pulse + FT8_memWrite16(REG_VSYNC1, dconfig->disp_config.vsync1); // end of vertical sync pulse + FT8_memWrite8(REG_SWIZZLE, dconfig->disp_config.swizzle); // FT8xx output to LCD - pin order + FT8_memWrite8(REG_PCLK_POL, dconfig->disp_config.pclkpol); // LCD data is clocked in on this PCLK edge + FT8_memWrite8(REG_CSPREAD, dconfig->disp_config.cspread); // helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 + + // Don't set PCLK yet - wait for just after the first display list - vTaskDelay(2 / portTICK_RATE_MS); // just to be safe - - while (FT8_busy() == 1) ; + // ** Configure Touch + FT8_memWrite8(REG_TOUCH_MODE, FT8_TMODE_CONTINUOUS); // enable touch + FT8_memWrite16(REG_TOUCH_RZTHRESH, dconfig->disp_config.touch_thresh); // eliminate any false touches + + // disable Audio for now + FT8_memWrite8(REG_VOL_PB, 0x00); // turn recorded audio volume down + FT8_memWrite8(REG_VOL_SOUND, 0x00); // turn synthesizer volume off + FT8_memWrite16(REG_SOUND, 0x6000); // set synthesizer to mute + + // write a basic display-list to get things started + FT8_memWrite32(FT8_RAM_DL, DL_CLEAR_RGB); + FT8_memWrite32(FT8_RAM_DL + 4, (DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG)); + FT8_memWrite32(FT8_RAM_DL + 8, DL_DISPLAY); // end of display list + FT8_memWrite32(REG_DLSWAP, FT8_DLSWAP_FRAME); + + // nothing is being displayed yet... the pixel clock is still 0x00 + FT8_memWrite8(REG_GPIO, 0x80); // enable the DISP signal to the LCD panel + FT8_memWrite8(REG_PCLK, dconfig->disp_config.pclk); // now start clocking data to the LCD panel + + do { + vTaskDelay(2 / portTICK_RATE_MS); // just to be safe + } while (FT8_busy()); + + FT8_memWrite8(REG_PWM_DUTY, 64); // turn on backlight + FT8_get_cmdoffset(); - FT8_get_cmdoffset(); - return 1; + return ESP_OK; } #endif // CONFIG_MICROPY_USE_EVE diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.h b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.h index c68955af..81b623c8 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/eve/FT8_commands.h @@ -32,213 +32,152 @@ #ifndef FT8_COMMANDS_H_ #define FT8_COMMANDS_H_ -#include - -/* switch over to FT81x */ -#define FT8_81X_ENABLE +#include "sdkconfig.h" +#if CONFIG_MICROPY_USE_EVE -/* select the settings for the TFT attached */ -#if 0 - #define FT8_VM800B35A - #define FT8_VM800B43A - #define FT8_VM800B50A - #define FT8_FT810CB_HY50HD - #define FT8_FT811CB_HY50HD - #define FT8_ET07 - #define FT8_RVT70AQ -#endif +#include +#include "esp_err.h" +//#include "tft/tftspi.h" +#include "driver/spi_master_utils.h" -#define FT8_FT810CB_HY50HD +#define MAX_USER_FONTS 15 +//#define EVE_STATIC_LIST 0 +//#define EVE_STATIC_LIST_SIZE 8192 +//#define EVE_FONT_IMG_START 8192 +#define EVE_FONT_METRICS_SIZE 148 +#define EVE_FONT_WIDTHS_SIZE 128 -/* some pre-definded colors */ -#define RED 0xff0000UL -#define ORANGE 0xffa500UL -#define GREEN 0x00ff00UL -#define BLUE 0x0000ffUL -#define YELLOW 0xffff00UL -/*#define PINK 0xff00ffUL*/ -#define PURPLE 0x800080UL -#define WHITE 0xffffffUL -#define BLACK 0x000000UL - - -/* VM800B35A: FT800 320x240 3.5" FTDI */ -#ifdef FT8_VM800B35A -#define FT8_VSYNC0 (0L) /* Tvf Vertical Front Porch */ -#define FT8_VSYNC1 (2L) /* Tvf + Tvp Vertical Front Porch plus Vsync Pulse width */ -#define FT8_VOFFSET (13L) /* Tvf + Tvp + Tvb Number of non-visible lines (in lines) */ -#define FT8_VCYCLE (263L) /* Tv Total number of lines (visible and non-visible) (in lines) */ -#define FT8_VSIZE (240L) /* Tvd Number of visible lines (in lines) - display height */ -#define FT8_HSYNC0 (0L) /* Thf Horizontal Front Porch */ -#define FT8_HSYNC1 (10L) /* Thf + Thp Horizontal Front Porch plus Hsync Pulse width */ -#define FT8_HOFFSET (70L) /* Thf + Thp + Thb Length of non-visible part of line (in PCLK cycles) */ -#define FT8_HCYCLE (408L) /* Th Total length of line (visible and non-visible) (in PCLKs) */ -#define FT8_HSIZE (320L) /* Thd Length of visible part of line (in PCLKs) - display width */ -#define FT8_PCLKPOL (0L) /* PCLK polarity (0 = rising edge, 1 = falling edge) */ -#define FT8_SWIZZLE (2L) /* Defines the arrangement of the RGB pins of the FT800 */ -#define FT8_PCLK (8L) /* 48MHz / REG_PCLK = PCLK frequency */ -#define FT8_TOUCH_RZTHRESH (1200L) /* touch-sensitivity */ -#define FT8_HAS_CRYSTAL 1 /* use external crystal or internal oscillator? */ +#ifdef CONFIG_MICROPY_EVE_FT81X +#define FT8_81X_ENABLE #endif -/* VM800B43A: FT800 480x272 4.3" FTDI */ -#ifdef FT8_VM800B43A -#define FT8_VSYNC0 (0L) -#define FT8_VSYNC1 (10L) -#define FT8_VOFFSET (12L) -#define FT8_VCYCLE (292L) -#define FT8_VSIZE (272L) -#define FT8_HSYNC0 (0L) -#define FT8_HSYNC1 (41L) -#define FT8_HOFFSET (43L) -#define FT8_HCYCLE (548L) -#define FT8_HSIZE (480L) -#define FT8_PCLKPOL (1L) -#define FT8_SWIZZLE (0L) -#define FT8_PCLK (5L) -#define FT8_TOUCH_RZTHRESH (1200L) -#define FT8_HAS_CRYSTAL 1 -#endif +#define EVE_TYPE_NONE 0 +#define EVE_TYPE_FT800 1 +#define EVE_TYPE_FT801 2 +#define EVE_TYPE_FT810 3 +#define EVE_TYPE_FT811 4 +#define EVE_TYPE_FT812 5 +#define EVE_TYPE_FT813 6 +#define EVE_TYPE_MAX 7 -/* VM800B50A: FT800 480x272 5.0" FTDI */ -#ifdef FT8_VM800B50A -#define FT8_VSYNC0 (0L) -#define FT8_VSYNC1 (10L) -#define FT8_VOFFSET (12L) -#define FT8_VCYCLE (292L) -#define FT8_VSIZE (272L) -#define FT8_HSYNC0 (0L) -#define FT8_HSYNC1 (41L) -#define FT8_HOFFSET (43L) -#define FT8_HCYCLE (548L) -#define FT8_HSIZE (480L) -#define FT8_PCLKPOL (1L) -#define FT8_SWIZZLE (0L) -#define FT8_PCLK (5L) -#define FT8_TOUCH_RZTHRESH (1200L) -#define FT8_HAS_CRYSTAL 1 -#endif +/* some pre-definded colors */ +#define EVE_BLACK 0 +#define EVE_NAVY 128 +#define EVE_DARKGREEN 32768 +#define EVE_DARKCYAN 32896 +#define EVE_MAROON 8388608 +#define EVE_PURPLE 8388736 +#define EVE_OLIVE 8421376 +#define EVE_LIGHTGREY 12632256 +#define EVE_DARKGREY 8421504 +#define EVE_BLUE 255 +#define EVE_GREEN 65280 +#define EVE_CYAN 65535 +#define EVE_RED 16515072 +#define EVE_MAGENTA 16515327 +#define EVE_YELLOW 16579584 +#define EVE_WHITE 16579836 +#define EVE_ORANGE 16557056 +#define EVE_GREENYELLOW 11336748 +#define EVE_PINK 16564426 + + +typedef struct { + uint16_t vsync0; // Tvf Vertical Front Porch + uint16_t vsync1; // Tvf + Tvp Vertical Front Porch plus Vsync Pulse width + uint16_t voffset; // Tvf + Tvp + Tvb Number of non-visible lines (in lines) + uint16_t vcycle; // Tv Total number of lines (visible and non-visible) (in lines) + uint16_t vsize; // Tvd Number of visible lines (in lines) - display height + uint16_t hsync0; // Thf Horizontal Front Porch + uint16_t hsync1; // Thf + Thp Horizontal Front Porch plus Hsync Pulse width + uint16_t hoffset; // Thf + Thp + Thb Length of non-visible part of line (in PCLK cycles) + uint16_t hcycle; // Th Total length of line (visible and non-visible) (in PCLKs) + uint16_t hsize; // Thd Length of visible part of line (in PCLKs) - display width + uint8_t pclkpol; // PCLK polarity (0 = rising edge, 1 = falling edge) + uint8_t swizzle; // Defines the arrangement of the RGB pins of the FT800 + uint8_t pclk; // 48MHz or 60 MHz / REG_PCLK = PCLK frequency + uint8_t has_crystal; // use external crystal or internal oscillator? + uint16_t touch_thresh; // touch-sensitivity + uint8_t cspread; // helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 + uint8_t has_GT911; // special treatment required for out-of-spec touch-controller +} ft8_config_t; + +// EVE Display structure +typedef struct { + uint16_t width; // Display width (smaller dimension) + uint16_t height; // Display height (larger dimension) + uint32_t speed; // SPI clock in Hz + uint8_t host; // SPI host (HSPI_HOST or VSPI_HOST) + uint8_t miso; // SPI MISO pin + uint8_t mosi; // SPI MOSI pin + uint8_t sck; // SPI CLOCK pin + uint8_t cs; // Display CS pin + int8_t pd; // GPIO used as PD pin + uint8_t touch; // Touch panel type + ft8_config_t disp_config; // Pointer to display configuration structure +} eve_config_t; + +typedef struct { + uint32_t fifo_buff; //fifo buffer address + int32_t fifo_len; //fifo length + int32_t fifo_wp; //fifo write pointer - maintained by host + int32_t fifo_rp; //fifo read point - maintained by device + FILE *pFile; + int32_t file_remain; + int32_t file_size; + uint8_t *g_scratch; + uint16_t fbuff_size; + uint32_t max_free; + uint32_t min_free; +} FT8_Fifo_t; -/* FT810CB-HY50HD: FT810 800x480 5" HAOYU */ -#ifdef FT8_FT810CB_HY50HD -#define FT8_VSYNC0 (0L) -#define FT8_VSYNC1 (2L) -#define FT8_VOFFSET (13L) -#define FT8_VCYCLE (525L) -#define FT8_VSIZE (480L) -#define FT8_HSYNC0 (0L) -#define FT8_HSYNC1 (20L) -#define FT8_HOFFSET (64L) -#define FT8_HCYCLE (952L) -#define FT8_HSIZE (800L) -#define FT8_PCLKPOL (1L) -#define FT8_SWIZZLE (0L) -#define FT8_PCLK (2L) -#define FT8_TOUCH_RZTHRESH (2000L) /* touch-sensitivity */ -#define FT8_HAS_CRYSTAL 1 -#endif -/* FT811CB-HY50HD: FT811 800x480 5" HAOYU */ -#ifdef FT8_FT811CB_HY50HD -#define FT8_VSYNC0 (0L) -#define FT8_VSYNC1 (2L) -#define FT8_VOFFSET (13L) -#define FT8_VCYCLE (525L) -#define FT8_VSIZE (480L) -#define FT8_HSYNC0 (0L) -#define FT8_HSYNC1 (20L) -#define FT8_HOFFSET (64L) -#define FT8_HCYCLE (952L) -#define FT8_HSIZE (800L) -#define FT8_PCLKPOL (1L) -#define FT8_SWIZZLE (0L) -#define FT8_PCLK (2L) -#define FT8_TOUCH_RZTHRESH (1200L) /* touch-sensitivity */ -#define FT8_HAS_CRYSTAL 1 -#endif +// ---------------------------------------------------------------------------------- -/* some test setup */ -#ifdef FT8_800x480x -#define FT8_VSYNC0 (0L) /* Tvf Vertical Front Porch */ -#define FT8_VSYNC1 (10L) /* Tvf + Tvp Vertical Front Porch plus Vsync Pulse width */ -#define FT8_VOFFSET (35L) /* Tvf + Tvp + Tvb Number of non-visible lines (in lines) */ -#define FT8_VCYCLE (516L) /* Tv Total number of lines (visible and non-visible) (in lines) */ -#define FT8_VSIZE (480L) /* Tvd Number of visible lines (in lines) - display height */ -#define FT8_HSYNC0 (0L) /* (40L) // Thf Horizontal Front Porch */ -#define FT8_HSYNC1 (88L) /* Thf + Thp Horizontal Front Porch plus Hsync Pulse width */ -#define FT8_HOFFSET (169L) /* Thf + Thp + Thb Length of non-visible part of line (in PCLK cycles) */ -#define FT8_HCYCLE (969L) /* Th Total length of line (visible and non-visible) (in PCLKs) */ -#define FT8_HSIZE (800L) /* Thd Length of visible part of line (in PCLKs) - display width */ -#define FT8_PCLKPOL (1L) /* PCLK polarity (0 = rising edge, 1 = falling edge) */ -#define FT8_SWIZZLE (0L) /* Defines the arrangement of the RGB pins of the FT800 */ -#define FT8_PCLK (2L) /* 60MHz / REG_PCLK = PCLK frequency 30 MHz */ -#define FT8_TOUCH_RZTHRESH (1200L) /* touch-sensitivity */ -#define FT8_HAS_CRYSTAL 1 -#endif +extern uint16_t eve_chip_id; +extern exspi_device_handle_t *eve_spi; +extern uint16_t eve_cmdOffset; +extern uint32_t ft8_ramg_ptr; +extern FT8_Fifo_t ft8_stFifo; +extern uint8_t ft8_full_cs; +extern uint8_t eve_spibus_is_init; +extern uint8_t spi_is_init; -/* G-ET0700G0DM6 800x480 7" Glyn, untested */ -#ifdef FT8_ET07 -#define FT8_VSYNC0 (0L) -#define FT8_VSYNC1 (2L) -#define FT8_VOFFSET (35L) -#define FT8_VCYCLE (525L) -#define FT8_VSIZE (480L) -#define FT8_HSYNC0 (0L) -#define FT8_HSYNC1 (128L) -#define FT8_HOFFSET (203L) -#define FT8_HCYCLE (1056L) -#define FT8_HSIZE (800L) -#define FT8_PCLKPOL (1L) -#define FT8_SWIZZLE (0L) -#define FT8_PCLK (2L) -#define FT8_TOUCH_RZTHRESH (1200L) -#define FT8_HAS_CRYSTAL 0 /* no idea if these come with a crystal populated or not */ -#endif -/* RVT70AQxxxxxx 800x480 7" Riverdi, various options, FT812/FT813, tested with RVT70UQFNWC0x */ -#ifdef FT8_RVT70AQ -#define FT8_VSYNC0 (0L) /* Tvf Vertical Front Porch */ -#define FT8_VSYNC1 (10L) /* Tvf + Tvp Vertical Front Porch plus Vsync Pulse width */ -#define FT8_VOFFSET (23L) /* Tvf + Tvp + Tvb Number of non-visible lines (in lines) */ -#define FT8_VCYCLE (525L) /* Tv Total number of lines (visible and non-visible) (in lines) */ -#define FT8_VSIZE (480L) /* Tvd Number of visible lines (in lines) - display height */ -#define FT8_HSYNC0 (0L) /* Thf Horizontal Front Porch */ -#define FT8_HSYNC1 (10L) /* Thf + Thp Horizontal Front Porch plus Hsync Pulse width */ -#define FT8_HOFFSET (46L) /* Thf + Thp + Thb Length of non-visible part of line (in PCLK cycles) */ -#define FT8_HCYCLE (1056L) /* Th Total length of line (visible and non-visible) (in PCLKs) */ -#define FT8_HSIZE (800L) /* Thd Length of visible part of line (in PCLKs) - display width */ -#define FT8_PCLKPOL (1L) /* PCLK polarity (0 = rising edge, 1 = falling edge) */ -#define FT8_SWIZZLE (0L) /* Defines the arrangement of the RGB pins of the FT800 */ -#define FT8_PCLK (2L) /* 60MHz / REG_PCLK = PCLK frequency 30 MHz */ -#define FT8_TOUCH_RZTHRESH (1800L) /* touch-sensitivity */ -#define FT8_HAS_CRYSTAL 0 +#ifdef CONFIG_EVE_CHIP_TYPE1 +int FT8_Fifo_init(FILE *fhndl); +void FT8_Fifo_deinit(); #endif -// ---------------------------------------------------------------------------------- - -extern uint16_t eve_cmdOffset; - void FT8_cmdWrite(uint8_t data); uint8_t FT8_memRead8(uint32_t ftAddress); uint16_t FT8_memRead16(uint32_t ftAddress); uint32_t FT8_memRead32(uint32_t ftAddress); +void FT8_memRead_buffer(uint32_t ftAddress, uint8_t *data, uint16_t len); + void FT8_memWrite8(uint32_t ftAddress, uint8_t ftData8); void FT8_memWrite16(uint32_t ftAddress, uint16_t ftData16); void FT8_memWrite32(uint32_t ftAddress, uint32_t ftData32); -void FT8_memWrite_flash_buffer(uint32_t ftAddress, const uint8_t *data, uint16_t len); +int FT8_memWrite_flash_buffer(uint32_t ftAddress, const uint8_t *data, uint16_t len, bool check_padding); + +void FT8_send_long(uint32_t val1, uint32_t val2, uint32_t val3, uint8_t len); + uint8_t FT8_busy(void); void FT8_cmd_dl(uint32_t command); +void FT8_inc_cmdoffset(uint16_t increment); void FT8_get_cmdoffset(void); uint32_t FT8_get_touch_tag(void); void FT8_cmd_start(void); -void FT8_cmd_execute(void); +bool FT8_cmd_execute(int tmo_ms); void FT8_start_cmd_burst(void); void FT8_end_cmd_burst(void); +void FT8_start_cmd(uint32_t command); + /* commands to draw graphics objects: */ void FT8_cmd_text(int16_t x0, int16_t y0, int16_t font, uint16_t options, const char* text); @@ -257,24 +196,33 @@ void FT8_cmd_dial(int16_t x0, int16_t y0, int16_t r0, uint16_t options, uint16_t void FT8_cmd_toggle(int16_t x0, int16_t y0, int16_t w0, int16_t font, uint16_t options, uint16_t state, const char* text); void FT8_cmd_number(int16_t x0, int16_t y0, int16_t font, uint16_t options, int32_t number); -#ifdef FT8_81X_ENABLE void FT8_cmd_setbase(uint32_t base); void FT8_cmd_setbitmap(uint32_t addr, uint16_t fmt, uint16_t width, uint16_t height); -#endif +void FT8_cmd_bitmapXY(uint16_t x, uint16_t y); /* commands to operate on memory: */ void FT8_cmd_memzero(uint32_t ptr, uint32_t num); void FT8_cmd_memset(uint32_t ptr, uint8_t value, uint32_t num); -/*(void FT8_cmd_memwrite(uint32_t dest, uint32_t num, const uint8_t *data); */ +void FT8_cmd_memwrite(uint32_t dest, const uint8_t *data, uint32_t num); void FT8_cmd_memcpy(uint32_t dest, uint32_t src, uint32_t num); void FT8_cmd_append(uint32_t ptr, uint32_t num); /* commands for loading image data into FT8xx memory: */ void FT8_cmd_inflate(uint32_t ptr, const uint8_t *data, uint16_t len); -void FT8_cmd_loadimage(uint32_t ptr, uint32_t options, const uint8_t *data, uint16_t len); -#ifdef FT8_81X_ENABLE +int FT8_cmd_loadimage(uint32_t ptr, uint32_t options, FILE *fhndl, uint32_t len, uint8_t type); + +#ifdef CONFIG_EVE_CHIP_TYPE1 void FT8_cmd_mediafifo(uint32_t ptr, uint32_t size); + +int FT8_sendDataViaMediafifo(FILE *pFile, uint32_t ptr, uint32_t options, uint8_t type); +int FT8_Fifo_service(); +void FT8_cmd_videoframe(uint32_t addr); + +void FT8_cmd_romfont(uint32_t font, uint32_t romslot); +void FT8_cmd_setfont2(uint32_t font, uint32_t ptr, uint32_t firstchar); +void FT8_cmd_setrotate(uint32_t r); +void FT8_cmd_setscratch(uint32_t handle); #endif /* commands for setting the bitmap transform matrix: */ @@ -282,26 +230,21 @@ void FT8_cmd_translate(int32_t tx, int32_t ty); void FT8_cmd_scale(int32_t sx, int32_t sy); void FT8_cmd_rotate(int32_t ang); void FT8_cmd_getmatrix(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f); +void FT8_cmd_setmatrix(); /* other commands: */ void FT8_cmd_calibrate(void); void FT8_cmd_interrupt(uint32_t ms); void FT8_cmd_setfont(uint32_t font, uint32_t ptr); -#ifdef FT8_81X_ENABLE -void FT8_cmd_romfont(uint32_t font, uint32_t romslot); -void FT8_cmd_setfont2(uint32_t font, uint32_t ptr, uint32_t firstchar); -void FT8_cmd_setrotate(uint32_t r); -void FT8_cmd_setscratch(uint32_t handle); -#endif + void FT8_cmd_sketch(int16_t x0, int16_t y0, uint16_t w0, uint16_t h0, uint32_t ptr, uint16_t format); void FT8_cmd_snapshot(uint32_t ptr); -#ifdef FT8_81X_ENABLE void FT8_cmd_snapshot2(uint32_t fmt, uint32_t ptr, int16_t x0, int16_t y0, int16_t w0, int16_t h0); -#endif void FT8_cmd_spinner(int16_t x0, int16_t y0, uint16_t style, uint16_t scale); void FT8_cmd_track(int16_t x0, int16_t y0, int16_t w0, int16_t h0, int16_t tag); +void FT8_CP_reset(); /* commands that return values by writing to the command-fifo */ uint16_t FT8_cmd_memcrc(uint32_t ptr, uint32_t num); @@ -314,9 +257,12 @@ uint16_t FT8_cmd_getprops(uint32_t ptr); void FT8_cmd_point(int16_t x0, int16_t y0, uint16_t size); void FT8_cmd_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t w0); void FT8_cmd_rect(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t corner); +void FT8_cmd_strip(uint16_t *data, uint16_t length, uint8_t type, uint16_t width); /* startup FT8xx: */ -uint8_t FT8_init(void); +esp_err_t FT8_init(eve_config_t *dconfig, exspi_device_handle_t *disp_spi_dev); + +#endif //CONFIG_MICROPY_USE_EVE #endif // FT8_COMMANDS_H_ diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c index 16921ddd..59e197b5 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c @@ -68,6 +68,8 @@ #include "freertos/task.h" #include "freertos/semphr.h" +#include "modnetwork.h" + TaskHandle_t FtpTaskHandle = NULL; QueueHandle_t ftp_mutex = NULL; uint32_t ftp_stack_size; @@ -86,7 +88,7 @@ const char *FTP_TAG = "[Ftp]"; #define FTP_DATA_CLIENTS_MAX 1 #define FTP_MAX_PARAM_SIZE (MICROPY_ALLOC_PATH_MAX + 1) #define FTP_UNIX_SECONDS_180_DAYS 15552000 -#define FTP_DATA_TIMEOUT_MS 5000 // 10 seconds +#define FTP_DATA_TIMEOUT_MS 10000 // 10 seconds #define FTP_SOCKETFIFO_ELEMENTS_MAX 4 /****************************************************************************** @@ -216,19 +218,30 @@ static bool ftp_open_file (const char *path, const char *mode) { return true; } -//---------------------------------- -static void ftp_close_files (void) { +//-------------------------------------- +static void ftp_close_files_dir (void) { if (ftp_data.e_open == E_FTP_FILE_OPEN) { fclose(ftp_data.fp); - } else if (ftp_data.e_open == E_FTP_DIR_OPEN) { + ftp_data.fp = NULL; + } + else if (ftp_data.e_open == E_FTP_DIR_OPEN) { closedir(ftp_data.dp); + ftp_data.dp = NULL; } ftp_data.e_open = E_FTP_NOTHING_OPEN; } //------------------------------------------------ static void ftp_close_filesystem_on_error (void) { - ftp_close_files(); + ftp_close_files_dir(); + if (ftp_data.fp) { + fclose(ftp_data.fp); + ftp_data.fp = NULL; + } + if (ftp_data.dp) { + closedir(ftp_data.dp); + ftp_data.dp = NULL; + } } //--------------------------------------------------------------------------------------------- @@ -236,10 +249,10 @@ static ftp_result_t ftp_read_file (char *filebuf, uint32_t desiredsize, uint32_t ftp_result_t result = E_FTP_RESULT_CONTINUE; *actualsize = fread(filebuf, 1, desiredsize, ftp_data.fp); if (*actualsize == 0) { - ftp_close_files(); + ftp_close_files_dir(); result = E_FTP_RESULT_FAILED; } else if (*actualsize < desiredsize) { - ftp_close_files(); + ftp_close_files_dir(); result = E_FTP_RESULT_OK; } return result; @@ -252,13 +265,17 @@ static ftp_result_t ftp_write_file (char *filebuf, uint32_t size) { if (actualsize == size) { result = E_FTP_RESULT_OK; } else { - ftp_close_files(); + ftp_close_files_dir(); } return result; } //--------------------------------------------------------------- static ftp_result_t ftp_open_dir_for_listing (const char *path) { + if (ftp_data.dp) { + closedir(ftp_data.dp); + ftp_data.dp = NULL; + } if (path[0] == '/' && path[1] == '\0') { ftp_data.listroot = true; ESP_LOGD(FTP_TAG, "ftp_open_dir_for_listing: root"); @@ -308,8 +325,27 @@ static int ftp_get_eplf_item (char *dest, uint32_t destsize, struct dirent *de) if ((buf.st_mtime + FTP_UNIX_SECONDS_180_DAYS) < now) strftime(str_time, 127, "%b %d %Y", tm_info); else strftime(str_time, 63, "%b %d %H:%M", tm_info); - if (ftp_nlist) return snprintf(dest, destsize, "%s\r\n", de->d_name); - return snprintf(dest, destsize, "%srw-rw-rw- 1 root root %9u %s %s\r\n", type, (uint32_t)buf.st_size, str_time, de->d_name); + int addsize = destsize + 64; + + while (addsize >= destsize) { + if (ftp_nlist) addsize = snprintf(dest, destsize, "%s\r\n", de->d_name); + else addsize = snprintf(dest, destsize, "%srw-rw-rw- 1 root root %9u %s %s\r\n", type, (uint32_t)buf.st_size, str_time, de->d_name); + if (addsize >= destsize) { + ESP_LOGW(FTP_TAG, "Buffer too small, reallocating [%d > %d]", ftp_buff_size, ftp_buff_size + (addsize - destsize) + 64); + char *new_dest = realloc(dest, ftp_buff_size + (addsize - destsize) + 65); + if (new_dest) { + ftp_buff_size += (addsize - destsize) + 64; + destsize += (addsize - destsize) + 64; + dest = new_dest; + addsize = destsize + 64; + } + else { + ESP_LOGE(FTP_TAG, "Buffer reallocation ERROR"); + addsize = 0; + } + } + } + return addsize; } //--------------------------------------------------------------------------- @@ -325,8 +361,8 @@ static int ftp_get_eplf_drive (char *dest, uint32_t destsize, char *name) { return snprintf(dest, destsize, "%srw-rw-rw- 1 root root %9u %s %s\r\n", type, 0, str_time, name); } -//--------------------------------------------------------------------------------------- -static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *listsize) { +//-------------------------------------------------------------------------------------- +static ftp_result_t ftp_list_dir(char *list, uint32_t maxlistsize, uint32_t *listsize) { uint next = 0; uint listcount = 0; ftp_result_t result = E_FTP_RESULT_CONTINUE; @@ -344,7 +380,7 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li } // read up to 8 directory items - while (listcount < 8) { + while (((maxlistsize - next) > 64) && (listcount < 8)) { de = readdir(ftp_data.dp); // Read a directory item if (de == NULL) { result = E_FTP_RESULT_OK; @@ -359,7 +395,7 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li listcount++; } if (result == E_FTP_RESULT_OK) { - ftp_close_files(); + ftp_close_files_dir(); } *listsize = next; return result; @@ -448,26 +484,32 @@ static ftp_result_t ftp_wait_for_connection (int32_t l_sd, int32_t *n_sd, uint32 } if (ip_addr) { - tcpip_adapter_ip_info_t ip_info; - wifi_mode_t wifi_mode; - esp_wifi_get_mode(&wifi_mode); - if (wifi_mode != WIFI_MODE_APSTA) { - // easy way - tcpip_adapter_if_t if_type; - if (wifi_mode == WIFI_MODE_AP) { - if_type = TCPIP_ADAPTER_IF_AP; - } else { - if_type = TCPIP_ADAPTER_IF_STA; + // check on which network interface the client was connected and save the IP address + tcpip_adapter_ip_info_t ip_info = {0}; + int n_if = network_get_active_interfaces(); + + if (n_if > 0) { + struct sockaddr_in clientAddr; + in_addrSize = sizeof(struct sockaddr_in); + getpeername(_sd, (struct sockaddr *)&clientAddr, (socklen_t *)&in_addrSize); + ESP_LOGD(FTP_TAG, "Client IP: %08x", clientAddr.sin_addr.s_addr); + *ip_addr = 0; + for (int i=0; i 0) && (ftp_path[strlen(ftp_path)-1] != '/')) { + if (unlink(ftp_path) == 0) { + vTaskDelay(20 / portTICK_PERIOD_MS); + ftp_send_reply(250, NULL); + } + else ftp_send_reply(550, NULL); + } + else ftp_send_reply(250, NULL); + break; case E_FTP_CMD_RMD: ftp_get_param_and_open_child(&bufptr); if ((strlen(ftp_path) > 0) && (ftp_path[strlen(ftp_path)-1] != '/')) { - if (unlink(ftp_path) >= 0) { + if (rmdir(ftp_path) == 0) { vTaskDelay(20 / portTICK_PERIOD_MS); ftp_send_reply(250, NULL); } @@ -1076,16 +1128,32 @@ void ftp_deinit(void) { } //------------------- -void ftp_init(void) { +bool ftp_init(void) { ftp_stop = 0; // Allocate memory for the data buffer, and the file system structures (from the RTOS heap) ftp_deinit(); memset(&ftp_data, 0, sizeof(ftp_data_t)); - ftp_data.dBuffer = malloc(ftp_buff_size); + ftp_data.dBuffer = malloc(ftp_buff_size+1); + if (ftp_data.dBuffer == NULL) return false; ftp_path = malloc(FTP_MAX_PARAM_SIZE); + if (ftp_path == NULL) { + free(ftp_data.dBuffer); + return false; + } ftp_scratch_buffer = malloc(FTP_MAX_PARAM_SIZE); + if (ftp_scratch_buffer == NULL) { + free(ftp_path); + free(ftp_data.dBuffer); + return false; + } ftp_cmd_buffer = malloc(FTP_MAX_PARAM_SIZE + FTP_CMD_SIZE_MAX); + if (ftp_cmd_buffer == NULL) { + free(ftp_scratch_buffer); + free(ftp_path); + free(ftp_data.dBuffer); + return false; + } //SOCKETFIFO_Init((void *)ftp_fifoelements, FTP_SOCKETFIFO_ELEMENTS_MAX); @@ -1098,6 +1166,7 @@ void ftp_init(void) { ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; if (ftp_mutex == NULL) ftp_mutex = xSemaphoreCreateMutex(); + return true; } //============================ @@ -1149,15 +1218,10 @@ int ftp_run (uint32_t elapsed) case E_FTP_STE_CONTINUE_LISTING: // go on with listing { - uint32_t listsize; - ftp_list_dir((char *)ftp_data.dBuffer, ftp_buff_size, &listsize); - if (listsize > 0) { - ftp_send_list(listsize); - if (ftp_data.listroot) { - ftp_send_reply(226, NULL); - ftp_data.state = E_FTP_STE_END_TRANSFER; - } - } else { + uint32_t listsize = 0; + ftp_result_t list_res = ftp_list_dir((char *)ftp_data.dBuffer, ftp_buff_size, &listsize); + if (listsize > 0) ftp_send_list(listsize); + if (list_res == E_FTP_RESULT_OK) { ftp_send_reply(226, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; } @@ -1213,7 +1277,7 @@ int ftp_run (uint32_t elapsed) else if (result == E_FTP_RESULT_CONTINUE) { // nothing received if (ftp_data.dtimeout > FTP_DATA_TIMEOUT_MS) { - ftp_close_files(); + ftp_close_files_dir(); ftp_send_reply(426, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; ESP_LOGW(FTP_TAG, "Receiving to file timeout"); @@ -1221,7 +1285,7 @@ int ftp_run (uint32_t elapsed) } else { // File received (E_FTP_RESULT_FAILED) - ftp_close_files(); + ftp_close_files_dir(); ftp_send_reply(226, NULL); ftp_data.state = E_FTP_STE_END_TRANSFER; ESP_LOGI(FTP_TAG, "File received (%u bytes in %u msek).", ftp_data.total, ftp_data.time); @@ -1243,12 +1307,12 @@ int ftp_run (uint32_t elapsed) ESP_LOGD(FTP_TAG, "Data socket connected"); } else if (ftp_data.dtimeout > FTP_DATA_TIMEOUT_MS) { + ESP_LOGW(FTP_TAG, "Waiting for data connection timeout (%d)", ftp_data.dtimeout); ftp_data.dtimeout = 0; // close the listening socket closesocket(ftp_data.ld_sd); ftp_data.ld_sd = -1; ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED; - ESP_LOGW(FTP_TAG, "Waiting for data connection timeout"); } break; case E_FTP_STE_SUB_DATA_CONNECTED: @@ -1355,6 +1419,16 @@ bool ftp_terminate (void) { return res; } +//------------------------- +bool ftp_stop_requested() { + if ((FtpTaskHandle == NULL) || (ftp_mutex == NULL)) return false; + if (xSemaphoreTake(ftp_mutex, FTP_MUTEX_TIMEOUT_MS / portTICK_PERIOD_MS) !=pdTRUE) return false; + + bool res = (ftp_stop == 1); + xSemaphoreGive(ftp_mutex); + return res; +} + //------------------------------- int32_t ftp_get_maxstack (void) { if ((FtpTaskHandle == NULL) || (ftp_mutex == NULL)) return -1; diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h index 78aeee6f..23eaf397 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h @@ -70,7 +70,7 @@ extern QueueHandle_t ftp_mutex; extern int ftp_buff_size; extern int ftp_timeout; -void ftp_init (void); +bool ftp_init (void); void ftp_deinit (void); int ftp_run (uint32_t elapsed); bool ftp_enable (void); @@ -79,6 +79,7 @@ bool ftp_disable (void); bool ftp_reset (void); int ftp_getstate(); bool ftp_terminate (void); +bool ftp_stop_requested(); int32_t ftp_get_maxstack (void); #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c b/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c index b34603a7..46a045b7 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c @@ -40,6 +40,8 @@ #include "netif/ppp/pppos.h" #include "netif/ppp/ppp.h" #include "lwip/pppapi.h" +//#include "lwip/port/lwipopts.h" +#include "lwip/opt.h" #include "libs/libGSM.h" #include "py/runtime.h" @@ -80,6 +82,11 @@ static int gsm_pin_rts = UART_PIN_NO_CHANGE; static int gsm_baudrate = 115200; static uint8_t tcpip_adapter_initialized = 0; static uint32_t sms_timer = 0; +static bool allow_roaming = false; + +static uint32_t ppp_ip = 0; +static uint32_t ppp_netmask = 0; +static uint32_t ppp_gw = 0; // The PPP control block static ppp_pcb *ppp = NULL; @@ -228,6 +235,9 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) #endif } xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); + ppp_ip = pppif->ip_addr.u_addr.ip4.addr; + ppp_netmask = pppif->netmask.u_addr.ip4.addr; + ppp_gw = pppif->gw.u_addr.ip4.addr; gsm_status = GSM_STATE_CONNECTED; xSemaphoreGive(pppos_mutex); break; @@ -262,6 +272,9 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) ESP_LOGW(TAG,"status_cb: User interrupt (disconnected)"); } xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); + ppp_ip = 0; + ppp_netmask = 0; + ppp_gw = 0; gsm_status = GSM_STATE_DISCONNECTED; xSemaphoreGive(pppos_mutex); break; @@ -271,6 +284,9 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) ESP_LOGE(TAG,"status_cb: Connection lost"); } xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); + ppp_ip = 0; + ppp_netmask = 0; + ppp_gw = 0; gsm_status = GSM_STATE_DISCONNECTED; xSemaphoreGive(pppos_mutex); break; @@ -609,6 +625,9 @@ static void pppos_client_task() { xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); pppos_task_started = 1; + ppp_ip = 0; + ppp_netmask = 0; + ppp_gw = 0; xSemaphoreGive(pppos_mutex); char PPP_ApnATReq[strlen(GSM_APN)+24]; @@ -685,6 +704,7 @@ static void pppos_client_task() } int gsmCmdIter = 0; int nfail = 0; + int cmd_res = 0; // ===== GSM Initialization loop ========================================================================= while(gsmCmdIter < GSM_InitCmdsSize) @@ -696,11 +716,11 @@ static void pppos_client_task() gsmCmdIter++; continue; } - if (atCmd_waitResponse(GSM_Init[gsmCmdIter]->cmd, - GSM_Init[gsmCmdIter]->cmdResponseOnOk, NULL, - GSM_Init[gsmCmdIter]->cmdSize, - GSM_Init[gsmCmdIter]->timeoutMs, NULL, 0, NULL) == 0) - { + if ((GSM_Init[gsmCmdIter] == &cmd_Reg) && (allow_roaming)) + cmd_res = atCmd_waitResponse(GSM_Init[gsmCmdIter]->cmd, GSM_Init[gsmCmdIter]->cmdResponseOnOk, "CREG: 0,5", GSM_Init[gsmCmdIter]->cmdSize, GSM_Init[gsmCmdIter]->timeoutMs, NULL, 0, NULL); + else + cmd_res = atCmd_waitResponse(GSM_Init[gsmCmdIter]->cmd, GSM_Init[gsmCmdIter]->cmdResponseOnOk, NULL, GSM_Init[gsmCmdIter]->cmdSize, GSM_Init[gsmCmdIter]->timeoutMs, NULL, 0, NULL); + if (cmd_res == 0) { // * No response or not as expected, start from first initialization command if (debug) { ESP_LOGW(TAG,"Wrong response, restarting..."); @@ -713,7 +733,15 @@ static void pppos_client_task() continue; } - if (GSM_Init[gsmCmdIter]->delayMs > 0) vTaskDelay(GSM_Init[gsmCmdIter]->delayMs / portTICK_PERIOD_MS); + if ((GSM_Init[gsmCmdIter] == &cmd_Reg) && (allow_roaming)) { + if (cmd_res == 2) { + if (debug) { + ESP_LOGW(TAG,"Connected in roaming"); + } + } + } + + if (GSM_Init[gsmCmdIter]->delayMs > 0) vTaskDelay(GSM_Init[gsmCmdIter]->delayMs / portTICK_PERIOD_MS); GSM_Init[gsmCmdIter]->skip = 1; if (GSM_Init[gsmCmdIter] == &cmd_Reg) GSM_Init[gsmCmdIter]->delayMs = 0; // Next command @@ -908,11 +936,12 @@ static void pppos_client_task() vTaskDelete(NULL); } -//=================================================================================================================== -int ppposInit(int tx, int rx, int rts, int cts, int bdr, char *user, char *pass, char *apn, uint8_t wait, int doconn) +//================================================================================================================================= +int ppposInit(int tx, int rx, int rts, int cts, int bdr, char *user, char *pass, char *apn, uint8_t wait, int doconn, bool roaming) { if (pppos_mutex != NULL) xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); do_pppos_connect = doconn; + allow_roaming = roaming; int gstat = 0; int task_s = pppos_task_started; if (pppos_mutex != NULL) xSemaphoreGive(pppos_mutex); @@ -936,7 +965,7 @@ int ppposInit(int tx, int rx, int rts, int cts, int bdr, char *user, char *pass, tcpip_adapter_initialized = 1; } #if CONFIG_MICROPY_USE_BOTH_CORES - xTaskCreate(&pppos_client_task, "GSM_PPPoS", PPPOS_CLIENT_STACK_SIZE, NULL, CONFIG_MICROPY_TASK_PRIORITY+1, &PPPoSTaskHandle); + xTaskCreate(&pppos_client_task, "GSM_PPPoS", PPPOS_CLIENT_STACK_SIZE, NULL, CONFIG_MICROPY_TASK_PRIORITY, &PPPoSTaskHandle); #else // Select GSM task core int task_core = MainTaskCore; @@ -945,7 +974,7 @@ int ppposInit(int tx, int rx, int rts, int cts, int bdr, char *user, char *pass, else task_core = 0; #endif - xTaskCreatePinnedToCore(&pppos_client_task, "GSM_PPPoS", PPPOS_CLIENT_STACK_SIZE, NULL, CONFIG_MICROPY_TASK_PRIORITY+1, &PPPoSTaskHandle, task_core); + xTaskCreatePinnedToCore(&pppos_client_task, "GSM_PPPoS", PPPOS_CLIENT_STACK_SIZE, NULL, CONFIG_MICROPY_TASK_PRIORITY, &PPPoSTaskHandle, task_core); #endif if (PPPoSTaskHandle == NULL) return -2; @@ -986,31 +1015,34 @@ int ppposConnect() if (task_s == 0) return -2; if (gstat == GSM_STATE_CONNECTED) return 0; + int tmo = 0; while (gstat != 1) { vTaskDelay(10 / portTICK_RATE_MS); xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); gstat = gsm_status; task_s = pppos_task_started; xSemaphoreGive(pppos_mutex); - if (task_s == 0) return 0; + if (task_s == 0) return -2; + tmo++; + if (tmo > 800) return -1; } return 0; } //=================================================== -void ppposDisconnect(uint8_t end_task, uint8_t rfoff) +int ppposDisconnect(uint8_t end_task, uint8_t rfoff) { - if (pppos_mutex == NULL) return; + if (pppos_mutex == NULL) return -1; xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); int gstat = gsm_status; int task_s = pppos_task_started; xSemaphoreGive(pppos_mutex); - if (task_s == 0) return; + if (task_s == 0) return 0; - if ((gstat == GSM_STATE_IDLE) && (end_task == 0)) return; + if ((gstat == GSM_STATE_IDLE) && (end_task == 0)) return 0; vTaskDelay(2000 / portTICK_RATE_MS); xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); @@ -1020,31 +1052,41 @@ void ppposDisconnect(uint8_t end_task, uint8_t rfoff) xSemaphoreGive(pppos_mutex); gstat = 0; + int tmo = 0; while ((gstat == 0) && (task_s != 0)) { xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); gstat = do_pppos_connect; task_s = pppos_task_started; xSemaphoreGive(pppos_mutex); vTaskDelay(10 / portTICK_RATE_MS); + tmo++; + if (tmo > 800) return -1; } - if (task_s == 0) return; + if (task_s == 0) return 0; + tmo = 0; while ((gstat != 0) && (task_s != 0)) { vTaskDelay(100 / portTICK_RATE_MS); xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); gstat = do_pppos_connect; task_s = pppos_task_started; xSemaphoreGive(pppos_mutex); + tmo++; + if (tmo > 800) return -1; } + return 0; } -//=================== -int ppposStatus() +//============================================================ +int ppposStatus(uint32_t *ip, uint32_t *netmask, uint32_t *gw) { if (pppos_mutex == NULL) return GSM_STATE_FIRSTINIT; xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); int gstat = gsm_status; + if (ip) *ip = ppp_ip; + if (netmask) *netmask = ppp_netmask; + if (gw) *gw = ppp_gw; xSemaphoreGive(pppos_mutex); return gstat; @@ -1133,7 +1175,7 @@ int gsm_RFOn() //-------------------- static int sms_ready() { - if (ppposStatus() != GSM_STATE_IDLE) return 0; + if (ppposStatus(NULL, NULL, NULL) != GSM_STATE_IDLE) return 0; int ret = 0; xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); @@ -1518,7 +1560,7 @@ void setDebug(uint8_t dbg) //=======================================*============================================ int at_Cmd(char *cmd, char* resp, char **buffer, int buf_size, int tmo, char *cmddata) { - if (ppposStatus() != GSM_STATE_IDLE) return 0; + if (ppposStatus(NULL, NULL, NULL) != GSM_STATE_IDLE) return 0; xSemaphoreTake(pppos_mutex, PPPOSMUTEX_TIMEOUT); int res = atCmd_waitResponse(cmd, resp, NULL, -1, tmo, buffer, buf_size, cmddata); diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.h b/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.h index eee4f6eb..7ecb2e01 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.h @@ -77,8 +77,8 @@ typedef struct * If 'wait' = 1, wait until connected * If 'doconn' = 0, only initialize the task, do not connect to Internet */ -//=================================================================================================================== -int ppposInit(int tx, int rx, int rts, int cts, int bdr, char *user, char *pass, char *apn, uint8_t wait, int doconn); +//================================================================================================================================= +int ppposInit(int tx, int rx, int rts, int cts, int bdr, char *user, char *pass, char *apn, uint8_t wait, int doconn, bool roaming); /* * Disconnect from Internet @@ -86,8 +86,8 @@ int ppposInit(int tx, int rx, int rts, int cts, int bdr, char *user, char *pass, * If 'rfoff' = 1, turns off GSM RF section to preserve power * If already disconnected, this function does nothing */ -//==================================================== -void ppposDisconnect(uint8_t end_task, uint8_t rfoff); +//=================================================== +int ppposDisconnect(uint8_t end_task, uint8_t rfoff); /* * Connect from Internet @@ -118,8 +118,8 @@ void resetRxTxCount(); * GSM_STATE_IDLE (89) Disconnected from Internet, Task idle, waiting for reconnect request * GSM_STATE_FIRSTINIT (98) Task started, initializing PPPoS */ -//================ -int ppposStatus(); +//============================================================ +int ppposStatus(uint32_t *ip, uint32_t *netmask, uint32_t *gw); /* * Turn GSM RF Off diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/littleflash.c b/MicroPython_BUILD/components/micropython/esp32/libs/littleflash.c new file mode 100644 index 00000000..a9f1c795 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/littleflash.c @@ -0,0 +1,1048 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * Adapted from https://github.com/lllucius/esp32_littleflash, see the Copyright and license notice below + * + */ + +// Copyright 2017-2018 Leland Lucius +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "sdkconfig.h" + +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 2 + +#include +#include +#include +#include +#include +#include +#include +#include "esp_heap_caps.h" +#include "esp_err.h" +#include "esp_log.h" + +#include "mphalport.h" +#include "libs/littleflash.h" + +#ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING +#include "wear_levelling.h" +#include "lfs_util.h" + +static wl_handle_t lfs_wl_handle = WL_INVALID_HANDLE; +#endif + + +static const char *TAG = "littleflash"; + +littleFlash_t littleFlash = {0}; + +static uint8_t *block_buffer = NULL; + +// ============================================================================ +// LFS disk interface for internal flash +// ============================================================================ + +//------------------------------------------------------------------------------------------------------------------- +static int internal_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) +{ + ESP_LOGV(TAG, "LFS_READ: block=%u off=%u size=%u", block, off, size); + + littleFlash_t *self = (littleFlash_t *) c->context; + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + esp_err_t err = wl_read(lfs_wl_handle, (block * self->sector_sz) + off, buffer, size); + #else + esp_err_t err = esp_partition_read(self->part, (block * self->sector_sz) + off, buffer, size); + #endif + + return err == ESP_OK ? LFS_ERR_OK : LFS_ERR_IO; +} + +//------------------------------------------------------------------------------------------------------------------------- +static int internal_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) +{ + ESP_LOGV(TAG, "LFS_PROG: block=%u off=%u size=%u",block, off, size); + + littleFlash_t *self = (littleFlash_t *) c->context; + + // --- Check if block needs to be erased --- + // Read the block + esp_err_t err; + err = internal_read(c, block, 0, block_buffer, self->sector_sz); + if (err != ESP_OK) return LFS_ERR_IO; + + // Check if the block was changed in a way that it must be erased before programming + uint8_t *buff = (uint8_t *)buffer; + for (int i=0; isector_sz); + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + err = wl_erase_range(lfs_wl_handle, block * self->sector_sz, self->sector_sz); + #else + err = esp_partition_erase_range(self->part, block * self->sector_sz, self->sector_sz); + #endif + if (err != ESP_OK) return LFS_ERR_IO; + break; + } + } + } + + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + err = wl_write(lfs_wl_handle, (block * self->sector_sz) + off, buffer, size); + #else + err = esp_partition_write(self->part, (block * self->sector_sz) + off, buffer, size); + #endif + + return err == ESP_OK ? LFS_ERR_OK : LFS_ERR_IO; +} + +//----------------------------------------------------------------------- +static bool internal_check_erased(littleFlash_t *self, lfs_block_t block) +{ + // Check if the sector is already erased + bool f = true; + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + esp_err_t err = wl_read(lfs_wl_handle, (block * self->sector_sz), block_buffer, self->sector_sz); + #else + esp_err_t err = esp_partition_read(self->part, (block * self->sector_sz), block_buffer, self->sector_sz); + #endif + if (err == ESP_OK) { + for (int i=0; isector_sz; i++) { + if (block_buffer[i] != 0xFF) { + f = false; + break; + } + } + } + else f = false; + return f; +} + +//---------------------------------------------------------------------- +static int internal_erase(const struct lfs_config *c, lfs_block_t block) +{ + littleFlash_t *self = (littleFlash_t *) c->context; + + esp_err_t err = ESP_OK; + if (!internal_check_erased(self, block)) { + ESP_LOGV(TAG, "LFS_ERASE: block=%u, sect_sz=%u", block, self->sector_sz); + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + err = wl_erase_range(lfs_wl_handle, block * self->sector_sz, self->sector_sz); + #else + err = esp_partition_erase_range(self->part, block * self->sector_sz, self->sector_sz); + #endif + } + else { + ESP_LOGV(TAG, "LFS_ERASE: block %u already erased", block); + return 1; + } + + return err == ESP_OK ? LFS_ERR_OK : LFS_ERR_IO; +} + +//---------------------------------------------------------------------------- +static int internal_dummy_erase(const struct lfs_config *c, lfs_block_t block) +{ + return LFS_ERR_OK; +} + +//-------------------------------------------------- +static int internal_sync(const struct lfs_config *c) +{ + ESP_LOGV(TAG, "%s", __func__); + + return LFS_ERR_OK; +} + + +// ============================================================================ +// ESP32 VFS implementation +// ============================================================================ + +typedef struct +{ + DIR dir; // must be first...ESP32 VFS expects it... + struct dirent dirent; + lfs_dir_t lfs_dir; + long off; +} vfs_lfs_dir_t; + +//------------------------------- +static int map_lfs_error(int err) +{ + if (err == LFS_ERR_OK) + { + return 0; + } + + switch (err) + { + case LFS_ERR_IO: + errno = EIO; + break; + case LFS_ERR_CORRUPT: + errno = EIO; + break; + case LFS_ERR_NOENT: + errno = ENOENT; + break; + case LFS_ERR_EXIST: + errno = EEXIST; + break; + case LFS_ERR_NOTDIR: + errno = ENOTDIR; + break; + case LFS_ERR_ISDIR: + errno = EISDIR; + break; + case LFS_ERR_NOTEMPTY: + errno = ENOTEMPTY; + break; + case LFS_ERR_INVAL: + errno = EINVAL; + break; + case LFS_ERR_NOSPC: + errno = ENOSPC; + break; + case LFS_ERR_NOMEM: + errno = ENOMEM; + break; + default: + errno = EINVAL; + break; + } + + return -1; +} + +//---------------------- +static int get_free_fd() +{ + for (int i = 0; i < littleFlash.open_files; i++) { + if (littleFlash.fds[i].file == NULL) return i; + } + + return -1; +} + +//---------------------------------------------------------------------- +static ssize_t write_p(void *ctx, int fd, const void *data, size_t size) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + if (self->fds[fd].file == NULL) + { + _lock_release(&self->lock); + errno = EBADF; + return -1; + } + + lfs_ssize_t written = lfs_file_write(&self->lfs, self->fds[fd].file, data, size); + + _lock_release(&self->lock); + + if (written < 0) + { + return map_lfs_error(written); + } + + return written; +} + +//----------------------------------------------------------- +static off_t lseek_p(void *ctx, int fd, off_t size, int mode) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + int lfs_mode = 0; + if (mode == SEEK_SET) + { + lfs_mode = LFS_SEEK_SET; + } + else if (mode == SEEK_CUR) + { + lfs_mode = LFS_SEEK_CUR; + } + else if (mode == SEEK_END) + { + lfs_mode = LFS_SEEK_END; + } + else + { + errno = EINVAL; + return -1; + } + + _lock_acquire(&self->lock); + + if (self->fds[fd].file == NULL) + { + _lock_release(&self->lock); + errno = EBADF; + return -1; + } + + lfs_soff_t pos = lfs_file_seek(&self->lfs, self->fds[fd].file, size, lfs_mode); + + if (pos >= 0) + { + pos = lfs_file_tell(&self->lfs, self->fds[fd].file); + } + + _lock_release(&self->lock); + + if (pos < 0) + { + return map_lfs_error(pos); + } + + return pos; +} + +//-------------------------------------------------------------- +static ssize_t read_p(void *ctx, int fd, void *dst, size_t size) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + if (self->fds[fd].file == NULL) + { + _lock_release(&self->lock); + errno = EBADF; + return -1; + } + + lfs_ssize_t read = lfs_file_read(&self->lfs, self->fds[fd].file, dst, size); + + _lock_release(&self->lock); + + if (read < 0) + { + return map_lfs_error(read); + } + + return read; +} + +//----------------------------------------------------------------- +static int open_p(void *ctx, const char *path, int flags, int mode) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + int lfs_flags = 0; + if ((flags & O_ACCMODE) == O_RDONLY) + { + lfs_flags = LFS_O_RDONLY; + } + else if ((flags & O_ACCMODE) == O_WRONLY) + { + lfs_flags = LFS_O_WRONLY; + } + else if ((flags & O_ACCMODE) == O_RDWR) + { + lfs_flags = LFS_O_RDWR; + } + + if (flags & O_CREAT) + { + lfs_flags |= LFS_O_CREAT; + } + + if (flags & O_EXCL) + { + lfs_flags |= LFS_O_EXCL; + } + + if (flags & O_TRUNC) + { + lfs_flags |= LFS_O_TRUNC; + } + + if (flags & O_APPEND) + { + lfs_flags |= LFS_O_APPEND; + } + + lfs_file_t *file = (lfs_file_t *) malloc(sizeof(lfs_file_t)); + if (file == NULL) + { + errno = ENOMEM; + return -1; + } + + char *name = strdup(path); + if (name == NULL) + { + free(file); + errno = ENOMEM; + return -1; + } + + _lock_acquire(&self->lock); + + int fd = get_free_fd(); + if (fd == -1) + { + _lock_release(&self->lock); + free(name); + free(file); + errno = ENFILE; + return -1; + } + + int err = lfs_file_open(&self->lfs, file, path, lfs_flags); + if (err < 0) + { + _lock_release(&self->lock); + free(name); + free(file); + return map_lfs_error(err); + } + + self->fds[fd].file = file; + self->fds[fd].name = name; + + _lock_release(&self->lock); + + return fd; +} + +//----------------------------------- +static int close_p(void *ctx, int fd) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + if (self->fds[fd].file == NULL) + { + _lock_release(&self->lock); + errno = EBADF; + return -1; + } + + int err = lfs_file_close(&self->lfs, self->fds[fd].file); + + free(self->fds[fd].name); + free(self->fds[fd].file); + memset(&self->fds[fd], 0 , sizeof(vfs_fd_t)); + + _lock_release(&self->lock); + + return map_lfs_error(err); +} + +//---------------------------------------------------- +static int fstat_p(void *ctx, int fd, struct stat *st) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + if (self->fds[fd].file == NULL) + { + _lock_release(&self->lock); + errno = EBADF; + return -1; + } + + struct lfs_info lfs_info;; + int err = lfs_stat(&self->lfs, self->fds[fd].name, &lfs_info); + + _lock_release(&self->lock); + + if (err < 0) + { + return map_lfs_error(err); + } + + st->st_size = lfs_info.size; + if (lfs_info.type == LFS_TYPE_DIR) + { + st->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO; + } + else + { + st->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO; + } + st->st_mtime = lfs_info.time; + st->st_atime = 0; + st->st_ctime = 0; + + return 0; +} + +//------------------------------------------------------------- +static int stat_p(void *ctx, const char *path, struct stat *st) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + struct lfs_info lfs_info; + int err = lfs_stat(&self->lfs, path, &lfs_info); + + _lock_release(&self->lock); + + if (err < 0) + { + return map_lfs_error(err); + } + + st->st_size = lfs_info.size; + if (lfs_info.type == LFS_TYPE_DIR) + { + st->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO; + } + else + { + st->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO; + } + st->st_mtime = lfs_info.time; + st->st_atime = 0; + st->st_ctime = 0; + + return 0; +} + +//---------------------------------------------- +static int unlink_p(void *ctx, const char *path) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + int err = lfs_remove(&self->lfs, path); + + _lock_release(&self->lock); + + return map_lfs_error(err); +} + +//-------------------------------------------------------------- +static int rename_p(void *ctx, const char *src, const char *dst) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + int err = lfs_rename(&self->lfs, src, dst); + + _lock_release(&self->lock); + + return map_lfs_error(err); +} + +//------------------------------------------------ +static DIR *opendir_p(void *ctx, const char *name) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + vfs_lfs_dir_t *vfs_dir = (vfs_lfs_dir_t *) malloc(sizeof(vfs_lfs_dir_t)); + if (vfs_dir == NULL) + { + errno = ENOMEM; + return NULL; + } + //*vfs_dir = {}; + + _lock_acquire(&self->lock); + + int err = lfs_dir_open(&self->lfs, &vfs_dir->lfs_dir, name); + + _lock_release(&self->lock); + + if (err != LFS_ERR_OK) + { + free(vfs_dir); + vfs_dir = NULL; + map_lfs_error(err); + } + + return (DIR *) vfs_dir; +} + +//-------------------------------------------------------------------------------------------- +static int readdir_r_p(void *ctx, DIR *pdir, struct dirent *entry, struct dirent **out_dirent) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + vfs_lfs_dir_t *vfs_dir = (vfs_lfs_dir_t *) pdir; + if (vfs_dir == NULL) + { + errno = EBADF; + return errno; + } + + _lock_acquire(&self->lock); + + struct lfs_info lfs_info; + int err = lfs_dir_read(&self->lfs, &vfs_dir->lfs_dir, &lfs_info); + + _lock_release(&self->lock); + + if (err == 0) + { + *out_dirent = NULL; + return 0; + } + + if (err < 0) + { + map_lfs_error(err); + return errno; + } + + entry->d_ino = 0; + if (lfs_info.type == LFS_TYPE_REG) + { + entry->d_type = DT_REG; + } + else if (lfs_info.type == LFS_TYPE_DIR) + { + entry->d_type = DT_DIR; + } + else + { + entry->d_type = DT_UNKNOWN; + } + size_t len = strlcpy(entry->d_name, lfs_info.name, sizeof(entry->d_name)); + + // This "shouldn't" happen, but the LFS name length can be customized and may + // be longer than what's provided in "struct dirent" + if (len >= sizeof(entry->d_name)) + { + errno = ENAMETOOLONG; + return errno; + } + + vfs_dir->off++; + + *out_dirent = entry; + + return 0; +} + +//--------------------------------------------------- +static struct dirent *readdir_p(void *ctx, DIR *pdir) +{ + vfs_lfs_dir_t *vfs_dir = (vfs_lfs_dir_t *) pdir; + if (vfs_dir == NULL) + { + errno = EBADF; + return NULL; + } + + struct dirent *out_dirent = NULL; + + int err = readdir_r_p(ctx, pdir, &vfs_dir->dirent, &out_dirent); + if (err != 0) + { + errno = err; + } + + return out_dirent; +} + +//----------------------------------------- +static long telldir_p(void *ctx, DIR *pdir) +{ + vfs_lfs_dir_t *vfs_dir = (vfs_lfs_dir_t *) pdir; + if (vfs_dir == NULL) + { + errno = EBADF; + return errno; + } + + return vfs_dir->off; +} + +//------------------------------------------------------ +static void seekdir_p(void *ctx, DIR *pdir, long offset) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + vfs_lfs_dir_t *vfs_dir = (vfs_lfs_dir_t *) pdir; + if (vfs_dir == NULL) + { + errno = EBADF; + return; + } + + _lock_acquire(&self->lock); + + // ESP32 VFS expects simple 0 to n counted directory offsets but lfs + // doesn't so we need to "translate"... + int err = lfs_dir_rewind(&self->lfs, &vfs_dir->lfs_dir); + if (err >= 0) + { + for (vfs_dir->off = 0; vfs_dir->off < offset; ++vfs_dir->off) + { + struct lfs_info lfs_info; + err = lfs_dir_read(&self->lfs, &vfs_dir->lfs_dir, &lfs_info); + if (err < 0) + { + break; + } + } + } + + _lock_release(&self->lock); + + if (err < 0) + { + map_lfs_error(err); + return; + } + + return; +} + +//----------------------------------------- +static int closedir_p(void *ctx, DIR *pdir) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + vfs_lfs_dir_t *vfs_dir = (vfs_lfs_dir_t *) pdir; + if (vfs_dir == NULL) + { + errno = EBADF; + return -1; + } + + _lock_acquire(&self->lock); + + int err = lfs_dir_close(&self->lfs, &vfs_dir->lfs_dir); + + _lock_release(&self->lock); + + free(vfs_dir); + + return map_lfs_error(err); +} + +//---------------------------------------------------------- +static int mkdir_p(void *ctx, const char *name, mode_t mode) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + int err = lfs_mkdir(&self->lfs, name); + + _lock_release(&self->lock); + + return map_lfs_error(err); +} + +//--------------------------------------------- +static int rmdir_p(void *ctx, const char *name) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + int err = lfs_remove(&self->lfs, name); + + _lock_release(&self->lock); + + return map_lfs_error(err); +} + +//----------------------------------- +static int fsync_p(void *ctx, int fd) +{ + littleFlash_t *self = (littleFlash_t *) ctx; + + _lock_acquire(&self->lock); + + if (self->fds[fd].file == NULL) + { + _lock_release(&self->lock); + errno = EBADF; + return -1; + } + + int err = lfs_file_sync(&self->lfs, self->fds[fd].file); + + _lock_release(&self->lock); + + return map_lfs_error(err); +} + + +// ============================================================================ +// LittleFlash global functions +// ============================================================================ + +#include +#include +//============================================================= +esp_err_t littleFlash_init(const little_flash_config_t *config) +{ + ESP_LOGV(TAG, "%s", __func__); + + int err; + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + size_t sector_size = CONFIG_WL_SECTOR_SIZE; + #else + size_t sector_size = SPI_FLASH_SEC_SIZE; + #endif + size_t block_cnt = config->part->size / SPI_FLASH_SEC_SIZE; + + if (block_buffer == NULL) { + block_buffer = heap_caps_malloc(sector_size, MALLOC_CAP_DMA); + if (block_buffer == NULL) { + ESP_LOGE(TAG, "failed to allocate read buffer"); + return ESP_ERR_NO_MEM; + } + } + + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + ESP_LOGD(TAG, "LittleFS on top of ESP32 wear leveling"); + + err = wl_mount(config->part, &lfs_wl_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "failed to mount wear leveling layer. result = %i", err); + return ESP_FAIL; + } + block_cnt = wl_size(lfs_wl_handle) / sector_size; + ESP_LOGD(TAG, "Original_partition_size=%uKB, WL_size=%uKB", config->part->size/1024, wl_size(lfs_wl_handle)/1024); + #endif + + _lock_init(&littleFlash.lock); + + littleFlash.open_files = config->open_files; + littleFlash.part = config->part; + + memset(&littleFlash.lfs, 0, sizeof(lfs_t)); + littleFlash.sector_sz = sector_size; + littleFlash.block_cnt = block_cnt; + + littleFlash.lfs_cfg.read = &internal_read; + littleFlash.lfs_cfg.prog = &internal_prog; + littleFlash.lfs_cfg.erase = &internal_dummy_erase; + littleFlash.lfs_cfg.sync = &internal_sync; + + littleFlash.lfs_cfg.read_size = littleFlash.sector_sz; + littleFlash.lfs_cfg.prog_size = littleFlash.sector_sz; + littleFlash.lfs_cfg.block_size = littleFlash.sector_sz; + littleFlash.lfs_cfg.block_count = littleFlash.block_cnt; + littleFlash.lfs_cfg.lookahead = config->lookahead; + littleFlash.lfs_cfg.context = (void *)&littleFlash; + + err = lfs_mount(&littleFlash.lfs, &littleFlash.lfs_cfg); + if (err < 0) + { + lfs_unmount(&littleFlash.lfs); + if (!config->auto_format) { + ESP_LOGE(TAG, "Error mounting (%d), auto format not requested", err); + goto fail; + } + + memset(&littleFlash.lfs, 0, sizeof(lfs_t)); + ESP_LOGW(TAG, "Error mounting (%d), auto format requested", err); + // Erase first 4 blocks + for (int i=0; i<4; i++) { + err = internal_erase(&littleFlash.lfs_cfg, i); + if (err < LFS_ERR_OK) { + ESP_LOGE(TAG, "Error erasing flash - %d", err); + goto fail; + } + } + // format + err = lfs_format(&littleFlash.lfs, &littleFlash.lfs_cfg); + if (err < 0) + { + lfs_unmount(&littleFlash.lfs); + ESP_LOGE(TAG, "Error formating - %d", err); + goto fail; + } + + memset(&littleFlash.lfs, 0, sizeof(lfs_t)); + err = lfs_mount(&littleFlash.lfs, &littleFlash.lfs_cfg); + if (err < 0) + { + lfs_unmount(&littleFlash.lfs); + ESP_LOGE(TAG, "Error mounting after format"); + goto fail; + } + ESP_LOGW(TAG, "Formated and mounted"); + } + littleFlash.mounted = true; + + littleFlash.fds = malloc(sizeof(vfs_fd_t) * littleFlash.open_files); + if (littleFlash.fds == NULL) + { + ESP_LOGE(TAG, "Error allocating fds structure"); + goto fail; + } + + for (int i = 0; i < littleFlash.open_files; i++) + { + littleFlash.fds[i].file = NULL; + littleFlash.fds[i].name = NULL; + } + + esp_vfs_t vfs = {0}; + + vfs.flags = ESP_VFS_FLAG_CONTEXT_PTR; + vfs.write_p = &write_p; + vfs.lseek_p = &lseek_p; + vfs.read_p = &read_p; + vfs.open_p = &open_p; + vfs.close_p = &close_p; + vfs.fstat_p = &fstat_p; + vfs.stat_p = &stat_p; + vfs.unlink_p = &unlink_p; + vfs.rename_p = &rename_p; + vfs.opendir_p = &opendir_p; + vfs.readdir_p = &readdir_p; + vfs.readdir_r_p = &readdir_r_p; + vfs.telldir_p = &telldir_p; + vfs.seekdir_p = &seekdir_p; + vfs.closedir_p = &closedir_p; + vfs.mkdir_p = &mkdir_p; + vfs.rmdir_p = &rmdir_p; + vfs.fsync_p = &fsync_p; + + esp_err_t esperr = esp_vfs_register(config->base_path, &vfs, &littleFlash); + if (esperr != ESP_OK) + { + lfs_unmount(&littleFlash.lfs); + littleFlash.mounted = false; + ESP_LOGE(TAG, "Error registering littleflash to VFS"); + goto fail; + } + + littleFlash.registered = true; + + return ESP_OK; + +fail: + free(block_buffer); + block_buffer = NULL; + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + wl_unmount(lfs_wl_handle); + lfs_wl_handle = WL_INVALID_HANDLE; + #endif + return ESP_FAIL; +} + +//================================================ +void littleFlash_term(const char* partition_label) +{ + ESP_LOGV(TAG, "%s", __func__); + + if (littleFlash.registered) + { + for (int i = 0; i < littleFlash.open_files; i++) + { + if (littleFlash.fds[i].file) + { + close_p(&littleFlash, i); + littleFlash.fds[i].file = NULL; + } + } + + esp_vfs_unregister(partition_label); + littleFlash.registered = false; + } + + if (littleFlash.fds) + { + free(littleFlash.fds); + littleFlash.fds = NULL; + } + + if (littleFlash.mounted) + { + lfs_unmount(&littleFlash.lfs); + littleFlash.mounted = false; + } + + if (block_buffer) free(block_buffer); + + #ifdef CONFIG_LITTLEFLASH_USE_WEAR_LEVELING + wl_unmount(lfs_wl_handle); + lfs_wl_handle = WL_INVALID_HANDLE; + #endif + _lock_close(&littleFlash.lock); +} + +//-------------------------------------------- +static int lfs_count(void *p, lfs_block_t b) { + *(lfs_size_t *)p += 1; + return 0; +} + +//================================== +uint32_t littleFlash_getUsedBlocks() +{ + lfs_size_t in_use = 0; + _lock_acquire(&littleFlash.lock); + lfs_traverse(&littleFlash.lfs, lfs_count, &in_use); + _lock_release(&littleFlash.lock); + return in_use; +} + +//==================================================== +uint32_t littleFlash_trim(int max_blocks, int noerase) +{ + lfs_block_t block; + uint32_t nfree = 0; + uint32_t nerased = 0; + uint32_t nblocks = max_blocks; + if (nblocks == 0) nblocks = littleFlash.block_cnt; + littleFlash.lfs.free.off = 0; + + mp_hal_set_wdt_tmo(); + lfs_setup_free(&littleFlash.lfs); + + struct timeval tv; + gettimeofday(&tv, NULL); + uint32_t tstart = tv.tv_sec * 1000 + (tv.tv_usec / 1000); + + for (int i=0; i 0) { + gettimeofday(&tv, NULL); + uint32_t tend = tv.tv_sec * 1000 + (tv.tv_usec / 1000); + ESP_LOGW(TAG, "Erased %u in %d ms, %d ms/block", nerased, tend-tstart, (tend-tstart)/ nerased); + } + lfs_setup_free(&littleFlash.lfs); + + return nfree; +} +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/littleflash.h b/MicroPython_BUILD/components/micropython/esp32/libs/littleflash.h new file mode 100644 index 00000000..64379ada --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/littleflash.h @@ -0,0 +1,79 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * Adapted from https://github.com/lllucius/esp32_littleflash, see the Copyright and license notice below + * + */ + +// Copyright 2017-2018 Leland Lucius +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#if !defined(_LITTLEFLASH_H_) +#define _LITTLEFLASH_H_ 1 + +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 2 + +#include + +#include "esp_err.h" +#include "esp_vfs.h" +#include "esp_partition.h" + +#include "lfs.h" + + +typedef struct +{ + esp_partition_t *part; // partition to be used + char *base_path; // mount point + int open_files; // number of open files to support + bool auto_format; // true=format if not valid + lfs_size_t lookahead; // number of LFS lookahead blocks +} little_flash_config_t; + +typedef struct vfs_fd +{ + lfs_file_t *file; + char *name; +} vfs_fd_t; + +typedef struct { + _lock_t lock; + struct lfs_config lfs_cfg; // littlefs configuration + esp_partition_t *part; // partition to be used + int open_files; // number of open files to support + size_t sector_sz; // sector size + size_t block_cnt; // block count + lfs_t lfs; // The littlefs type + bool mounted; + bool registered; + vfs_fd_t *fds; +} littleFlash_t; + +extern littleFlash_t littleFlash; + +esp_err_t littleFlash_init(const little_flash_config_t *config); + +void littleFlash_term(); + +uint32_t littleFlash_getUsedBlocks(); + +uint32_t littleFlash_trim(int max_blocks, int noerase); + +#endif + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_button.c b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_button.c new file mode 100644 index 00000000..809febf0 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_button.c @@ -0,0 +1,126 @@ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "m5ui.h" +#endif + +#define BUTTONA_X 34 +#define BUTTONB_X 126 +#define BUTTONC_X 222 +#define BUTTON_Y 216 +#define BUTTON_W 70 +#define BUTTON_H 30 + +typedef struct _m5ui_button_obj_t { + mp_obj_base_t base; + uint8_t visibility; + uint8_t x; + char text[10]; +} m5ui_button_obj_t; + +m5ui_button_obj_t btn_a = {.x = BUTTONA_X}; +m5ui_button_obj_t btn_b = {.x = BUTTONB_X}; +m5ui_button_obj_t btn_c = {.x = BUTTONC_X}; + + +// STATIC mp_obj_t m5ui_button_hide(mp_obj_t self_in) { +// m5ui_button_obj_t *self = self_in; +// TFT_fillRect(self->x, self->y, self->w, self->h, ui_bg_color); +// return mp_const_none; + +// } +// STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_button_hide_obj, m5ui_button_hide); + +// STATIC mp_obj_t m5ui_button_show(mp_obj_t self_in) { +// m5ui_button_obj_t *self = self_in; +// TFT_fillRect(self->x, self->y,self->w, self->h, self->fill_color); +// TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); +// return mp_const_none; + +// } +// STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_button_show_obj, m5ui_button_show); + +STATIC void m5ui_button_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_printf(print, "hello m5 button..."); +} + +mp_obj_t m5ui_button_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args){ + //--------------------------------------------------------------------- + const mp_arg_t m5ui_button_init_allowed_args[] = { + { MP_QSTR_name, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_visibility, MP_ARG_INT, {.u_int = 0}}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(m5ui_button_init_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(m5ui_button_init_allowed_args), m5ui_button_init_allowed_args, args); + + const char *tstr = NULL; + m5ui_button_obj_t *self = NULL; + tstr = mp_obj_str_get_str(args[0].u_obj); + if(strlen(tstr) > 9){ + mp_raise_ValueError("button name too long"); + } + + if(strcmp("ButtonA", tstr) == 0){ + self = &btn_a; + } else if(strcmp("ButtonB", tstr) == 0){ + self = &btn_b; + } else { + self = &btn_c; + } + + tstr = mp_obj_str_get_str(args[1].u_obj); + if(strlen(tstr) > 9){ + mp_raise_ValueError("button name too long"); + } + + sprintf(self->text, "%s", tstr); + self->visibility = args[2].u_int; + color_t white = { .r = 0xff, .g=0xff, .b=0xff }; + if(self->visibility == 1) { + TFT_drawRoundRect(self->x, BUTTON_Y, BUTTON_W, BUTTON_H, 5, white); + color_t old_fg = _fg; + _fg = white; + TFT_setFont(0, (char *)NULL); + TFT_print(self->text, self->x + BUTTON_W/2 - TFT_getStringWidth(self->text)/2, 224); + _fg = old_fg; + } + return MP_OBJ_FROM_PTR(self); +} + +//=============================================================== +STATIC const mp_rom_map_elem_t m5ui_button_locals_dict_table[] = { + // { MP_ROM_QSTR(MP_QSTR_hide), (mp_obj_t)&m5ui_button_hide_obj}, + // { MP_ROM_QSTR(MP_QSTR_show), (mp_obj_t)&m5ui_button_show_obj}, +}; + +STATIC MP_DEFINE_CONST_DICT(m5ui_button_locals_dict, m5ui_button_locals_dict_table); + +//==================================== +const mp_obj_type_t m5ui_button_type = { + { &mp_type_type }, + .name = MP_QSTR_M5Button, + .make_new = m5ui_button_make_new, + .print = m5ui_button_print, + .locals_dict = (mp_obj_dict_t*)&m5ui_button_locals_dict, +}; \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_circle.c b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_circle.c new file mode 100644 index 00000000..7d96ebc7 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_circle.c @@ -0,0 +1,198 @@ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" +#include "esp_task_wdt.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "libs/qrcode.h" + +#include "m5ui.h" +#endif + +typedef struct _m5ui_circle_obj_t { + mp_obj_base_t base; + uint16_t x; + uint16_t y; + uint16_t r; + color_t fill_color; + color_t draw_color; +} m5ui_circle_obj_t; + +typedef struct _circle_list_t { + uint8_t head; + m5ui_circle_obj_t *list[20]; +} circle_list_t; + +circle_list_t circle_list = { + .head = 0, +}; + +STATIC color_t intToColor(uint32_t cint) +{ + color_t cl = {0,0,0}; + cl.r = (cint >> 16) & 0xFF; + cl.g = (cint >> 8) & 0xFF; + cl.b = cint & 0xFF; + return cl; +} + +STATIC void m5ui_circle_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_printf(print, "hello m5 circle..."); +} + +mp_obj_t m5ui_circle_deinit() { + for(uint8_t i = 0; i < circle_list.head; i++) { + if(circle_list.list[i] != NULL) { + // m_del_obj(m5ui_circle_obj_t, circle_list.list[i]); + circle_list.list[i] = NULL; + } + } + circle_list.head = 0; + return mp_const_none; +} + +// STATIC MP_DEFINE_CONST_FUN_OBJ_0(m5ui_circle_deinit_obj, m5ui_circle_deinit); + +STATIC mp_obj_t m5ui_circle_resize(mp_obj_t self_in, mp_obj_t r_in) { + m5ui_circle_obj_t *self = self_in; + uint16_t r = mp_obj_get_int(r_in); + if( r == self->r) { + return mp_const_none; + } else if(r > self->r) { + TFT_fillCircle(self->x, self->y, r, self->fill_color); + } else { + TFT_fillCircle(self->x, self->y, self->r + 1, ui_bg_color); + TFT_fillCircle(self->x, self->y, r, self->fill_color); + } + TFT_drawCircle(self->x, self->y, r, self->draw_color); + self->r = r; + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_circle_resize_obj, m5ui_circle_resize); + +STATIC mp_obj_t m5ui_circle_setposition(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + m5ui_circle_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_INT, { .u_int = self->x } }, + { MP_QSTR_y, MP_ARG_INT, { .u_int = self->y } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + if(self->x != args[0].u_int || self->y != args[1].u_int){ + TFT_fillCircle(self->x, self->y, self->r + 1, ui_bg_color); + self->x = args[0].u_int; + self->y = args[1].u_int; + } + TFT_fillCircle(self->x, self->y,self->r, self->fill_color); + TFT_drawCircle(self->x, self->y, self->r, self->draw_color); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(m5ui_circle_setposition_obj, 1, m5ui_circle_setposition); + + +STATIC mp_obj_t m5ui_circle_setbgcolor(mp_obj_t self_in, mp_obj_t color_in) { + m5ui_circle_obj_t *self = self_in; + self->fill_color = intToColor(mp_obj_get_int(color_in)); + TFT_fillCircle(self->x, self->y,self->r, self->fill_color); + TFT_drawCircle(self->x, self->y, self->r, self->draw_color); + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_circle_setbgcolor_obj, m5ui_circle_setbgcolor); + +STATIC mp_obj_t m5ui_circle_setbordercolor(mp_obj_t self_in, mp_obj_t color_in) { + m5ui_circle_obj_t *self = self_in; + self->draw_color = intToColor(mp_obj_get_int(color_in)); + TFT_drawCircle(self->x, self->y, self->r, self->draw_color); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_circle_setbordercolor_obj, m5ui_circle_setbordercolor); + +STATIC mp_obj_t m5ui_circle_show(mp_obj_t self_in) { + m5ui_circle_obj_t *self = self_in; + TFT_fillCircle(self->x, self->y,self->r, self->fill_color); + TFT_drawCircle(self->x, self->y, self->r, self->draw_color); + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_circle_show_obj, m5ui_circle_show); + +STATIC mp_obj_t m5ui_circle_hide(mp_obj_t self_in) { + m5ui_circle_obj_t *self = self_in; + TFT_fillCircle(self->x, self->y,self->r, ui_bg_color); + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_circle_hide_obj, m5ui_circle_hide); + +mp_obj_t m5ui_circle_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args){ + enum { ARG_x, ARG_y, ARG_r, ARG_fillcolor, ARG_drawcolor }; + //--------------------------------------------------------------------- + const mp_arg_t m5ui_circle_init_allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_fillcolor, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_color, MP_ARG_INT, {.u_int = -1}}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(m5ui_circle_init_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(m5ui_circle_init_allowed_args), m5ui_circle_init_allowed_args, args); + + m5ui_circle_obj_t *self = m_new_obj(m5ui_circle_obj_t); + self->base.type = &m5ui_circle_type; + self->x = args[ARG_x].u_int; + self->y = args[ARG_y].u_int; + self->r = args[ARG_r].u_int; + self->fill_color = intToColor(args[ARG_fillcolor].u_int); + self->draw_color = self->fill_color; + TFT_fillCircle(self->x, self->y, self->r, self->fill_color); + if(args[ARG_drawcolor].u_int >= 0){ + self->draw_color = intToColor(args[ARG_drawcolor].u_int); + TFT_drawCircle(self->x, self->y, self->r, self->draw_color); + } + circle_list.list[circle_list.head++] = self; + circle_list.head = circle_list.head > 19 ? 19 : circle_list.head; + return MP_OBJ_FROM_PTR(self); +} + +//=============================================================== +STATIC const mp_rom_map_elem_t m5ui_circle_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_setSize), (mp_obj_t)&m5ui_circle_resize_obj}, + { MP_ROM_QSTR(MP_QSTR_setBgColor), (mp_obj_t)&m5ui_circle_setbgcolor_obj}, + { MP_ROM_QSTR(MP_QSTR_setBorderColor), (mp_obj_t)&m5ui_circle_setbordercolor_obj}, + { MP_ROM_QSTR(MP_QSTR_setPosition), (mp_obj_t)&m5ui_circle_setposition_obj}, + { MP_ROM_QSTR(MP_QSTR_hide), (mp_obj_t)&m5ui_circle_hide_obj}, + { MP_ROM_QSTR(MP_QSTR_show), (mp_obj_t)&m5ui_circle_show_obj}, + + // { MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&m5ui_circle_deinit_obj}, +}; + +STATIC MP_DEFINE_CONST_DICT(m5ui_circle_locals_dict, m5ui_circle_locals_dict_table); + +//==================================== +const mp_obj_type_t m5ui_circle_type = { + { &mp_type_type }, + .name = MP_QSTR_M5Circle, + .make_new = m5ui_circle_make_new, + .print = m5ui_circle_print, + .locals_dict = (mp_obj_dict_t*)&m5ui_circle_locals_dict, +}; \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_img.c b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_img.c new file mode 100644 index 00000000..72e98eb8 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_img.c @@ -0,0 +1,235 @@ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "m5ui.h" +#endif + +#if !defined(max) +#define max(A,B) ( (A) > (B) ? (A):(B)) +#endif +#if !defined(min) +#define min(A,B) ( (A) < (B) ? (A):(B)) +#endif +typedef struct _m5ui_img_obj_t { + mp_obj_base_t base; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t hight; + uint8_t type; + uint8_t visibility; + char text[20]; +} m5ui_img_obj_t; + +STATIC void img_show(m5ui_img_obj_t *self) { + char fullname[128] = {'\0'}; + physicalPath(self->text, fullname); + if(self->type == IMAGE_TYPE_BMP) { + TFT_bmp_image(self->x, self->y, 0, fullname, NULL, 0); + } else if (self->type == IMAGE_TYPE_JPG) { + TFT_jpg_image(self->x, self->y, 0, fullname, NULL, 0); + } else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported image type")); + } + self->width = image_width; + self->hight = image_hight; + self->visibility = 1; +} + +STATIC void m5ui_img_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + m5ui_img_obj_t *self = self_in; + mp_printf(print, "img size x:%d y:%d", self->width, self->hight); +} + +mp_obj_t m5ui_img_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args){ + //--------------------------------------------------------------------- + const mp_arg_t m5ui_img_init_allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_name, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_visibility, MP_ARG_INT, {.u_int = 1}}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(m5ui_img_init_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(m5ui_img_init_allowed_args), m5ui_img_init_allowed_args, args); + + m5ui_img_obj_t *self = m_new_obj(m5ui_img_obj_t); + self->base.type = &m5ui_img_type; + self->x = args[0].u_int; + self->y = args[1].u_int; + self->visibility = args[3].u_int; + + char *fname = NULL; + int img_type = 0; + char fullname[128] = {'\0'}; + fname = (char *)mp_obj_str_get_str(args[2].u_obj); + if(strlen(fname) > 19) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported image type")); + } + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + + char upr_fname[128]; + strcpy(upr_fname, fname); + for (int i=0; i < strlen(upr_fname); i++) { + upr_fname[i] = toupper((unsigned char) upr_fname[i]); + } + if (strstr(upr_fname, ".JPG") != NULL) img_type = IMAGE_TYPE_JPG; + else if (strstr(upr_fname, ".BMP") != NULL) img_type = IMAGE_TYPE_BMP; + else { + FILE *fhndl = fopen(fullname, "r"); + if (fhndl != NULL) { + uint8_t buf[16]; + if (fread(buf, 1, 11, fhndl) == 11) { + buf[10] = 0; + if (strstr((char *)(buf+6), "JFIF") != NULL) img_type = IMAGE_TYPE_JPG; + else if ((buf[0] = 0x42) && (buf[1] = 0x4d)) img_type = IMAGE_TYPE_BMP; + } + fclose(fhndl); + } + } + + if (img_type == IMAGE_TYPE_BMP) { + if(self->visibility) { + TFT_bmp_image(args[0].u_int, args[1].u_int, 0, fullname, NULL, 0); + } + } + else if (img_type == IMAGE_TYPE_JPG) { + if(self->visibility) { + TFT_jpg_image(args[0].u_int, args[1].u_int, 0, fullname, NULL, 0); + } + } + else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported image type")); + } + sprintf(self->text, "%s", fname); + self->type = img_type; + self->width = image_width; + self->hight = image_hight; + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t m5ui_img_hide(mp_obj_t self_in) { + m5ui_img_obj_t *self = self_in; + if(self->visibility) { + TFT_fillRect(self->x, self->y, self->width, self->hight, ui_bg_color); + self->visibility = 0; + } + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_img_hide_obj, m5ui_img_hide); + +STATIC mp_obj_t m5ui_img_show(mp_obj_t self_in) { + m5ui_img_obj_t *self = self_in; + img_show(self); + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_img_show_obj, m5ui_img_show); + +STATIC mp_obj_t m5ui_img_setposition(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + m5ui_img_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_INT, { .u_int = self->x } }, + { MP_QSTR_y, MP_ARG_INT, { .u_int = self->y } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + uint16_t x = args[0].u_int; + uint16_t y = args[1].u_int; + if(self->x == args[0].u_int && self->y == args[1].u_int) { + return mp_const_none; + } + if((max(self->x, x) > min(self->x, x) + self->width) || (max(self->y, y) > min(self->y, y) + self->hight)) { + TFT_fillRect(self->x, self->y, self->width, self->hight, ui_bg_color); + } else { + TFT_fillRect(self->x > x ? x+self->width : self->x, self->y, abs(self->x - x), self->hight, ui_bg_color); + TFT_fillRect(self->x, self->y > y ? y + self->hight : self->y, self->width, abs(self->y - y), ui_bg_color); + } + self->x = x; + self->y = y; + img_show(self); + + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(m5ui_img_setposition_obj, 1, m5ui_img_setposition); + +STATIC mp_obj_t m5ui_img_changeimg(mp_obj_t self_in, mp_obj_t name_in){ + m5ui_img_obj_t *self = self_in; + const char *fname = mp_obj_str_get_str(name_in); + uint16_t old_width = self->width; + uint16_t old_hight = self->hight; + + uint8_t img_type = 0; + char fullname[128] = {'\0'}; + if(strlen(fname) > 19) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "name too len")); + } + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + + char upr_fname[128]; + strcpy(upr_fname, fname); + for (int i=0; i < strlen(upr_fname); i++) { + upr_fname[i] = toupper((unsigned char) upr_fname[i]); + } + if (strstr(upr_fname, ".JPG") != NULL) img_type = IMAGE_TYPE_JPG; + else if (strstr(upr_fname, ".BMP") != NULL) img_type = IMAGE_TYPE_BMP; + self->type = img_type; + sprintf(self->text, "%s", fname); + img_show(self); + if(self->width < old_width){ + TFT_fillRect(self->x+self->width, self->y, old_width - self->width, old_hight, ui_bg_color); + } + if(self->hight < old_hight){ + TFT_fillRect(self->x, self->y+self->hight, old_hight, old_hight - self->hight, ui_bg_color); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_img_changeimg_obj, m5ui_img_changeimg); + + +//=============================================================== +STATIC const mp_rom_map_elem_t m5ui_img_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_hide), (mp_obj_t)&m5ui_img_hide_obj}, + { MP_ROM_QSTR(MP_QSTR_show), (mp_obj_t)&m5ui_img_show_obj}, + { MP_ROM_QSTR(MP_QSTR_setPosition), (mp_obj_t)&m5ui_img_setposition_obj}, + { MP_ROM_QSTR(MP_QSTR_changeImg), (mp_obj_t)&m5ui_img_changeimg_obj}, + +}; + +STATIC MP_DEFINE_CONST_DICT(m5ui_img_locals_dict, m5ui_img_locals_dict_table); + +//==================================== +const mp_obj_type_t m5ui_img_type = { + { &mp_type_type }, + .name = MP_QSTR_M5Img, + .make_new = m5ui_img_make_new, + .print = m5ui_img_print, + .locals_dict = (mp_obj_dict_t*)&m5ui_img_locals_dict, +}; \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_rect.c b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_rect.c new file mode 100644 index 00000000..b928d9cf --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_rect.c @@ -0,0 +1,249 @@ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" +#include "esp_task_wdt.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "libs/qrcode.h" + +#include "m5ui.h" +#endif + +#if !defined(max) +#define max(A,B) ( (A) > (B) ? (A):(B)) +#endif +#if !defined(min) +#define min(A,B) ( (A) < (B) ? (A):(B)) +#endif + +typedef struct _m5ui_rect_obj_t { + mp_obj_base_t base; + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; + color_t fill_color; + color_t draw_color; +} m5ui_rect_obj_t; + +typedef struct _rect_list_t { + uint8_t head; + m5ui_rect_obj_t *list[20]; +} rect_list_t; + +rect_list_t rect_list = { + .head = 0, +}; + +STATIC color_t intToColor(uint32_t cint) +{ + color_t cl = {0,0,0}; + cl.r = (cint >> 16) & 0xFF; + cl.g = (cint >> 8) & 0xFF; + cl.b = cint & 0xFF; + return cl; +} + +STATIC void m5ui_rect_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_printf(print, "hello m5 rect..."); +} + +mp_obj_t m5ui_rect_deinit() { + for(uint8_t i = 0; i < rect_list.head; i++) { + // m_del_obj(m5ui_rect_obj_t, rect_list.list[i]); + rect_list.list[i] = NULL; + } + rect_list.head = 0; + return mp_const_none; +} + +// STATIC MP_DEFINE_CONST_FUN_OBJ_0(m5ui_rect_deinit_obj, m5ui_rect_deinit); + +STATIC mp_obj_t m5ui_rect_resize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + m5ui_rect_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);; + const mp_arg_t allowed_args[] = { + { MP_QSTR_width, MP_ARG_INT, { .u_int = self->w } }, + { MP_QSTR_height, MP_ARG_INT, { .u_int = self->h } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + uint16_t width = args[0].u_int; + uint16_t hight = args[1].u_int; + + if(width == self->w && hight == self->h) { + return mp_const_none; + } + + if(width > self->w && hight > self->h) { + self->w = width; + self->h = hight; + TFT_fillRect(self->x, self->y,self->w, self->h, self->fill_color); + TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); + return mp_const_none; + } + + if(width > self->w) { + if(self->w > 0) { self->w -= 1; } + TFT_fillRect(self->x + self->w, self->y, width - self->w, self->h, self->fill_color); + } else if(width < self->w) { + TFT_fillRect(self->x + width, self->y, self->w - width, self->h, ui_bg_color); + } + self->w = width; + + if(hight > self->h){ + if(self->h > 0) { self->h -= 1; } + TFT_fillRect(self->x, self->y + self->h, self->w, hight - self->h, self->fill_color); + } else if(hight < self->h) { + TFT_fillRect(self->x, self->y + hight, self->w + 1, self->h - hight + 1, ui_bg_color); + } + self->h = hight; + + TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); + return mp_const_none; + +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(m5ui_rect_resize_obj, 1, m5ui_rect_resize); + +STATIC mp_obj_t m5ui_rect_setposition(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + m5ui_rect_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_INT, { .u_int = self->x } }, + { MP_QSTR_y, MP_ARG_INT, { .u_int = self->y } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if(args[0].u_int != self->x || args[1].u_int != self->y) { + TFT_fillRect(self->x, self->y,self->w, self->h, ui_bg_color); + self->x = args[0].u_int; + self->y = args[1].u_int; + } + TFT_fillRect(self->x, self->y,self->w, self->h, self->fill_color); + TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(m5ui_rect_setposition_obj, 1, m5ui_rect_setposition); + + +STATIC mp_obj_t m5ui_rect_hide(mp_obj_t self_in) { + m5ui_rect_obj_t *self = self_in; + TFT_fillRect(self->x, self->y, self->w, self->h, ui_bg_color); + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_rect_hide_obj, m5ui_rect_hide); + +STATIC mp_obj_t m5ui_rect_show(mp_obj_t self_in) { + m5ui_rect_obj_t *self = self_in; + TFT_fillRect(self->x, self->y,self->w, self->h, self->fill_color); + TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_rect_show_obj, m5ui_rect_show); + +STATIC mp_obj_t m5ui_rect_setbgcolor(mp_obj_t self_in, mp_obj_t color_in) { + m5ui_rect_obj_t *self = self_in; + self->fill_color = intToColor(mp_obj_get_int(color_in)); + TFT_fillRect(self->x, self->y,self->w, self->h, self->fill_color); + TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_rect_setbgcolor_obj, m5ui_rect_setbgcolor); + +STATIC mp_obj_t m5ui_rect_setbordercolor(mp_obj_t self_in, mp_obj_t color_in) { + m5ui_rect_obj_t *self = self_in; + self->draw_color = intToColor(mp_obj_get_int(color_in)); + TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_rect_setbordercolor_obj, m5ui_rect_setbordercolor); + +STATIC mp_obj_t m5ui_rect_isoverlap(mp_obj_t self_in, mp_obj_t rect_in) { + m5ui_rect_obj_t *self = self_in; + m5ui_rect_obj_t *rect = rect_in; + + bool result = false; + + result = (max(self->x, rect->x) > min(self->x + self->w, rect->x + rect->w)) + || (max(self->y, rect->y) > min(self->y + self->h, rect->y + rect->h)); + + result = !result; + return mp_obj_new_bool(result); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_rect_isoverlap_obj, m5ui_rect_isoverlap); + +mp_obj_t m5ui_rect_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args){ + enum { ARG_x, ARG_y, ARG_w, ARG_h, ARG_fillcolor, ARG_drawcolor }; + //--------------------------------------------------------------------- + const mp_arg_t m5ui_rect_init_allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_fillcolor, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_color, MP_ARG_INT, {.u_int = -1}}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(m5ui_rect_init_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(m5ui_rect_init_allowed_args), m5ui_rect_init_allowed_args, args); + + m5ui_rect_obj_t *self = m_new_obj(m5ui_rect_obj_t); + self->base.type = &m5ui_rect_type; + self->x = args[ARG_x].u_int; + self->y = args[ARG_y].u_int; + self->w = args[ARG_w].u_int; + self->h = args[ARG_h].u_int; + self->fill_color = intToColor(args[ARG_fillcolor].u_int); + self->draw_color = self->fill_color; + TFT_fillRect(self->x, self->y, self->w, self->h, self->fill_color); + if(args[ARG_drawcolor].u_int >= 0){ + self->draw_color = intToColor(args[ARG_drawcolor].u_int); + TFT_drawRect(self->x, self->y, self->w, self->h, self->draw_color); + } + rect_list.list[rect_list.head++] = self; + rect_list.head = rect_list.head > 19 ? 19 : rect_list.head; + return MP_OBJ_FROM_PTR(self); +} + +//=============================================================== +STATIC const mp_rom_map_elem_t m5ui_rect_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_setSize), (mp_obj_t)&m5ui_rect_resize_obj}, + { MP_ROM_QSTR(MP_QSTR_setBgColor), (mp_obj_t)&m5ui_rect_setbgcolor_obj}, + { MP_ROM_QSTR(MP_QSTR_setBorderColor), (mp_obj_t)&m5ui_rect_setbordercolor_obj}, + { MP_ROM_QSTR(MP_QSTR_setPosition), (mp_obj_t)&m5ui_rect_setposition_obj}, + { MP_ROM_QSTR(MP_QSTR_hide), (mp_obj_t)&m5ui_rect_hide_obj}, + { MP_ROM_QSTR(MP_QSTR_show), (mp_obj_t)&m5ui_rect_show_obj}, + +}; + +STATIC MP_DEFINE_CONST_DICT(m5ui_rect_locals_dict, m5ui_rect_locals_dict_table); + +//==================================== +const mp_obj_type_t m5ui_rect_type = { + { &mp_type_type }, + .name = MP_QSTR_M5Rect, + .make_new = m5ui_rect_make_new, + .print = m5ui_rect_print, + .locals_dict = (mp_obj_dict_t*)&m5ui_rect_locals_dict, +}; \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_textbox.c b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_textbox.c new file mode 100644 index 00000000..b79616be --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_textbox.c @@ -0,0 +1,361 @@ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" +#include "esp_task_wdt.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "libs/qrcode.h" + +#include "m5ui.h" +#endif + +typedef struct _m5ui_text_obj_t { + mp_obj_base_t base; + char *text; + uint8_t text_max_len; + uint8_t font; + uint16_t x; + uint16_t y; + uint16_t rotate; + color_t color; +} m5ui_text_obj_t; + +typedef struct _text_list_t { + uint8_t head; + m5ui_text_obj_t *list[20]; +} text_list_t; + +text_list_t text_list = { + .head = 0, +}; + +STATIC color_t intToColor(uint32_t cint) +{ + color_t cl = {0,0,0}; + cl.r = (cint >> 16) & 0xFF; + cl.g = (cint >> 8) & 0xFF; + cl.b = cint & 0xFF; + return cl; +} + +STATIC void m5ui_text_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_printf(print, "hello m5 text..."); +} + +mp_obj_t m5ui_text_deinit() { + for(uint8_t i = 0; i < text_list.head; i++) { + // m_del_obj(m5ui_text_obj_t, text_list.list[i]); + text_list.list[i] = NULL; + } + text_list.head = 0; + return mp_const_none; +} + +// STATIC MP_DEFINE_CONST_FUN_OBJ_0(m5ui_text_deinit_obj, m5ui_text_deinit); + +STATIC mp_obj_t m5ui_text_show(mp_obj_t self_in) { + m5ui_text_obj_t *self = self_in; + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + + _fg = self->color; + font_rotate = self->rotate; + font_transparent = 1; + + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + TFT_print(self->text, self->x, self->y); + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_text_show_obj, m5ui_text_show); + +STATIC mp_obj_t m5ui_text_hide(mp_obj_t self_in) { + m5ui_text_obj_t *self = self_in; + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + + _fg = ui_bg_color; + font_rotate = self->rotate; + font_transparent = 1; + + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + TFT_print(self->text, self->x, self->y); + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_text_hide_obj, m5ui_text_hide); + +STATIC mp_obj_t m5ui_text_font(mp_obj_t self_in, mp_obj_t font_in) { + m5ui_text_obj_t *self = self_in; + uint8_t font = mp_obj_get_int(font_in); + if(font == self->font) { return mp_const_none; } + + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + + _fg = ui_bg_color; + font_rotate = self->rotate; + font_transparent = 1; + + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + TFT_print(self->text, self->x, self->y); + _fg = self->color; + TFT_setFont(font, (char *)NULL); + TFT_print(self->text, self->x, self->y); + + self->font = font; + font_now = font; + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_text_font_obj, m5ui_text_font); + +STATIC mp_obj_t m5ui_text_rotate(mp_obj_t self_in, mp_obj_t rotate_in) { + m5ui_text_obj_t *self = self_in; + uint16_t rotate = mp_obj_get_int(rotate_in); + if(rotate == self->rotate) { return mp_const_none; } + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + _fg = ui_bg_color; + font_rotate = self->rotate; + font_transparent = 1; + + TFT_print(self->text, self->x, self->y); + _fg = self->color; + self->rotate = rotate; + font_rotate = rotate; + TFT_print(self->text, self->x, self->y); + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_text_rotate_obj, m5ui_text_rotate); + +STATIC mp_obj_t m5ui_text_setposition(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + m5ui_text_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_INT, { .u_int = self->x } }, + { MP_QSTR_y, MP_ARG_INT, { .u_int = self->y } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + uint16_t x = args[0].u_int; + uint16_t y = args[1].u_int; + if(x == self->x && y == self->y) { return mp_const_none; } + + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + font_rotate = self->rotate; + font_transparent = 1; + + _fg = ui_bg_color; + TFT_print(self->text, self->x, self->y); + _fg = self->color; + self->x = x; + self->y = y; + TFT_print(self->text, self->x, self->y); + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(m5ui_text_setposition_obj, 1, m5ui_text_setposition); + + +STATIC mp_obj_t m5ui_text_setcolor(mp_obj_t self_in, mp_obj_t color_in) { + m5ui_text_obj_t *self = self_in; + self->color = intToColor(mp_obj_get_int(color_in)); + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + _fg = self->color; + font_rotate = self->rotate; + font_transparent = 1; + + TFT_print(self->text, self->x, self->y); + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_text_setcolor_obj, m5ui_text_setcolor); + +STATIC mp_obj_t m5ui_text_settext(mp_obj_t self_in, mp_obj_t text_in) { + m5ui_text_obj_t *self = self_in; + const char *tstr = mp_obj_str_get_str(text_in); + + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + if(strcmp(self->text, tstr) == 0) { + return mp_const_none; + } + + _fg = ui_bg_color; + font_rotate = self->rotate; + font_transparent = 1; + + TFT_print(self->text, self->x, self->y); + + if(strlen(tstr) > self->text_max_len) { + self->text_max_len = strlen(tstr); + char *text_n = m_new(char, self->text_max_len); + strcpy(text_n, tstr); + m_free(self->text); + self->text = text_n; + } else { + strcpy(self->text, tstr); + } + + _fg = self->color; + TFT_print(self->text, self->x, self->y); + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_text_settext_obj, m5ui_text_settext); + + +mp_obj_t m5ui_text_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_x, ARG_y, ARG_text, ARG_font, ARG_color, ARG_rotate }; + //--------------------------------------------------------------------- + const mp_arg_t m5ui_text_init_allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_font, MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_color, MP_ARG_INT, {.u_int = -1}}, + { MP_QSTR_rotate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(m5ui_text_init_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(m5ui_text_init_allowed_args), m5ui_text_init_allowed_args, args); + + m5ui_text_obj_t *self = m_new_obj(m5ui_text_obj_t); + const char *tstr = NULL; + + self->base.type = &m5ui_text_type; + self->x = args[ARG_x].u_int; + self->y = args[ARG_y].u_int; + self->color = intToColor(args[ARG_color].u_int); + self->font = args[ARG_font].u_int; + self->rotate = args[ARG_rotate].u_int; + tstr = (char *)mp_obj_str_get_str(args[ARG_text].u_obj); + self->text_max_len = strlen(tstr); + char *text_n = m_new(char, self->text_max_len); + strcpy(text_n, tstr); + self->text = text_n; + + color_t old_fg = _fg; + int old_rot = font_rotate; + int old_transp = font_transparent; + if(font_now != self->font){ + TFT_setFont(self->font, (char *)NULL); + } + + _fg = self->color; + font_rotate = self->rotate; + font_transparent = 1; + TFT_print(self->text, self->x, self->y); + + _fg = old_fg; + font_rotate = old_rot; + font_transparent = old_transp; + text_list.list[text_list.head++] = self; + text_list.head = text_list.head > 19 ? 19 : text_list.head; + return MP_OBJ_FROM_PTR(self); +} + +//=============================================================== +STATIC const mp_rom_map_elem_t m5ui_text_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_setColor), (mp_obj_t)&m5ui_text_setcolor_obj}, + { MP_ROM_QSTR(MP_QSTR_setPosition), (mp_obj_t)&m5ui_text_setposition_obj}, + { MP_ROM_QSTR(MP_QSTR_setFont), (mp_obj_t)&m5ui_text_font_obj}, + { MP_ROM_QSTR(MP_QSTR_setRotate), (mp_obj_t)&m5ui_text_rotate_obj}, + { MP_ROM_QSTR(MP_QSTR_setText), (mp_obj_t)&m5ui_text_settext_obj}, + { MP_ROM_QSTR(MP_QSTR_hide), (mp_obj_t)&m5ui_text_hide_obj}, + { MP_ROM_QSTR(MP_QSTR_show), (mp_obj_t)&m5ui_text_show_obj}, + + // { MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&m5ui_text_deinit_obj}, +}; + +STATIC MP_DEFINE_CONST_DICT(m5ui_text_locals_dict, m5ui_text_locals_dict_table); + +//==================================== +const mp_obj_type_t m5ui_text_type = { + { &mp_type_type }, + .name = MP_QSTR_M5TextBox, + .make_new = m5ui_text_make_new, + .print = m5ui_text_print, + .locals_dict = (mp_obj_dict_t*)&m5ui_text_locals_dict, +}; \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_title.c b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_title.c new file mode 100644 index 00000000..7df05f08 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/m5ui/m5ui_title.c @@ -0,0 +1,195 @@ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" +#include "esp_task_wdt.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "libs/qrcode.h" +#include "m5ui.h" +#endif + +#define TITLE_NAME_LEN 20 +typedef struct _m5ui_title_obj_t { + mp_obj_base_t base; + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; + char msg[TITLE_NAME_LEN]; + color_t fill_color; + color_t draw_color; +} m5ui_title_obj_t; + +m5ui_title_obj_t title; + +STATIC color_t intToColor(uint32_t cint) { + color_t cl = {0,0,0}; + cl.r = (cint >> 16) & 0xFF; + cl.g = (cint >> 8) & 0xFF; + cl.b = cint & 0xFF; + return cl; +} + +STATIC void m5ui_title_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mp_printf(print, "hello m5 title..."); +} + +STATIC mp_obj_t m5ui_title_show(mp_obj_t self_in) { + m5ui_title_obj_t *self = self_in; + TFT_fillRect(0, 0,self->w, self->h, self->fill_color); + int old_font_transparent = font_transparent; + color_t old_fg = _fg; + font_transparent = 1; + _fg = self->draw_color; + TFT_setFont(0, (char *)NULL); + TFT_print(self->msg, self->x, self->y); + font_transparent = old_font_transparent; + _fg = old_fg; + return mp_const_none; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_title_show_obj, m5ui_title_show); + +STATIC mp_obj_t m5ui_title_hide(mp_obj_t self_in) { + m5ui_title_obj_t *self = self_in; + TFT_fillRect(0, 0,self->w, self->h, ui_bg_color); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(m5ui_title_hide_obj, m5ui_title_hide); + + +STATIC mp_obj_t m5ui_title_setbgcolor(mp_obj_t self_in, mp_obj_t color_in) { + m5ui_title_obj_t *self = self_in; + self->fill_color = intToColor(mp_obj_get_int(color_in)); + TFT_fillRect(0, 0,self->w, self->h, self->fill_color); + int old_font_transparent = font_transparent; + color_t old_fg = _fg; + font_transparent = 1; + _fg = self->draw_color; + TFT_setFont(0, (char *)NULL); + TFT_print(self->msg, self->x, self->y); + font_transparent = old_font_transparent; + _fg = old_fg; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_title_setbgcolor_obj, m5ui_title_setbgcolor); + +STATIC mp_obj_t m5ui_title_setfgcolor(mp_obj_t self_in, mp_obj_t color_in) { + m5ui_title_obj_t *self = self_in; + self->draw_color = intToColor(mp_obj_get_int(color_in)); + int old_font_transparent = font_transparent; + color_t old_fg = _fg; + font_transparent = 1; + _fg = self->draw_color; + TFT_setFont(0, (char *)NULL); + TFT_print(self->msg, self->x, self->y); + font_transparent = old_font_transparent; + _fg = old_fg; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_title_setfgcolor_obj, m5ui_title_setfgcolor); + +mp_obj_t m5ui_title_settitle(mp_obj_t self_in, mp_obj_t text_in) { + m5ui_title_obj_t *self = self_in; + char *st = (char *)mp_obj_str_get_str(text_in); + if(strlen(st) > TITLE_NAME_LEN){ + mp_raise_ValueError("Title too long"); + } + int old_font_transparent = font_transparent; + color_t old_fg = _fg; + font_transparent = 1; + _fg = self->fill_color; + TFT_setFont(0, (char *)NULL); + TFT_print(self->msg, self->x, self->y); + _fg = self->draw_color; + TFT_print(st, self->x, self->y); + sprintf(self->msg, "%s", st); + font_transparent = old_font_transparent; + _fg = old_fg; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(m5ui_title_settitle_obj, m5ui_title_settitle); + + +mp_obj_t m5ui_title_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args){ + //--------------------------------------------------------------------- + const mp_arg_t m5ui_title_init_allowed_args[] = { + { MP_QSTR_fgcolor, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1}}, + { MP_QSTR_bgcolor, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1}}, + { MP_QSTR_title, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_h, MP_ARG_INT, {.u_int = 20}}, + { MP_QSTR_x, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 3} }, + { MP_QSTR_y, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_w, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 320} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(m5ui_title_init_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(m5ui_title_init_allowed_args), m5ui_title_init_allowed_args, args); + + const char *tstr = NULL; + m5ui_title_obj_t *self = &title; + memset(self, 0, sizeof(m5ui_title_obj_t)); + + self->base.type = &m5ui_title_type; + self->draw_color = intToColor(args[0].u_int); + self->fill_color = intToColor(args[1].u_int); + tstr = mp_obj_str_get_str(args[2].u_obj); + self->h = args[3].u_int; + self->x = args[4].u_int; + self->y = args[5].u_int; + self->w = args[6].u_int; + + if(strlen(tstr) >= TITLE_NAME_LEN){ + mp_raise_ValueError("Title too long"); + } + sprintf(self->msg, "%s", tstr); + TFT_fillRect(0, 0, self->w, self->h, self->fill_color); + int old_font_transparent = font_transparent; + color_t old_fg = _fg; + font_transparent = 1; + + _fg = self->draw_color; + TFT_setFont(0, (char *)NULL); + TFT_print(self->msg, self->x, self->y); + + _fg = old_fg; + font_transparent = old_font_transparent; + return MP_OBJ_FROM_PTR(self); +} + +//=============================================================== +STATIC const mp_rom_map_elem_t m5ui_title_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_hide), (mp_obj_t)&m5ui_title_hide_obj}, + { MP_ROM_QSTR(MP_QSTR_show), (mp_obj_t)&m5ui_title_show_obj}, + { MP_ROM_QSTR(MP_QSTR_setTitle), (mp_obj_t)&m5ui_title_settitle_obj}, + { MP_ROM_QSTR(MP_QSTR_setFgColor), (mp_obj_t)&m5ui_title_setfgcolor_obj}, + { MP_ROM_QSTR(MP_QSTR_setBgColor), (mp_obj_t)&m5ui_title_setbgcolor_obj}, +}; + +STATIC MP_DEFINE_CONST_DICT(m5ui_title_locals_dict, m5ui_title_locals_dict_table); + +//==================================== +const mp_obj_type_t m5ui_title_type = { + { &mp_type_type }, + .name = MP_QSTR_M5Title, + .make_new = m5ui_title_make_new, + .print = m5ui_title_print, + .locals_dict = (mp_obj_dict_t*)&m5ui_title_locals_dict, +}; \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.c b/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.c index 75a4c8fc..90e9441b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.c @@ -116,8 +116,8 @@ uint32_t np_get_pixel_color(pixel_settings_t *px, uint16_t idx, uint8_t *white) } // Set two levels of RMT output to the Neopixel value for bit value "1". -//------------------------------------------------------------------------------ -static void IRAM_ATTR neopixel_mark(rmt_item32_t *pItem, pixel_settings_t *px) { +//-------------------------------------------------------------------- +static void neopixel_mark(rmt_item32_t *pItem, pixel_settings_t *px) { pItem->level0 = px->timings.mark.level0; pItem->duration0 = px->timings.mark.duration0; pItem->level1 = px->timings.mark.level1; @@ -125,8 +125,8 @@ static void IRAM_ATTR neopixel_mark(rmt_item32_t *pItem, pixel_settings_t *px) { } // Set two levels of RMT output to the Neopixel value for bit value "0". -//------------------------------------------------------------------------------- -static void IRAM_ATTR neopixel_space(rmt_item32_t *pItem, pixel_settings_t *px) { +//--------------------------------------------------------------------- +static void neopixel_space(rmt_item32_t *pItem, pixel_settings_t *px) { pItem->level0 = px->timings.space.level0; pItem->duration0 = px->timings.space.duration0; pItem->level1 = px->timings.space.level1; @@ -134,8 +134,8 @@ static void IRAM_ATTR neopixel_space(rmt_item32_t *pItem, pixel_settings_t *px) } // Set levels and duration of RMT output to the Neopixel value for Reset. -//------------------------------------------------------------------------------ -static void IRAM_ATTR rmt_terminate(rmt_item32_t *pItem, pixel_settings_t *px) { +//-------------------------------------------------------------------- +static void rmt_terminate(rmt_item32_t *pItem, pixel_settings_t *px) { pItem->level0 = px->timings.reset.level0; pItem->duration0 = px->timings.reset.duration0; pItem->level1 = px->timings.reset.level1; @@ -143,8 +143,8 @@ static void IRAM_ATTR rmt_terminate(rmt_item32_t *pItem, pixel_settings_t *px) { } // Transfer pixels from buffer to Neopixel strip -//----------------------------------------- -static void IRAM_ATTR copyToRmtBlock_half() +//------------------------------- +static void copyToRmtBlock_half() { // This fills half an RMT block // When wrap around is happening, we want to keep the inactive half of the RMT block filled @@ -207,8 +207,8 @@ static void IRAM_ATTR copyToRmtBlock_half() } // RMT interrupt handler -//------------------------------------------------------- -static void IRAM_ATTR neopixel_handleInterrupt(void *arg) +//--------------------------------------------- +static void neopixel_handleInterrupt(void *arg) { portBASE_TYPE taskAwoken = 0; @@ -237,10 +237,13 @@ int neopixel_init(int gpioNum, rmt_channel_t channel) if (neopixel_sem == NULL) { neopixel_sem = xSemaphoreCreateBinary(); if (neopixel_sem == NULL) return ESP_FAIL; + // Note: binary semaphores created using xSemaphoreCreateBinary() are created in a state + // such that the semaphore must first be 'given' before it can be 'taken' ! + xSemaphoreGive(neopixel_sem); + + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST); } - // Note: binary semaphores created using xSemaphoreCreateBinary() are created in a state - // such that the semaphore must first be 'given' before it can be 'taken' ! - xSemaphoreGive(neopixel_sem); // Allocate RMT interrupt if needed if (rmt_intr_handle == NULL) { @@ -253,9 +256,6 @@ int neopixel_init(int gpioNum, rmt_channel_t channel) uint32_t tx_thr_event_mask = 0x01000000 << channel; uint32_t tx_end_event_mask = 1 << (channel*3); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_RMT_CLK_EN); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_RMT_RST); - res = rmt_set_pin(channel, RMT_MODE_TX, (gpio_num_t)gpioNum); if (res != ESP_OK) { xSemaphoreGive(neopixel_sem); @@ -278,7 +278,7 @@ int neopixel_init(int gpioNum, rmt_channel_t channel) RMT.conf_ch[channel].conf1.idle_out_lv = 0; RMT.tx_lim_ch[channel].limit = MAX_PULSES; - RMT.int_ena.val = tx_thr_event_mask | tx_end_event_mask; + // RMT.int_ena.val = tx_thr_event_mask | tx_end_event_mask; used_channels[channel] = 1; xSemaphoreGive(neopixel_sem); @@ -321,20 +321,27 @@ void neopixel_deinit(rmt_channel_t channel) } // Start the transfer of Neopixel color bytes from buffer -//===================================================================== -void np_show(pixel_settings_t *px, rmt_channel_t channel, uint8_t wait) +//======================================================= +void np_show(pixel_settings_t *px, rmt_channel_t channel) { // Wait for previous operation to finish xSemaphoreTake(neopixel_sem, portMAX_DELAY); RMTchannel = channel; + // Enable interrupt for neopixel RMT channel + uint32_t tx_thr_event_mask = 0x01000000 << channel; + uint32_t tx_end_event_mask = 1 << (channel*3); + RMT.int_ena.val = tx_thr_event_mask | tx_end_event_mask; + uint16_t blen = px->pixel_count * (px->nbits / 8); + // Allocate neopixel buffer if needed if (neopixel_buffer == NULL) { neopixel_buffer = (uint8_t *)malloc(blen); if (neopixel_buffer == NULL) return; neopixel_buf_len = blen; } + // Resize neopixel buffer if needed if (neopixel_buf_len < blen) { // larger buffer needed free(neopixel_buffer); @@ -362,11 +369,11 @@ void np_show(pixel_settings_t *px, rmt_channel_t channel, uint8_t wait) RMT.conf_ch[RMTchannel].conf1.mem_rd_rst = 1; RMT.conf_ch[RMTchannel].conf1.tx_start = 1; - if (wait) { - // Wait for operation to finish + // Wait for operation to finish + if (xSemaphoreTake(neopixel_sem, 0) == pdTRUE) { xSemaphoreTake(neopixel_sem, portMAX_DELAY); - xSemaphoreGive(neopixel_sem); } + xSemaphoreGive(neopixel_sem); } // Clear the Neopixel color buffer diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h b/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h index 646c9838..c45f33b5 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h @@ -60,7 +60,7 @@ typedef struct pixel_settings { void np_set_pixel_color(pixel_settings_t *px, uint16_t idx, uint32_t color); void np_set_pixel_color_hsb(pixel_settings_t *px, uint16_t idx, float hue, float saturation, float brightness); uint32_t np_get_pixel_color(pixel_settings_t *px, uint16_t idx, uint8_t *white); -void np_show(pixel_settings_t *px, rmt_channel_t channel, uint8_t wait); +void np_show(pixel_settings_t *px, rmt_channel_t channel); void np_clear(pixel_settings_t *px); int neopixel_init(int gpioNum, rmt_channel_t channel); diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/qrcode.c b/MicroPython_BUILD/components/micropython/esp32/libs/qrcode.c new file mode 100755 index 00000000..92e606eb --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/qrcode.c @@ -0,0 +1,872 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Richard Moore + * + * 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. + */ + +/** + * Special thanks to Nayuki (https://www.nayuki.io/) from which this library was + * heavily inspired and compared against. + * + * See: https://github.com/nayuki/QR-Code-generator/tree/master/cpp + */ + +#include "qrcode.h" + +#include +#include + +//#pragma mark - Error Correction Lookup tables + +#if LOCK_VERSION == 0 + +static const uint16_t NUM_ERROR_CORRECTION_CODEWORDS[4][40] = { + // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + { 10, 16, 26, 36, 48, 64, 72, 88, 110, 130, 150, 176, 198, 216, 240, 280, 308, 338, 364, 416, 442, 476, 504, 560, 588, 644, 700, 728, 784, 812, 868, 924, 980, 1036, 1064, 1120, 1204, 1260, 1316, 1372}, // Medium + { 7, 10, 15, 20, 26, 36, 40, 48, 60, 72, 80, 96, 104, 120, 132, 144, 168, 180, 196, 224, 224, 252, 270, 300, 312, 336, 360, 390, 420, 450, 480, 510, 540, 570, 570, 600, 630, 660, 720, 750}, // Low + { 17, 28, 44, 64, 88, 112, 130, 156, 192, 224, 264, 308, 352, 384, 432, 480, 532, 588, 650, 700, 750, 816, 900, 960, 1050, 1110, 1200, 1260, 1350, 1440, 1530, 1620, 1710, 1800, 1890, 1980, 2100, 2220, 2310, 2430}, // High + { 13, 22, 36, 52, 72, 96, 108, 132, 160, 192, 224, 260, 288, 320, 360, 408, 448, 504, 546, 600, 644, 690, 750, 810, 870, 952, 1020, 1050, 1140, 1200, 1290, 1350, 1440, 1530, 1590, 1680, 1770, 1860, 1950, 2040}, // Quartile +}; + +static const uint8_t NUM_ERROR_CORRECTION_BLOCKS[4][40] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + // 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + { 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + { 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + { 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High + { 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile +}; + +static const uint16_t NUM_RAW_DATA_MODULES[40] = { + // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 208, 359, 567, 807, 1079, 1383, 1568, 1936, 2336, 2768, 3232, 3728, 4256, 4651, 5243, 5867, 6523, + // 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 7211, 7931, 8683, 9252, 10068, 10916, 11796, 12708, 13652, 14628, 15371, 16411, 17483, 18587, + // 32, 33, 34, 35, 36, 37, 38, 39, 40 + 19723, 20891, 22091, 23008, 24272, 25568, 26896, 28256, 29648 +}; + +// @TODO: Put other LOCK_VERSIONS here +#elif LOCK_VERSION == 3 + +static const int16_t NUM_ERROR_CORRECTION_CODEWORDS[4] = { + 26, 15, 44, 36 +}; + +static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4] = { + 1, 1, 2, 2 +}; + +static const uint16_t NUM_RAW_DATA_MODULES = 567; + +#else + +#error Unsupported LOCK_VERSION (add it...) + +#endif + + +static int max(int a, int b) { + if (a > b) { return a; } + return b; +} + +/* +static int abs(int value) { + if (value < 0) { return -value; } + return value; +} +*/ + + +//#pragma mark - Mode testing and conversion + +static int8_t getAlphanumeric(char c) { + + if (c >= '0' && c <= '9') { return (c - '0'); } + if (c >= 'A' && c <= 'Z') { return (c - 'A' + 10); } + + switch (c) { + case ' ': return 36; + case '$': return 37; + case '%': return 38; + case '*': return 39; + case '+': return 40; + case '-': return 41; + case '.': return 42; + case '/': return 43; + case ':': return 44; + } + + return -1; +} + +static bool isAlphanumeric(const char *text, uint16_t length) { + while (length != 0) { + if (getAlphanumeric(text[--length]) == -1) { return false; } + } + return true; +} + + +static bool isNumeric(const char *text, uint16_t length) { + while (length != 0) { + char c = text[--length]; + if (c < '0' || c > '9') { return false; } + } + return true; +} + + +//#pragma mark - Counting + +// We store the following tightly packed (less 8) in modeInfo +// <=9 <=26 <= 40 +// NUMERIC ( 10, 12, 14); +// ALPHANUMERIC ( 9, 11, 13); +// BYTE ( 8, 16, 16); +static char getModeBits(uint8_t version, uint8_t mode) { + // Note: We use 15 instead of 16; since 15 doesn't exist and we cannot store 16 (8 + 8) in 3 bits + // hex(int("".join(reversed([('00' + bin(x - 8)[2:])[-3:] for x in [10, 9, 8, 12, 11, 15, 14, 13, 15]])), 2)) + unsigned int modeInfo = 0x7bbb80a; + +#if LOCK_VERSION == 0 || LOCK_VERSION > 9 + if (version > 9) { modeInfo >>= 9; } +#endif + +#if LOCK_VERSION == 0 || LOCK_VERSION > 26 + if (version > 26) { modeInfo >>= 9; } +#endif + + char result = 8 + ((modeInfo >> (3 * mode)) & 0x07); + if (result == 15) { result = 16; } + + return result; +} + + +//#pragma mark - BitBucket + +typedef struct BitBucket { + uint32_t bitOffsetOrWidth; + uint16_t capacityBytes; + uint8_t *data; +} BitBucket; + +/* +void bb_dump(BitBucket *bitBuffer) { + printf("Buffer: "); + for (uint32_t i = 0; i < bitBuffer->capacityBytes; i++) { + printf("%02x", bitBuffer->data[i]); + if ((i % 4) == 3) { printf(" "); } + } + printf("\n"); +} +*/ + +static uint16_t bb_getGridSizeBytes(uint8_t size) { + return (((size * size) + 7) / 8); +} + +static uint16_t bb_getBufferSizeBytes(uint32_t bits) { + return ((bits + 7) / 8); +} + +static void bb_initBuffer(BitBucket *bitBuffer, uint8_t *data, int32_t capacityBytes) { + bitBuffer->bitOffsetOrWidth = 0; + bitBuffer->capacityBytes = capacityBytes; + bitBuffer->data = data; + + memset(data, 0, bitBuffer->capacityBytes); +} + +static void bb_initGrid(BitBucket *bitGrid, uint8_t *data, uint8_t size) { + bitGrid->bitOffsetOrWidth = size; + bitGrid->capacityBytes = bb_getGridSizeBytes(size); + bitGrid->data = data; + + memset(data, 0, bitGrid->capacityBytes); +} + +static void bb_appendBits(BitBucket *bitBuffer, uint32_t val, uint8_t length) { + uint32_t offset = bitBuffer->bitOffsetOrWidth; + for (int8_t i = length - 1; i >= 0; i--, offset++) { + bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7)); + } + bitBuffer->bitOffsetOrWidth = offset; +} +/* +void bb_setBits(BitBucket *bitBuffer, uint32_t val, int offset, uint8_t length) { + for (int8_t i = length - 1; i >= 0; i--, offset++) { + bitBuffer->data[offset >> 3] |= ((val >> i) & 1) << (7 - (offset & 7)); + } +} +*/ +static void bb_setBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool on) { + uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; + uint8_t mask = 1 << (7 - (offset & 0x07)); + if (on) { + bitGrid->data[offset >> 3] |= mask; + } else { + bitGrid->data[offset >> 3] &= ~mask; + } +} + +static void bb_invertBit(BitBucket *bitGrid, uint8_t x, uint8_t y, bool invert) { + uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; + uint8_t mask = 1 << (7 - (offset & 0x07)); + bool on = ((bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0); + if (on ^ invert) { + bitGrid->data[offset >> 3] |= mask; + } else { + bitGrid->data[offset >> 3] &= ~mask; + } +} + +static bool bb_getBit(BitBucket *bitGrid, uint8_t x, uint8_t y) { + uint32_t offset = y * bitGrid->bitOffsetOrWidth + x; + return (bitGrid->data[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; +} + + +//#pragma mark - Drawing Patterns + +// XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical +// properties, calling applyMask(m) twice with the same value is equivalent to no change at all. +// This means it is possible to apply a mask, undo it, and try another mask. Note that a final +// well-formed QR Code symbol needs exactly one mask applied (not zero, not two, etc.). +static void applyMask(BitBucket *modules, BitBucket *isFunction, uint8_t mask) { + uint8_t size = modules->bitOffsetOrWidth; + + for (uint8_t y = 0; y < size; y++) { + for (uint8_t x = 0; x < size; x++) { + if (bb_getBit(isFunction, x, y)) { continue; } + + bool invert = 0; + switch (mask) { + case 0: invert = (x + y) % 2 == 0; break; + case 1: invert = y % 2 == 0; break; + case 2: invert = x % 3 == 0; break; + case 3: invert = (x + y) % 3 == 0; break; + case 4: invert = (x / 3 + y / 2) % 2 == 0; break; + case 5: invert = x * y % 2 + x * y % 3 == 0; break; + case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; + case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; + } + bb_invertBit(modules, x, y, invert); + } + } +} + +static void setFunctionModule(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y, bool on) { + bb_setBit(modules, x, y, on); + bb_setBit(isFunction, x, y, true); +} + +// Draws a 9*9 finder pattern including the border separator, with the center module at (x, y). +static void drawFinderPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) { + uint8_t size = modules->bitOffsetOrWidth; + + for (int8_t i = -4; i <= 4; i++) { + for (int8_t j = -4; j <= 4; j++) { + uint8_t dist = max(abs(i), abs(j)); // Chebyshev/infinity norm + int16_t xx = x + j, yy = y + i; + if (0 <= xx && xx < size && 0 <= yy && yy < size) { + setFunctionModule(modules, isFunction, xx, yy, dist != 2 && dist != 4); + } + } + } +} + +// Draws a 5*5 alignment pattern, with the center module at (x, y). +static void drawAlignmentPattern(BitBucket *modules, BitBucket *isFunction, uint8_t x, uint8_t y) { + for (int8_t i = -2; i <= 2; i++) { + for (int8_t j = -2; j <= 2; j++) { + setFunctionModule(modules, isFunction, x + j, y + i, max(abs(i), abs(j)) != 1); + } + } +} + +// Draws two copies of the format bits (with its own error correction code) +// based on the given mask and this object's error correction level field. +static void drawFormatBits(BitBucket *modules, BitBucket *isFunction, uint8_t ecc, uint8_t mask) { + + uint8_t size = modules->bitOffsetOrWidth; + + // Calculate error correction code and pack bits + uint32_t data = ecc << 3 | mask; // errCorrLvl is uint2, mask is uint3 + uint32_t rem = data; + for (int i = 0; i < 10; i++) { + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + } + + data = data << 10 | rem; + data ^= 0x5412; // uint15 + + // Draw first copy + for (uint8_t i = 0; i <= 5; i++) { + setFunctionModule(modules, isFunction, 8, i, ((data >> i) & 1) != 0); + } + + setFunctionModule(modules, isFunction, 8, 7, ((data >> 6) & 1) != 0); + setFunctionModule(modules, isFunction, 8, 8, ((data >> 7) & 1) != 0); + setFunctionModule(modules, isFunction, 7, 8, ((data >> 8) & 1) != 0); + + for (int8_t i = 9; i < 15; i++) { + setFunctionModule(modules, isFunction, 14 - i, 8, ((data >> i) & 1) != 0); + } + + // Draw second copy + for (int8_t i = 0; i <= 7; i++) { + setFunctionModule(modules, isFunction, size - 1 - i, 8, ((data >> i) & 1) != 0); + } + + for (int8_t i = 8; i < 15; i++) { + setFunctionModule(modules, isFunction, 8, size - 15 + i, ((data >> i) & 1) != 0); + } + + setFunctionModule(modules, isFunction, 8, size - 8, true); +} + + +// Draws two copies of the version bits (with its own error correction code), +// based on this object's version field (which only has an effect for 7 <= version <= 40). +static void drawVersion(BitBucket *modules, BitBucket *isFunction, uint8_t version) { + + int8_t size = modules->bitOffsetOrWidth; + +#if LOCK_VERSION != 0 && LOCK_VERSION < 7 + return; + +#else + if (version < 7) { return; } + + // Calculate error correction code and pack bits + uint32_t rem = version; // version is uint6, in the range [7, 40] + for (uint8_t i = 0; i < 12; i++) { + rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + } + + uint32_t data = version << 12 | rem; // uint18 + + // Draw two copies + for (uint8_t i = 0; i < 18; i++) { + bool bit = ((data >> i) & 1) != 0; + uint8_t a = size - 11 + i % 3, b = i / 3; + setFunctionModule(modules, isFunction, a, b, bit); + setFunctionModule(modules, isFunction, b, a, bit); + } + +#endif +} + +static void drawFunctionPatterns(BitBucket *modules, BitBucket *isFunction, uint8_t version, uint8_t ecc) { + + uint8_t size = modules->bitOffsetOrWidth; + + // Draw the horizontal and vertical timing patterns + for (uint8_t i = 0; i < size; i++) { + setFunctionModule(modules, isFunction, 6, i, i % 2 == 0); + setFunctionModule(modules, isFunction, i, 6, i % 2 == 0); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + drawFinderPattern(modules, isFunction, 3, 3); + drawFinderPattern(modules, isFunction, size - 4, 3); + drawFinderPattern(modules, isFunction, 3, size - 4); + +#if LOCK_VERSION == 0 || LOCK_VERSION > 1 + + if (version > 1) { + + // Draw the numerous alignment patterns + + uint8_t alignCount = version / 7 + 2; + uint8_t step; + if (version != 32) { + step = (version * 4 + alignCount * 2 + 1) / (2 * alignCount - 2) * 2; // ceil((size - 13) / (2*numAlign - 2)) * 2 + } else { // C-C-C-Combo breaker! + step = 26; + } + + uint8_t alignPositionIndex = alignCount - 1; + uint8_t alignPosition[alignCount]; + + alignPosition[0] = 6; + + uint8_t size = version * 4 + 17; + for (uint8_t i = 0, pos = size - 7; i < alignCount - 1; i++, pos -= step) { + alignPosition[alignPositionIndex--] = pos; + } + + for (uint8_t i = 0; i < alignCount; i++) { + for (uint8_t j = 0; j < alignCount; j++) { + if ((i == 0 && j == 0) || (i == 0 && j == alignCount - 1) || (i == alignCount - 1 && j == 0)) { + continue; // Skip the three finder corners + } else { + drawAlignmentPattern(modules, isFunction, alignPosition[i], alignPosition[j]); + } + } + } + } + +#endif + + // Draw configuration data + drawFormatBits(modules, isFunction, ecc, 0); // Dummy mask value; overwritten later in the constructor + drawVersion(modules, isFunction, version); +} + + +// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire +// data area of this QR Code symbol. Function modules need to be marked off before this is called. +static void drawCodewords(BitBucket *modules, BitBucket *isFunction, BitBucket *codewords) { + + uint32_t bitLength = codewords->bitOffsetOrWidth; + uint8_t *data = codewords->data; + + uint8_t size = modules->bitOffsetOrWidth; + + // Bit index into the data + uint32_t i = 0; + + // Do the funny zigzag scan + for (int16_t right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair + if (right == 6) { right = 5; } + + for (uint8_t vert = 0; vert < size; vert++) { // Vertical counter + for (int j = 0; j < 2; j++) { + uint8_t x = right - j; // Actual x coordinate + bool upwards = ((right & 2) == 0) ^ (x < 6); + uint8_t y = upwards ? size - 1 - vert : vert; // Actual y coordinate + if (!bb_getBit(isFunction, x, y) && i < bitLength) { + bb_setBit(modules, x, y, ((data[i >> 3] >> (7 - (i & 7))) & 1) != 0); + i++; + } + // If there are any remainder bits (0 to 7), they are already + // set to 0/false/white when the grid of modules was initialized + } + } + } +} + + + +//#pragma mark - Penalty Calculation + +#define PENALTY_N1 3 +#define PENALTY_N2 3 +#define PENALTY_N3 40 +#define PENALTY_N4 10 + +// Calculates and returns the penalty score based on state of this QR Code's current modules. +// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. +// @TODO: This can be optimized by working with the bytes instead of bits. +static uint32_t getPenaltyScore(BitBucket *modules) { + uint32_t result = 0; + + uint8_t size = modules->bitOffsetOrWidth; + + // Adjacent modules in row having same color + for (uint8_t y = 0; y < size; y++) { + + bool colorX = bb_getBit(modules, 0, y); + for (uint8_t x = 1, runX = 1; x < size; x++) { + bool cx = bb_getBit(modules, x, y); + if (cx != colorX) { + colorX = cx; + runX = 1; + + } else { + runX++; + if (runX == 5) { + result += PENALTY_N1; + } else if (runX > 5) { + result++; + } + } + } + } + + // Adjacent modules in column having same color + for (uint8_t x = 0; x < size; x++) { + bool colorY = bb_getBit(modules, x, 0); + for (uint8_t y = 1, runY = 1; y < size; y++) { + bool cy = bb_getBit(modules, x, y); + if (cy != colorY) { + colorY = cy; + runY = 1; + } else { + runY++; + if (runY == 5) { + result += PENALTY_N1; + } else if (runY > 5) { + result++; + } + } + } + } + + uint16_t black = 0; + for (uint8_t y = 0; y < size; y++) { + uint16_t bitsRow = 0, bitsCol = 0; + for (uint8_t x = 0; x < size; x++) { + bool color = bb_getBit(modules, x, y); + + // 2*2 blocks of modules having same color + if (x > 0 && y > 0) { + bool colorUL = bb_getBit(modules, x - 1, y - 1); + bool colorUR = bb_getBit(modules, x, y - 1); + bool colorL = bb_getBit(modules, x - 1, y); + if (color == colorUL && color == colorUR && color == colorL) { + result += PENALTY_N2; + } + } + + // Finder-like pattern in rows and columns + bitsRow = ((bitsRow << 1) & 0x7FF) | color; + bitsCol = ((bitsCol << 1) & 0x7FF) | bb_getBit(modules, y, x); + + // Needs 11 bits accumulated + if (x >= 10) { + if (bitsRow == 0x05D || bitsRow == 0x5D0) { + result += PENALTY_N3; + } + if (bitsCol == 0x05D || bitsCol == 0x5D0) { + result += PENALTY_N3; + } + } + + // Balance of black and white modules + if (color) { black++; } + } + } + + // Find smallest k such that (45-5k)% <= dark/total <= (55+5k)% + uint16_t total = size * size; + for (uint16_t k = 0; black * 20 < (9 - k) * total || black * 20 > (11 + k) * total; k++) { + result += PENALTY_N4; + } + + return result; +} + + +//#pragma mark - Reed-Solomon Generator + +static uint8_t rs_multiply(uint8_t x, uint8_t y) { + // Russian peasant multiplication + // See: https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication + uint16_t z = 0; + for (int8_t i = 7; i >= 0; i--) { + z = (z << 1) ^ ((z >> 7) * 0x11D); + z ^= ((y >> i) & 1) * x; + } + return z; +} + +static void rs_init(uint8_t degree, uint8_t *coeff) { + memset(coeff, 0, degree); + coeff[degree - 1] = 1; + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // drop the highest term, and store the rest of the coefficients in order of descending powers. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint16_t root = 1; + for (uint8_t i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for (uint8_t j = 0; j < degree; j++) { + coeff[j] = rs_multiply(coeff[j], root); + if (j + 1 < degree) { + coeff[j] ^= coeff[j + 1]; + } + } + root = (root << 1) ^ ((root >> 7) * 0x11D); // Multiply by 0x02 mod GF(2^8/0x11D) + } +} + +static void rs_getRemainder(uint8_t degree, uint8_t *coeff, uint8_t *data, uint8_t length, uint8_t *result, uint8_t stride) { + // Compute the remainder by performing polynomial division + + //for (uint8_t i = 0; i < degree; i++) { result[] = 0; } + //memset(result, 0, degree); + + for (uint8_t i = 0; i < length; i++) { + uint8_t factor = data[i] ^ result[0]; + for (uint8_t j = 1; j < degree; j++) { + result[(j - 1) * stride] = result[j * stride]; + } + result[(degree - 1) * stride] = 0; + + for (uint8_t j = 0; j < degree; j++) { + result[j * stride] ^= rs_multiply(coeff[j], factor); + } + } +} + + + +//#pragma mark - QrCode + +static int8_t encodeDataCodewords(BitBucket *dataCodewords, const uint8_t *text, uint16_t length, uint8_t version) { + int8_t mode = MODE_BYTE; + + if (isNumeric((char*)text, length)) { + mode = MODE_NUMERIC; + bb_appendBits(dataCodewords, 1 << MODE_NUMERIC, 4); + bb_appendBits(dataCodewords, length, getModeBits(version, MODE_NUMERIC)); + + uint16_t accumData = 0; + uint8_t accumCount = 0; + for (uint16_t i = 0; i < length; i++) { + accumData = accumData * 10 + ((char)(text[i]) - '0'); + accumCount++; + if (accumCount == 3) { + bb_appendBits(dataCodewords, accumData, 10); + accumData = 0; + accumCount = 0; + } + } + + // 1 or 2 digits remaining + if (accumCount > 0) { + bb_appendBits(dataCodewords, accumData, accumCount * 3 + 1); + } + + } else if (isAlphanumeric((char*)text, length)) { + mode = MODE_ALPHANUMERIC; + bb_appendBits(dataCodewords, 1 << MODE_ALPHANUMERIC, 4); + bb_appendBits(dataCodewords, length, getModeBits(version, MODE_ALPHANUMERIC)); + + uint16_t accumData = 0; + uint8_t accumCount = 0; + for (uint16_t i = 0; i < length; i++) { + accumData = accumData * 45 + getAlphanumeric((char)(text[i])); + accumCount++; + if (accumCount == 2) { + bb_appendBits(dataCodewords, accumData, 11); + accumData = 0; + accumCount = 0; + } + } + + // 1 character remaining + if (accumCount > 0) { + bb_appendBits(dataCodewords, accumData, 6); + } + + } else { + bb_appendBits(dataCodewords, 1 << MODE_BYTE, 4); + bb_appendBits(dataCodewords, length, getModeBits(version, MODE_BYTE)); + for (uint16_t i = 0; i < length; i++) { + bb_appendBits(dataCodewords, (char)(text[i]), 8); + } + } + + //bb_setBits(dataCodewords, length, 4, getModeBits(version, mode)); + + return mode; +} + +static void performErrorCorrection(uint8_t version, uint8_t ecc, BitBucket *data) { + + // See: http://www.thonky.com/qr-code-tutorial/structure-final-message + +#if LOCK_VERSION == 0 + uint8_t numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecc][version - 1]; + uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc][version - 1]; + uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1]; +#else + uint8_t numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecc]; + uint16_t totalEcc = NUM_ERROR_CORRECTION_CODEWORDS[ecc]; + uint16_t moduleCount = NUM_RAW_DATA_MODULES; +#endif + + uint8_t blockEccLen = totalEcc / numBlocks; + uint8_t numShortBlocks = numBlocks - moduleCount / 8 % numBlocks; + uint8_t shortBlockLen = moduleCount / 8 / numBlocks; + + uint8_t shortDataBlockLen = shortBlockLen - blockEccLen; + + uint8_t result[data->capacityBytes]; + memset(result, 0, sizeof(result)); + + uint8_t coeff[blockEccLen]; + rs_init(blockEccLen, coeff); + + uint16_t offset = 0; + uint8_t *dataBytes = data->data; + + + // Interleave all short blocks + for (uint8_t i = 0; i < shortDataBlockLen; i++) { + uint16_t index = i; + uint8_t stride = shortDataBlockLen; + for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { + result[offset++] = dataBytes[index]; + +#if LOCK_VERSION == 0 || LOCK_VERSION >= 5 + if (blockNum == numShortBlocks) { stride++; } +#endif + index += stride; + } + } + + // Version less than 5 only have short blocks +#if LOCK_VERSION == 0 || LOCK_VERSION >= 5 + { + // Interleave long blocks + uint16_t index = shortDataBlockLen * (numShortBlocks + 1); + uint8_t stride = shortDataBlockLen; + for (uint8_t blockNum = 0; blockNum < numBlocks - numShortBlocks; blockNum++) { + result[offset++] = dataBytes[index]; + + if (blockNum == 0) { stride++; } + index += stride; + } + } +#endif + + // Add all ecc blocks, interleaved + uint8_t blockSize = shortDataBlockLen; + for (uint8_t blockNum = 0; blockNum < numBlocks; blockNum++) { + +#if LOCK_VERSION == 0 || LOCK_VERSION >= 5 + if (blockNum == numShortBlocks) { blockSize++; } +#endif + rs_getRemainder(blockEccLen, coeff, dataBytes, blockSize, &result[offset + blockNum], numBlocks); + dataBytes += blockSize; + } + + memcpy(data->data, result, data->capacityBytes); + data->bitOffsetOrWidth = moduleCount; +} + +// We store the Format bits tightly packed into a single byte (each of the 4 modes is 2 bits) +// The format bits can be determined by ECC_FORMAT_BITS >> (2 * ecc) +static const uint8_t ECC_FORMAT_BITS = (0x02 << 6) | (0x03 << 4) | (0x00 << 2) | (0x01 << 0); + + +//#pragma mark - Public QRCode functions + +uint16_t qrcode_getBufferSize(uint8_t version) { + return bb_getGridSizeBytes(4 * version + 17); +} + +// @TODO: Return error if data is too big. +int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length) { + uint8_t size = version * 4 + 17; + qrcode->version = version; + qrcode->size = size; + qrcode->ecc = ecc; + qrcode->modules = modules; + + uint8_t eccFormatBits = (ECC_FORMAT_BITS >> (2 * ecc)) & 0x03; + +#if LOCK_VERSION == 0 + uint16_t moduleCount = NUM_RAW_DATA_MODULES[version - 1]; + uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits][version - 1]; +#else + version = LOCK_VERSION; + uint16_t moduleCount = NUM_RAW_DATA_MODULES; + uint16_t dataCapacity = moduleCount / 8 - NUM_ERROR_CORRECTION_CODEWORDS[eccFormatBits]; +#endif + + struct BitBucket codewords; + uint8_t codewordBytes[bb_getBufferSizeBytes(moduleCount)]; + bb_initBuffer(&codewords, codewordBytes, (int32_t)sizeof(codewordBytes)); + + // Place the data code words into the buffer + int8_t mode = encodeDataCodewords(&codewords, data, length, version); + + if (mode < 0) { return -1; } + qrcode->mode = mode; + + // Add terminator and pad up to a byte if applicable + uint32_t padding = (dataCapacity * 8) - codewords.bitOffsetOrWidth; + if (padding > 4) { padding = 4; } + bb_appendBits(&codewords, 0, padding); + bb_appendBits(&codewords, 0, (8 - codewords.bitOffsetOrWidth % 8) % 8); + + // Pad with alternate bytes until data capacity is reached + for (uint8_t padByte = 0xEC; codewords.bitOffsetOrWidth < (dataCapacity * 8); padByte ^= 0xEC ^ 0x11) { + bb_appendBits(&codewords, padByte, 8); + } + + BitBucket modulesGrid; + bb_initGrid(&modulesGrid, modules, size); + + BitBucket isFunctionGrid; + uint8_t isFunctionGridBytes[bb_getGridSizeBytes(size)]; + bb_initGrid(&isFunctionGrid, isFunctionGridBytes, size); + + // Draw function patterns, draw all codewords, do masking + drawFunctionPatterns(&modulesGrid, &isFunctionGrid, version, eccFormatBits); + performErrorCorrection(version, eccFormatBits, &codewords); + drawCodewords(&modulesGrid, &isFunctionGrid, &codewords); + + // Find the best (lowest penalty) mask + uint8_t mask = 0; + int32_t minPenalty = INT32_MAX; + for (uint8_t i = 0; i < 8; i++) { + drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, i); + applyMask(&modulesGrid, &isFunctionGrid, i); + int penalty = getPenaltyScore(&modulesGrid); + if (penalty < minPenalty) { + mask = i; + minPenalty = penalty; + } + applyMask(&modulesGrid, &isFunctionGrid, i); // Undoes the mask due to XOR + } + + qrcode->mask = mask; + + // Overwrite old format bits + drawFormatBits(&modulesGrid, &isFunctionGrid, eccFormatBits, mask); + + // Apply the final choice of mask + applyMask(&modulesGrid, &isFunctionGrid, mask); + + return 0; +} + +int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data) { + return qrcode_initBytes(qrcode, modules, version, ecc, (uint8_t*)data, strlen(data)); +} + +bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y) { + if (x < 0 || x >= qrcode->size || y < 0 || y >= qrcode->size) { + return false; + } + + uint32_t offset = y * qrcode->size + x; + return (qrcode->modules[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0; +} + +/* +uint8_t qrcode_getHexLength(QRCode *qrcode) { + return ((qrcode->size * qrcode->size) + 7) / 4; +} + +void qrcode_getHex(QRCode *qrcode, char *result) { + +} +*/ diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/qrcode.h b/MicroPython_BUILD/components/micropython/esp32/libs/qrcode.h new file mode 100755 index 00000000..692aa1c8 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/libs/qrcode.h @@ -0,0 +1,94 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Richard Moore + * + * 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. + */ + +/** + * Special thanks to Nayuki (https://www.nayuki.io/) from which this library was + * heavily inspired and compared against. + * + * See: https://github.com/nayuki/QR-Code-generator/tree/master/cpp + */ + + +#ifndef __QRCODE_H_ +#define __QRCODE_H_ + +#include + +#ifndef bool +#define bool uint8_t +static const bool false = 0; +static const bool true = 1; +#endif + +// QR Code Format Encoding +#define MODE_NUMERIC 0 +#define MODE_ALPHANUMERIC 1 +#define MODE_BYTE 2 + + +// Error Correction Code Levels +#define ECC_LOW 0 +#define ECC_MEDIUM 1 +#define ECC_QUARTILE 2 +#define ECC_HIGH 3 + + +// If set to non-zero, this library can ONLY produce QR codes at that version +// This saves a lot of dynamic memory, as the codeword tables are skipped +#ifndef LOCK_VERSION +#define LOCK_VERSION 0 +#endif + + +typedef struct QRCode { + uint8_t version; + uint8_t size; + uint8_t ecc; + uint8_t mode; + uint8_t mask; + uint8_t *modules; +} QRCode; + + +#ifdef __cplusplus +extern "C"{ +#endif /* __cplusplus */ + + + +uint16_t qrcode_getBufferSize(uint8_t version); + +int8_t qrcode_initText(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, const char *data); +int8_t qrcode_initBytes(QRCode *qrcode, uint8_t *modules, uint8_t version, uint8_t ecc, uint8_t *data, uint16_t length); + +bool qrcode_getModule(QRCode *qrcode, uint8_t x, uint8_t y); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __QRCODE_H_ */ diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/soft_uart.c b/MicroPython_BUILD/components/micropython/esp32/libs/soft_uart.c index 47e4a4bd..82384a0a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/soft_uart.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/soft_uart.c @@ -1,3 +1,29 @@ +* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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. + */ + // UART.C // // Generic software uart written in C, requiring a timer set to 3 times diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c index f0abb6ca..244ab154 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c @@ -149,8 +149,15 @@ static telnet_data_t telnet_data = {0}; static const char* telnet_welcome_msg = "MicroPython " MICROPY_GIT_TAG " - " MICROPY_BUILD_DATE " on " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n"; static const char* telnet_request_user = "Login as: "; static const char* telnet_request_password = "Password: "; -static const char* telnet_invalid_login = "\r\nInvalid credentials, try again.\r\n"; -static const char* telnet_login_success = "\r\nLogin succeeded!\r\nType \"help()\" for more information.\r\n"; +static const char* telnet_invalid_login = "\r\nInvalid credentials, try again.\r\n"; + +#if TELNET_LOGIN_MSG_LEN_MAX > 0 +static char telnet_login_msg[TELNET_LOGIN_MSG_LEN_MAX+1]; +#else +const char* telnet_login_msg = "\r\nLogin succeeded!\r\nType \"help()\" for more information.\r\n"; +#endif +char *telnet_login_success = telnet_login_msg; + static const uint8_t telnet_options_user[] = { IAC, WONT, ECHO, IAC, WONT, SUPPRESS_GO_AHEAD, IAC, WILL, LINEMODE }; static const uint8_t telnet_options_pass[] = { IAC, WILL, ECHO, IAC, WONT, SUPPRESS_GO_AHEAD, IAC, WILL, LINEMODE }; static const uint8_t telnet_options_repl[] = { IAC, WILL, ECHO, IAC, WILL, SUPPRESS_GO_AHEAD, IAC, WONT, LINEMODE }; @@ -723,6 +730,16 @@ bool telnet_terminate (void) { return true; } +//---------------------------- +bool telnet_stop_requested() { + if ((TelnetTaskHandle == NULL) || (telnet_mutex == NULL)) return false; + if (xSemaphoreTake(telnet_mutex, TELNET_MUTEX_TIMEOUT_MS / portTICK_PERIOD_MS) !=pdTRUE) return false; + + bool res = (telnet_stop == 1); + xSemaphoreGive(telnet_mutex); + return res; +} + //---------------------------------- int32_t telnet_get_maxstack (void) { if ((TelnetTaskHandle == NULL) || (telnet_mutex == NULL)) return -1; diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h index a39850da..e684e217 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h @@ -41,6 +41,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +#define TELNET_LOGIN_MSG_LEN_MAX 128 // set this to 0 to use static login msg #define TELNET_USER_PASS_LEN_MAX 32 #define TELNET_DEF_USER "micro" #define TELNET_DEF_PASS "python" @@ -58,6 +59,7 @@ typedef enum { extern char telnet_user[TELNET_USER_PASS_LEN_MAX + 1]; extern char telnet_pass[TELNET_USER_PASS_LEN_MAX + 1]; +char *telnet_login_success; extern uint32_t telnet_stack_size; extern QueueHandle_t telnet_mutex; extern int telnet_timeout; @@ -79,6 +81,7 @@ bool telnet_isenabled (void); bool telnet_reset (void); int telnet_getstate(); bool telnet_terminate (void); +bool telnet_stop_requested(); int32_t telnet_get_maxstack (void); #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/DefaultFont.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/DefaultFont.c index 3e3c2a07..5ec86aee 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/DefaultFont.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/DefaultFont.c @@ -38,6 +38,10 @@ // Memory usage : 1158 bytes // # characters : 95 +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + const unsigned char tft_DefaultFont[] = { 0x00, 0x0B, 0x86, 0x04, @@ -331,3 +335,5 @@ const unsigned char tft_DefaultFont[] = // Terminator 0xFF }; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans18.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans18.c index b9e6ba94..922c3ff6 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans18.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans18.c @@ -27,6 +27,10 @@ // Memory usage : 1828 bytes // # characters : 95 +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + const unsigned char tft_Dejavu18[] = { 0x00, 0x12, 0x00, 0x00, @@ -320,3 +324,5 @@ const unsigned char tft_Dejavu18[] = // Terminator 0xFF }; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans24.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans24.c index aa7e2f1a..69893491 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans24.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/DejaVuSans24.c @@ -36,6 +36,10 @@ // Memory usage : 2724 bytes // # characters : 95 +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + const unsigned char tft_Dejavu24[] = { 0x00, 0x17, 0x00, 0x00, @@ -329,3 +333,5 @@ const unsigned char tft_Dejavu24[] = // Terminator 0xFF }; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c index b7c8943b..d0ac220d 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c @@ -3,6 +3,9 @@ // Font size : 8x12 pixels // Memory usage : 1144 bytes +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT const unsigned char tft_SmallFont[1144] = { @@ -108,3 +111,5 @@ const unsigned char tft_SmallFont[1144] = 0x00,0x60,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x60,0x00, // } 0x40,0xA4,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // ~ }; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/comic24.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/comic24.c index f897e31f..fe9d312c 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/comic24.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/comic24.c @@ -21,6 +21,10 @@ // First Character (Reserved. 0x00) // Number Of Characters (Reserved. 0x00) +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + const unsigned char tft_Comic24[] = { 0x00, 0x19, 0x00, 0x00, @@ -329,3 +333,5 @@ const unsigned char tft_Comic24[] = // Terminator 0xFF }; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/def_small.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/def_small.c index 725a20a5..b5e879d9 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/def_small.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/def_small.c @@ -22,6 +22,10 @@ // Number Of Characters (Reserved. 0x00) +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + const unsigned char tft_def_small[] = { 0x00, 0x08, 0x00, 0x00, @@ -330,3 +334,5 @@ const unsigned char tft_def_small[] = // Terminator 0xFF }; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/minya24.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/minya24.c index 223bd668..c3080ab5 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/minya24.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/minya24.c @@ -21,6 +21,10 @@ // First Character (Reserved. 0x00) // Number Of Characters (Reserved. 0x00) +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + const unsigned char tft_minya24[] = { 0x00, 0x15, 0x00, 0x00, @@ -329,3 +333,5 @@ const unsigned char tft_minya24[] = // Terminator 0xFF }; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h b/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h index 50f3e19c..d4cae2db 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h @@ -30,6 +30,10 @@ #ifndef _STMPE610_H #define _STMPE610_H +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + #include #define STMPE610_SPI_MODE 0 @@ -145,4 +149,6 @@ #define STMPE610_REG_INT_CTRL_ENABLE 0x01 #define STMPE610_REG_INT_CTRL_DISABLE 0x00 -#endif /* _STMPE610_H */ +#endif // CONFIG_MICROPY_USE_TFT + +#endif // _STMPE610_H diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.c index 1f7eb91c..29a02627 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.c @@ -32,6 +32,10 @@ * Library supporting SPI TFT displays based on ILI9341, ILI9488 & ST7789V controllers */ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + #include #include #include @@ -45,6 +49,11 @@ #include "rom/tjpgd.h" #include "esp_heap_caps.h" #include "tftspi.h" +#include "driver/ledc.h" + +#if CONFIG_MICROPY_USE_EVE +#include "eve/FT8.h" +#endif #include "py/mpprint.h" #include "extmod/vfs_native.h" @@ -96,6 +105,8 @@ const color_t TFT_PINK = { 252, 192, 202 }; // ============================================================== // ==== Set default values of global variables ================== + +uint8_t tft_active_mode = TFT_MODE_TFT; uint8_t orientation = LANDSCAPE;// screen orientation uint16_t font_rotate = 0; // font rotation uint8_t font_transparent = 0; @@ -104,6 +115,9 @@ uint8_t text_wrap = 0; // character wrapping to new line color_t _fg = { 0, 255, 0}; color_t _bg = { 0, 0, 0}; uint8_t image_debug = 0; +uint8_t font_now = 0; +uint16_t image_width = 0; +uint16_t image_hight = 0; float _angleOffset = DEFAULT_ANGLE_OFFSET; @@ -131,6 +145,15 @@ Font cfont = { uint8_t font_buffered_char = 1; uint8_t font_line_space = 0; + +// ------------------------ +// ePaper display variables +// ------------------------ +uint8_t *drawBuff = NULL; +uint8_t *gs_drawBuff = NULL; +uint8_t _gs = 0; +uint16_t gs_used_shades = 0; + // ============================================================== @@ -172,18 +195,248 @@ int TFT_compare_colors(color_t c1, color_t c2) return 0; } +// ==== EPD low level functions ==================================================== + +//-------------------------------------------------- +static void EPD_drawPixel(int x, int y, uint8_t val) +{ + if (orientation == LANDSCAPE_FLIP) { + x = _width - x - 1; + y = _height - y - 1; + } + if (_gs) { + val &= 0x0F; + //if (gs_drawBuff[(y * _width) + x] != val) { + gs_drawBuff[(y * _width) + x] = val; + gs_used_shades |= (1<> 3)) + (y>>3)]; + uint8_t new_val = buf_val; + if (val) new_val &= (0x80 >> (y % 8)) ^ 0xFF; + else new_val |= (0x80 >> (y % 8)); + //if (new_val != buf_val) drawBuff[(x * (_height>>3)) + (y>>3)] = new_val; + drawBuff[(x * (_height>>3)) + (y>>3)] = new_val; + } +} + +//------------------------------------------------------------------------- +static void EPD_pushColorRep(int x1, int y1, int x2, int y2, uint8_t color) +{ + if (_gs == 0) color &= 0x01; + else color &= 0x0F; + for (int y=y1; y<=y2; y++) { + for (int x = x1; x<=x2; x++){ + EPD_drawPixel(x, y, color); + } + } +} + +// ^^^^ EPD low level functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +#if CONFIG_MICROPY_USE_EVE +// ==== EVE low level functions ==================================================== + +tft_eve_obj_t *eve_tft_obj = NULL; + + +//-------------------------------------- +static uint16_t eve_color(color_t color) +{ + uint16_t _color; + if (eve_tft_obj->type == FT8_RGB565) { + _color = (uint16_t)(color.r & 0xF8) << 8; + _color |= (uint16_t)(color.g & 0xFC) << 3; + _color |= (uint16_t)(color.b & 0xF8) >> 3; + } + else { + _color = (uint16_t)(color.r & 0xE0); + _color |= (uint16_t)(color.g & 0xE0) >> 3; + _color |= (uint16_t)(color.b & 0xC0) >> 6; + } + return _color; +} + +//---------------------------------------------------- +static void EVE_drawPixel(int x, int y, color_t color) +{ + if (eve_tft_obj == NULL) return; + + uint16_t _color = eve_color(color); + // calculate pixel address + uint32_t addr = eve_tft_obj->addr + (y * eve_tft_obj->rowsize) + (x * eve_tft_obj->byte_per_pixel); + if (eve_tft_obj->type == FT8_RGB565) FT8_memWrite16(addr, _color); + else FT8_memWrite8(addr, (uint8_t)_color); +} + +//------------------------------------------------------------------------- +static void EVE_pushColorRep(int x1, int y1, int x2, int y2, color_t color) +{ + if (eve_tft_obj == NULL) return; + + uint16_t _color = eve_color(color); + + int y = y1; + uint16_t xlen = x2 - x1 + 1; + uint8_t buff[xlen * eve_tft_obj->byte_per_pixel]; + uint32_t addr; + + if (xlen > 2) { + // fill buffer with color + if (eve_tft_obj->type == FT8_RGB565) { + for (int i=0; i> 8; // high byte first + buff[i+1] = _color & 0x00FF; + } + } + else { + for (int i=0; iaddr + ((y * eve_tft_obj->width) * eve_tft_obj->byte_per_pixel) + (x1 * eve_tft_obj->byte_per_pixel); + if (eve_tft_obj->type == FT8_RGB565) { + if (xlen == 1) FT8_memWrite16(addr, _color); + else if (xlen == 2) FT8_memWrite32(addr, (uint32_t)((_color << 16) | _color)); + else FT8_memWrite_flash_buffer(addr, (uint8_t *)buff, xlen*2, false); + } + else { + if (xlen == 1) FT8_memWrite8(addr, (uint8_t)_color); + else if (xlen == 2) FT8_memWrite16(addr, (uint16_t)((_color << 16) | _color)); + else FT8_memWrite_flash_buffer(addr, (uint8_t *)buff, xlen, false); + } + y++; + if (y >= _height) break; + } + + spi_device_deselect(eve_spi); + ft8_full_cs = 1; +} + +//------------------------------------------------------------------------------------ +static void EVE_send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t *cbuf) +{ + if (eve_tft_obj == NULL) return; + + int y = y1; + int buf_pos = 0; + uint16_t xlen = x2 - x1 + 1; + uint8_t buff[xlen * eve_tft_obj->byte_per_pixel]; + uint32_t addr; + + spi_device_select(eve_spi, 0); + ft8_full_cs = 0; + while (y <= y2) { + // fill the row buffer + if (eve_tft_obj->type == FT8_RGB565) { + for (int i=0; i> 8; + buff[i+1] = eve_color(cbuf[buf_pos]) & 0x00FF; + buf_pos++; + } + } + else { + for (int i=0; iaddr + ((y * eve_tft_obj->width) * eve_tft_obj->byte_per_pixel) + (x1 * eve_tft_obj->byte_per_pixel); + FT8_memWrite_flash_buffer(addr, (uint8_t *)buff, xlen*eve_tft_obj->byte_per_pixel, false); + y++; + if (y >= _height) break; + } + spi_device_deselect(eve_spi); + ft8_full_cs = 1; +} + +// ^^^^ EVE low level functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#endif + +//=========================================================================================== + +//------------------------------------ +static esp_err_t TFT_EPD_disp_select() +{ + #if CONFIG_MICROPY_USE_EVE + if (tft_active_mode == TFT_MODE_EVE) { + spi_device_select(eve_spi, 0); + ft8_full_cs = 0; + return ESP_OK; + } + #endif + return disp_select(); +} + +//-------------------------------------- +static esp_err_t TFT_EPD_disp_deselect() +{ + #if CONFIG_MICROPY_USE_EVE + if (tft_active_mode == TFT_MODE_EVE) { + spi_device_deselect(eve_spi); + ft8_full_cs = 1; + return ESP_OK; + } + #endif + return disp_deselect(); +} + +//----------------------------------------------------------------------------------------------------- +static void TFT_EPD_send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t *buf, uint8_t wait) +{ + #if CONFIG_MICROPY_USE_EVE + if (tft_active_mode == TFT_MODE_EVE) { + EVE_send_data(x1, y1, x2, y2, len, buf); + } + else send_data(x1, y1, x2, y2, len, buf, wait); + #else + send_data(x1, y1, x2, y2, len, buf, wait); + #endif +} + // draw color pixel on screen -//------------------------------------------------------------------------ -static void _drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel) { +//---------------------------------------------------------------------- +static void TFT_EPD_drawPixe(int16_t x, int16_t y, color_t color, uint8_t sel) +{ + if ((x < dispWin.x1) || (y < dispWin.y1) || (x > dispWin.x2) || (y > dispWin.y2)) return; + + if (tft_active_mode == TFT_MODE_EPD) EPD_drawPixel(x, y, color.b); + #if CONFIG_MICROPY_USE_EVE + else if (tft_active_mode == TFT_MODE_EVE) EVE_drawPixel(x, y, color); + #endif + else if (tft_active_mode == TFT_MODE_TFT) drawPixel(x, y, color, sel); +} + +//------------------------------------------------------------------------------------------- +static void TFT_EPD_pushColorRep(int x1, int y1, int x2, int y2, color_t color, uint32_t len) +{ + if (len == 0) return; - if ((x < dispWin.x1) || (y < dispWin.y1) || (x > dispWin.x2) || (y > dispWin.y2)) return; - drawPixel(x, y, color, sel); + if (tft_active_mode == TFT_MODE_EPD) EPD_pushColorRep(x1, y1, x2, y2, color.b); + #if CONFIG_MICROPY_USE_EVE + else if (tft_active_mode == TFT_MODE_EVE) EVE_pushColorRep(x1, y1, x2, y2, color); + #endif + else if (tft_active_mode == TFT_MODE_TFT) TFT_pushColorRep(x1, y1, x2, y2, color, len); } +//=========================================================================================== + + //==================================================================== void TFT_drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel) { - _drawPixel(x+dispWin.x1, y+dispWin.y1, color, sel); + TFT_EPD_drawPixe(x+dispWin.x1, y+dispWin.y1, color, sel); } //=========================================== @@ -205,7 +458,7 @@ static void _drawFastVLine(int16_t x, int16_t y, int16_t h, color_t color) { if (h < 0) h = 0; if ((y + h) > (dispWin.y2+1)) h = dispWin.y2 - y + 1; if (h == 0) h = 1; - TFT_pushColorRep(x, y, x, y+h-1, color, (uint32_t)h); + TFT_EPD_pushColorRep(x, y, x, y+h-1, color, (uint32_t)h); } //-------------------------------------------------------------------------- @@ -220,7 +473,7 @@ static void _drawFastHLine(int16_t x, int16_t y, int16_t w, color_t color) { if ((x + w) > (dispWin.x2+1)) w = dispWin.x2 - x + 1; if (w == 0) w = 1; - TFT_pushColorRep(x, y, x+w-1, y, color, (uint32_t)w); + TFT_EPD_pushColorRep(x, y, x+w-1, y, color, (uint32_t)w); } //====================================================================== @@ -233,8 +486,8 @@ void TFT_drawFastHLine(int16_t x, int16_t y, int16_t w, color_t color) { _drawFastHLine(x+dispWin.x1, y+dispWin.y1, w, color); } -// Bresenham's algorithm - thx wikipedia - speed enhanced by Bodmer this uses -// the eficient FastH/V Line draw routine for segments of 2 pixels or more +// Bresenham's algorithm, speed enhanced by Bodmer this uses +// the efficient FastH/V Line draw routine for segments of 2 pixels or more //---------------------------------------------------------------------------------- static void _drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, color_t color) { @@ -272,7 +525,7 @@ static void _drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, color_t co err -= dy; if (err < 0) { err += dx; - if (dlen == 1) _drawPixel(y0, xs, color, 1); + if (dlen == 1) TFT_EPD_drawPixe(y0, xs, color, 1); else _drawFastVLine(y0, xs, dlen, color); dlen = 0; y0 += ystep; xs = x0 + 1; } @@ -286,7 +539,7 @@ static void _drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, color_t co err -= dy; if (err < 0) { err += dx; - if (dlen == 1) _drawPixel(xs, y0, color, 1); + if (dlen == 1) TFT_EPD_drawPixe(xs, y0, color, 1); else _drawFastHLine(xs, y0, dlen, color); dlen = 0; y0 += ystep; xs = x0 + 1; } @@ -322,7 +575,7 @@ static void _fillRect(int16_t x, int16_t y, int16_t w, int16_t h, color_t color) if ((y + h) > (dispWin.y2+1)) h = dispWin.y2 - y + 1; if (w == 0) w = 1; if (h == 0) h = 1; - TFT_pushColorRep(x, y, x+w-1, y+h-1, color, (uint32_t)(h*w)); + TFT_EPD_pushColorRep(x, y, x+w-1, y+h-1, color, (uint32_t)(h*w)); } //============================================================================ @@ -332,12 +585,12 @@ void TFT_fillRect(int16_t x, int16_t y, int16_t w, int16_t h, color_t color) { //================================== void TFT_fillScreen(color_t color) { - TFT_pushColorRep(0, 0, _width-1, _height-1, color, (uint32_t)(_height*_width)); + TFT_EPD_pushColorRep(0, 0, _width-1, _height-1, color, (uint32_t)(_height*_width)); } //================================== void TFT_fillWindow(color_t color) { - TFT_pushColorRep(dispWin.x1, dispWin.y1, dispWin.x2, dispWin.y2, + TFT_EPD_pushColorRep(dispWin.x1, dispWin.y1, dispWin.x2, dispWin.y2, color, (uint32_t)((dispWin.x2-dispWin.x1+1) * (dispWin.y2-dispWin.y1+1))); } @@ -368,7 +621,7 @@ static void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornerna int16_t x = 0; int16_t y = r; - disp_select(); + TFT_EPD_disp_select(); while (x < y) { if (f >= 0) { y--; @@ -379,23 +632,23 @@ static void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornerna ddF_x += 2; f += ddF_x; if (cornername & 0x4) { - _drawPixel(x0 + x, y0 + y, color, 0); - _drawPixel(x0 + y, y0 + x, color, 0); + TFT_EPD_drawPixe(x0 + x, y0 + y, color, 0); + TFT_EPD_drawPixe(x0 + y, y0 + x, color, 0); } if (cornername & 0x2) { - _drawPixel(x0 + x, y0 - y, color, 0); - _drawPixel(x0 + y, y0 - x, color, 0); + TFT_EPD_drawPixe(x0 + x, y0 - y, color, 0); + TFT_EPD_drawPixe(x0 + y, y0 - x, color, 0); } if (cornername & 0x8) { - _drawPixel(x0 - y, y0 + x, color, 0); - _drawPixel(x0 - x, y0 + y, color, 0); + TFT_EPD_drawPixe(x0 - y, y0 + x, color, 0); + TFT_EPD_drawPixe(x0 - x, y0 + y, color, 0); } if (cornername & 0x1) { - _drawPixel(x0 - y, y0 - x, color, 0); - _drawPixel(x0 - x, y0 - y, color, 0); + TFT_EPD_drawPixe(x0 - y, y0 - x, color, 0); + TFT_EPD_drawPixe(x0 - x, y0 - y, color, 0); } } - disp_deselect(); + TFT_EPD_disp_deselect(); } // Used to do circles and roundrects @@ -620,11 +873,11 @@ void TFT_drawCircle(int16_t x, int16_t y, int radius, color_t color) { int x1 = 0; int y1 = radius; - disp_select(); - _drawPixel(x, y + radius, color, 0); - _drawPixel(x, y - radius, color, 0); - _drawPixel(x + radius, y, color, 0); - _drawPixel(x - radius, y, color, 0); + TFT_EPD_disp_select(); + TFT_EPD_drawPixe(x, y + radius, color, 0); + TFT_EPD_drawPixe(x, y - radius, color, 0); + TFT_EPD_drawPixe(x + radius, y, color, 0); + TFT_EPD_drawPixe(x - radius, y, color, 0); while(x1 < y1) { if (f >= 0) { y1--; @@ -634,16 +887,16 @@ void TFT_drawCircle(int16_t x, int16_t y, int radius, color_t color) { x1++; ddF_x += 2; f += ddF_x; - _drawPixel(x + x1, y + y1, color, 0); - _drawPixel(x - x1, y + y1, color, 0); - _drawPixel(x + x1, y - y1, color, 0); - _drawPixel(x - x1, y - y1, color, 0); - _drawPixel(x + y1, y + x1, color, 0); - _drawPixel(x - y1, y + x1, color, 0); - _drawPixel(x + y1, y - x1, color, 0); - _drawPixel(x - y1, y - x1, color, 0); + TFT_EPD_drawPixe(x + x1, y + y1, color, 0); + TFT_EPD_drawPixe(x - x1, y + y1, color, 0); + TFT_EPD_drawPixe(x + x1, y - y1, color, 0); + TFT_EPD_drawPixe(x - x1, y - y1, color, 0); + TFT_EPD_drawPixe(x + y1, y + x1, color, 0); + TFT_EPD_drawPixe(x - y1, y + x1, color, 0); + TFT_EPD_drawPixe(x + y1, y - x1, color, 0); + TFT_EPD_drawPixe(x - y1, y - x1, color, 0); } - disp_deselect(); + TFT_EPD_disp_deselect(); } //==================================================================== @@ -658,16 +911,16 @@ void TFT_fillCircle(int16_t x, int16_t y, int radius, color_t color) { //---------------------------------------------------------------------------------------------------------------- static void _draw_ellipse_section(uint16_t x, uint16_t y, uint16_t x0, uint16_t y0, color_t color, uint8_t option) { - disp_select(); + TFT_EPD_disp_select(); // upper right - if ( option & TFT_ELLIPSE_UPPER_RIGHT ) _drawPixel(x0 + x, y0 - y, color, 0); + if ( option & TFT_ELLIPSE_UPPER_RIGHT ) TFT_EPD_drawPixe(x0 + x, y0 - y, color, 0); // upper left - if ( option & TFT_ELLIPSE_UPPER_LEFT ) _drawPixel(x0 - x, y0 - y, color, 0); + if ( option & TFT_ELLIPSE_UPPER_LEFT ) TFT_EPD_drawPixe(x0 - x, y0 - y, color, 0); // lower right - if ( option & TFT_ELLIPSE_LOWER_RIGHT ) _drawPixel(x0 + x, y0 + y, color, 0); + if ( option & TFT_ELLIPSE_LOWER_RIGHT ) TFT_EPD_drawPixe(x0 + x, y0 + y, color, 0); // lower left - if ( option & TFT_ELLIPSE_LOWER_LEFT ) _drawPixel(x0 - x, y0 + y, color, 0); - disp_deselect(); + if ( option & TFT_ELLIPSE_LOWER_LEFT ) TFT_EPD_drawPixe(x0 - x, y0 + y, color, 0); + TFT_EPD_disp_deselect(); } //===================================================================================================== @@ -873,7 +1126,7 @@ static void _fillArcOffsetted(uint16_t cx, uint16_t cy, uint16_t radius, uint16_ int ir2 = (radius - thickness) * (radius - thickness); int or2 = radius * radius; - disp_select(); + TFT_EPD_disp_select(); for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { int x2 = x * x; @@ -896,10 +1149,10 @@ static void _fillArcOffsetted(uint16_t cx, uint16_t cy, uint16_t radius, uint16_ (y == 0 && start == 0 && x > 0) ) ) - _drawPixel(cx+x, cy+y, color, 0); + TFT_EPD_drawPixe(cx+x, cy+y, color, 0); } } - disp_deselect(); + TFT_EPD_disp_deselect(); } @@ -1533,6 +1786,7 @@ void fontProperties() { void TFT_setFont(uint8_t font, const char *font_file) { cfont.font = NULL; + font_now = font; if (font == FONT_7SEG) { cfont.bitmap = 2; @@ -1546,7 +1800,7 @@ void TFT_setFont(uint8_t font, const char *font_file) if (load_file_font(font_file, 0) != 0) cfont.font = tft_DefaultFont; else cfont.font = userfont; } - else if (font == DEJAVU18_FONT) cfont.font = tft_Dejavu18; + else if (font == DEJAVU18_FONT) cfont.font = tft_Dejavu18; else if (font == DEJAVU24_FONT) cfont.font = tft_Dejavu24; else if (font == UBUNTU16_FONT) cfont.font = tft_Ubuntu16; else if (font == COMIC24_FONT) cfont.font = tft_Comic24; @@ -1625,11 +1879,11 @@ static int printProportionalChar(int x, int y) { } } // send to display in one transaction - wait_trans_finish(1); - disp_select(); - send_data(x, y, x+char_width, y+cfont.y_size-1, len, color_line, 1); - disp_deselect(); - free(color_line); + if (tft_active_mode != TFT_MODE_EVE) wait_trans_finish(1); + TFT_EPD_disp_select(); + TFT_EPD_send_data(x, y, x+char_width, y+cfont.y_size-1, len, color_line, 1); + TFT_EPD_disp_deselect(); + if (tft_active_mode != TFT_MODE_EVE) free(color_line); return char_width; } @@ -1641,7 +1895,7 @@ static int printProportionalChar(int x, int y) { // draw Glyph uint8_t mask = 0x80; - disp_select(); + TFT_EPD_disp_select(); for (j=0; j < fontChar.height; j++) { for (i=0; i < fontChar.width; i++) { if (((i + (j*fontChar.width)) % 8) == 0) { @@ -1652,12 +1906,12 @@ static int printProportionalChar(int x, int y) { if ((ch & mask) !=0) { cx = (uint16_t)(x+fontChar.xOffset+i); cy = (uint16_t)(y+j+fontChar.adjYOffset); - _drawPixel(cx, cy, _fg, 0); + TFT_EPD_drawPixe(cx, cy, _fg, 0); } mask >>= 1; } } - disp_deselect(); + TFT_EPD_disp_deselect(); return char_width; } @@ -1697,11 +1951,11 @@ static void printChar(uint8_t c, int x, int y) { temp += (fz); } // send to display in one transaction - wait_trans_finish(1); - disp_select(); - send_data(x, y, x+cfont.x_size-1, y+cfont.y_size-1, len, color_line, 1); - disp_deselect(); - free(color_line); + if (tft_active_mode != TFT_MODE_EVE) wait_trans_finish(1); + TFT_EPD_disp_select(); + TFT_EPD_send_data(x, y, x+cfont.x_size-1, y+cfont.y_size-1, len, color_line, 1); + TFT_EPD_disp_deselect(); + if (tft_active_mode != TFT_MODE_EVE) free(color_line); return; } @@ -1709,7 +1963,7 @@ static void printChar(uint8_t c, int x, int y) { if (!font_transparent) _fillRect(x, y, cfont.x_size, cfont.y_size, _bg); - disp_select(); + TFT_EPD_disp_select(); for (j=0; j>= 1; } } temp += (fz); } - disp_deselect(); + TFT_EPD_disp_deselect(); } // print rotated proportional character @@ -1738,7 +1992,7 @@ static int rotatePropChar(int x, int y, int offset) { float sin_radian = sin(radian); uint8_t mask = 0x80; - disp_select(); + TFT_EPD_disp_select(); for (int j=0; j < fontChar.height; j++) { for (int i=0; i < fontChar.width; i++) { if (((i + (j*fontChar.width)) % 8) == 0) { @@ -1749,13 +2003,13 @@ static int rotatePropChar(int x, int y, int offset) { int newX = (int)(x + (((offset + i) * cos_radian) - ((j+fontChar.adjYOffset)*sin_radian))); int newY = (int)(y + (((j+fontChar.adjYOffset) * cos_radian) + ((offset + i) * sin_radian))); - if ((ch & mask) != 0) _drawPixel(newX,newY,_fg, 0); - else if (!font_transparent) _drawPixel(newX,newY,_bg, 0); + if ((ch & mask) != 0) TFT_EPD_drawPixe(newX,newY,_fg, 0); + else if (!font_transparent) TFT_EPD_drawPixe(newX,newY,_bg, 0); mask >>= 1; } } - disp_deselect(); + TFT_EPD_disp_deselect(); return fontChar.xDelta+1; } @@ -1775,7 +2029,7 @@ static void rotateChar(uint8_t c, int x, int y, int pos) { else fz = cfont.x_size/8; temp=((c-cfont.offset)*((fz)*cfont.y_size))+4; - disp_select(); + TFT_EPD_disp_select(); for (j=0; j>= 1; } } temp+=(fz); } - disp_deselect(); + TFT_EPD_disp_deselect(); // calculate x,y for the next char TFT_X = (int)(x + ((pos+1) * cfont.x_size * cos_radian)); TFT_Y = (int)(y + ((pos+1) * cfont.x_size * sin_radian)); @@ -1854,7 +2108,7 @@ void TFT_clearStringRect(int x, int y, char *str) static const uint16_t font_bcd[] = { 0x200, // 0010 0000 0000 // - 0x080, // 0000 1000 0000 // . - 0x06C, // 0100 0110 1100 // /, degree + 0x06C, // 0100 0110 1100 // / (degree sign) 0x05f, // 0000 0101 1111, // 0 0x005, // 0000 0000 0101, // 1 0x076, // 0000 0111 0110, // 2 @@ -1865,7 +2119,8 @@ static const uint16_t font_bcd[] = { 0x045, // 0000 0100 0101, // 7 0x07f, // 0000 0111 1111, // 8 0x07d, // 0000 0111 1101 // 9 - 0x900 // 1001 0000 0000 // : + 0x900, // 1001 0000 0000 // : + 0x000 // 0000 0000 0000 // ; (space) }; //----------------------------------------------------------------------------------------------- @@ -1895,9 +2150,11 @@ static void barHor(int16_t x, int16_t y, int16_t w, int16_t l, color_t color, co //-------------------------------------------------------------------------------------------- static void _draw7seg(int16_t x, int16_t y, int8_t num, int16_t w, int16_t l, color_t color) { /* TODO: clipping */ - if (num < 0x2D || num > 0x3A) return; + uint8_t nnum = num; + if (num == 0x20) nnum = 0x3B; // to clear the space character + if ((nnum < 0x2D) || (nnum > 0x3B)) return; - int16_t c = font_bcd[num-0x2D]; + int16_t c = font_bcd[nnum - 0x2D]; int16_t d = 2*w+l+1; // === Clear unused segments === @@ -1930,6 +2187,7 @@ static void _draw7seg(int16_t x, int16_t y, int8_t num, int16_t w, int16_t l, co if (cfont.offset) _drawRect(x+2*w+1, y+d, l, 2*w+1, _bg); } + if (c == 0) return; // === Draw used segments === if (c & 0x001) barVert(x+d, y+d, w, l, color, cfont.color); // down right if (c & 0x002) barVert(x, y+d, w, l, color, cfont.color); // down left @@ -2089,9 +2347,9 @@ void TFT_print(char *st, int x, int y) { void TFT_setRotation(uint8_t rot) { if (rot > 3) { uint8_t madctl = (rot & 0xF8); // for testing, manually set MADCTL register - if (disp_select() == ESP_OK) { + if (TFT_EPD_disp_select() == ESP_OK) { disp_spi_transfer_cmd_data(TFT_MADCTL, &madctl, 1); - disp_deselect(); + TFT_EPD_disp_deselect(); } } else { @@ -2381,30 +2639,51 @@ static UINT tjd_output ( if ((len > 0) && (len <= JPG_IMAGE_LINE_BUF_SIZE)) { - uint8_t *dest = (uint8_t *)(dev->linbuf[dev->linbuf_idx]); - - for (y = top; y <= bottom; y++) { - for (x = left; x <= right; x++) { - // Clip to display area - if ((x >= dleft) && (y >= dtop) && (x <= dright) && (y <= dbottom)) { - *dest++ = (*src++) & 0xFC; - *dest++ = (*src++) & 0xFC; - *dest++ = (*src++) & 0xFC; - } - else src += 3; // skip - } - } - if (image_trans) { - wait_trans_finish(1); - send_data(dleft, dtop, dright, dbottom, len, dev->linbuf[dev->linbuf_idx], 0); - } - else { - disp_select(); - send_data(dleft, dtop, dright, dbottom, len, dev->linbuf[dev->linbuf_idx], 0); - wait_trans_finish(1); - disp_deselect(); - } - dev->linbuf_idx = ((dev->linbuf_idx + 1) & 1); + if (tft_active_mode == TFT_MODE_EPD) { + uint8_t pix; + for (y = top; y <= bottom; y++) { + for (x = left; x <= right; x++) { + // Clip to display area + if ((x >= dleft) && (y >= dtop) && (x <= dright) && (y <= dbottom)) { + // Directly convert color to 4-bit gray scale + pix = 0; + pix |= ((*src++) >> 4) & 0x08; + pix |= ((*src++) >> 5) & 0x06; + pix |= ((*src++) >> 7); + pix ^= 0x0F; + gs_drawBuff[(y * _width) + x] = pix; + gs_used_shades |= (1 << pix); + } + else src += 3; // skip + } + } + } + else { + uint8_t *dest = (uint8_t *)(dev->linbuf[dev->linbuf_idx]); + + for (y = top; y <= bottom; y++) { + for (x = left; x <= right; x++) { + // Clip to display area + if ((x >= dleft) && (y >= dtop) && (x <= dright) && (y <= dbottom)) { + *dest++ = (*src++) & 0xFC; + *dest++ = (*src++) & 0xFC; + *dest++ = (*src++) & 0xFC; + } + else src += 3; // skip + } + } + if (image_trans) { + wait_trans_finish(1); + send_data(dleft, dtop, dright, dbottom, len, dev->linbuf[dev->linbuf_idx], 0); + } + else { + disp_select(); + send_data(dleft, dtop, dright, dbottom, len, dev->linbuf[dev->linbuf_idx], 0); + wait_trans_finish(1); + disp_deselect(); + } + dev->linbuf_idx = ((dev->linbuf_idx + 1) & 1); + } } else { if (image_trans) wait_trans_finish(1); @@ -2457,7 +2736,7 @@ void TFT_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int s } // Check if the image file is on sdcard - image_trans = file_noton_spi_sdcard(fname); + image_trans = file_noton_spi_sdcard(fname) & (tft_active_mode != TFT_MODE_EPD); if (scale > 3) scale = 3; @@ -2480,19 +2759,21 @@ void TFT_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int s dev.x = x; dev.y = y; - dev.linbuf[0] = malloc(JPG_IMAGE_LINE_BUF_SIZE*3); - if (dev.linbuf[0] == NULL) { - if (image_debug) mp_printf(&mp_plat_print, "Error allocating line buffer #0\r\n"); - goto exit; - } - dev.linbuf[1] = malloc(JPG_IMAGE_LINE_BUF_SIZE*3); - if (dev.linbuf[1] == NULL) { - if (image_debug) mp_printf(&mp_plat_print, "Error allocating line buffer #1\r\n"); - goto exit; + if (tft_active_mode != TFT_MODE_EPD) { + dev.linbuf[0] = malloc(JPG_IMAGE_LINE_BUF_SIZE*3); + if (dev.linbuf[0] == NULL) { + if (image_debug) mp_printf(&mp_plat_print, "Error allocating line buffer #0\r\n"); + goto exit; + } + dev.linbuf[1] = malloc(JPG_IMAGE_LINE_BUF_SIZE*3); + if (dev.linbuf[1] == NULL) { + if (image_debug) mp_printf(&mp_plat_print, "Error allocating line buffer #1\r\n"); + goto exit; + } } // Start to decode the JPEG file - if (image_trans) disp_select(); + if (image_trans) TFT_EPD_disp_select(); rc = jd_decomp(&jd, tjd_output, scale); if (image_trans) { wait_trans_finish(1); @@ -2503,6 +2784,8 @@ void TFT_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int s if (image_debug) mp_printf(&mp_plat_print, "jpg decompression error %d\r\n", rc); } if (image_debug) mp_printf(&mp_plat_print, "Jpg size: %dx%d, position; %d,%d, scale: %d, bytes used: %d\r\n", jd.width, jd.height, x, y, scale, jd.sz_pool); + image_width = jd.width; + image_hight = jd.height; } else { if (image_debug) mp_printf(&mp_plat_print, "jpg prepare error %d\r\n", rc); @@ -2708,7 +2991,8 @@ int TFT_bmp_image(int x, int y, uint8_t scale, char *fname, uint8_t *imgbuf, int if (image_debug) mp_printf(&mp_plat_print, "BMP: image size: (%d,%d) scale: %d disp size: (%d,%d) img xofs: %d img yofs: %d at: %d,%d; line buf: 2* %d scale buf: %d\r\n", img_xsize, img_ysize, scale_pix, img_xlen, img_ylen, img_xstart, img_ystart, disp_xstart, disp_ystart, img_xsize*3, ((scale) ? (rd_len*scale_pix) : 0)); - + image_width = img_xlen; + image_hight = img_ylen; // * Select the display if (image_trans) disp_select(); @@ -3013,3 +3297,30 @@ int TFT_read_touch(int *x, int* y, uint8_t raw) return 1; } +//.............LCD LED ............. +void led_pwm_init() { + ledc_timer_config_t ledc_timer = { + .bit_num = LEDC_TIMER_10_BIT, // resolution of PWM duty + .freq_hz = 10000, // frequency of PWM signal + .speed_mode = LEDC_HIGH_SPEED_MODE, // timer mode + .timer_num = LEDC_TIMER_3 // timer index + }; + // Set configuration of timer0 for high speed channels + ledc_timer_config(&ledc_timer); + + ledc_channel_config_t ledc_channel = + { + .channel = LEDC_CHANNEL_7, + .duty = 700, + .gpio_num = 32, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_sel = LEDC_TIMER_3 + }; + ledc_channel_config(&ledc_channel); +} + void led_setBrightness(int duty) { + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_7, duty); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_7); +} + +#endif \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h index a5ebc45a..81294112 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h @@ -32,8 +32,18 @@ #ifndef _TFT_H_ #define _TFT_H_ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + #include #include "tftspi.h" +#include "py/obj.h" + +#define TFT_MODE_TFT 0 +#define TFT_MODE_EPD 1 +#define TFT_MODE_EVE 2 + typedef struct { uint16_t x1; @@ -54,10 +64,24 @@ typedef struct { color_t color; } Font; +typedef struct _tft_eve_obj_t { + mp_obj_base_t base; + uint32_t addr; + uint32_t size; + uint16_t width; + uint16_t height; + uint16_t rowsize; + uint8_t type; + uint8_t byte_per_pixel; + uint8_t prev_tft_mode; + uint8_t loaded; +} tft_eve_obj_t; + //========================================================================================== // ==== Global variables =================================================================== //========================================================================================== + extern uint8_t orientation; // current screen orientation extern uint16_t font_rotate; // current font font_rotate angle (0~395) extern uint8_t font_transparent; // if not 0 draw fonts transparent @@ -67,6 +91,7 @@ extern uint8_t font_line_space; // additional spacing between text lines; adde extern uint8_t text_wrap; // if not 0 wrap long text to the new line, else clip extern color_t _fg; // current foreground color for fonts extern color_t _bg; // current background for non transparent fonts +extern uint8_t font_now; extern dispWin_t dispWin; // display clip window extern float _angleOffset; // angle offset for arc, polygon and line by angle functions extern uint8_t image_debug; // print debug messages during image decode if set to 1 @@ -75,9 +100,18 @@ extern Font cfont; // Current font structure extern int TFT_X; // X position of the next character after TFT_print() function extern int TFT_Y; // Y position of the next character after TFT_print() function +extern uint16_t image_width; +extern uint16_t image_hight; extern uint32_t tp_calx; // touch screen X calibration constant extern uint32_t tp_caly; // touch screen Y calibration constant + +extern uint8_t tft_active_mode; // used tft driver mode (TFT, EPD or EVE) + +#if CONFIG_MICROPY_USE_EVE +extern tft_eve_obj_t *eve_tft_obj; +#endif + // ========================================================================================= @@ -205,6 +239,7 @@ void TFT_drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel); //------------------------------------------ color_t TFT_readPixel(int16_t x, int16_t y); + /* * Draw vertical line at given x,y coordinates * @@ -628,6 +663,7 @@ int TFT_getStringWidth(char* str); /* * Fills the rectangle occupied by string with current background color */ +//------------------------------------------------ void TFT_clearStringRect(int x, int y, char *str); /* @@ -723,4 +759,10 @@ int compile_font_file(char *fontfile, uint8_t dbg); */ void getFontCharacters(uint8_t *buf); + +void led_pwm_init(); +void led_setBrightness(int duty); + +#endif + #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c index 9f82d576..d0c5157f 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c @@ -33,6 +33,10 @@ * */ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + #include #include "tftspi.h" #include "esp_system.h" @@ -81,27 +85,65 @@ uint8_t spibus_is_init = 0; #define GS_FACT_G 0.4870 #define GS_FACT_B 0.2140 +#ifdef CONFIG_MICROPY_USE_EPD + +static uint16_t xDot = 128; +static uint16_t yDot = 296; + +//static uint8_t GDOControl[] = {0x01, (_width-1)%256, (_width-1)/256, 0x00}; +static uint8_t softstart[4] = {0x0c, 0xd7, 0xd6, 0x9d}; +static uint8_t VCOMVol[2] = {0x2c, 0xa8}; // VCOM 7c +static uint8_t DummyLine[2] = {0x3a, 0x1a}; // 4 dummy line per gate +static uint8_t Gatetime[2] = {0x3b, 0x08}; // 2us per line +static uint8_t RamDataEntryMode[2] = {0x11, 0x01}; // Ram data entry mode +static uint8_t Border[2] = {0x3c, 0x61}; // Border control ( 0x61: white border; 0x51: black border + +/* +There are totally 20 phases for programmable Source waveform of different phase length. +The phase period defined as TP [n] * T FRAME , where TP [n] range from 0 to 15. +TP [n] = 0 indicates phase skipped +Source Voltage Level: VS [n-XY] is constant in each phase +VS [n-XY] indicates the voltage in phase n for transition from GS X to GS Y + 00 – VSS + 01 – VSH + 10 – VSL + 11 – NA +VS [n-XY] and TP[n] are stored in waveform lookup table register [LUT]. + +VS coding: VS[0-11] VS[0-10] VS[0-01] VS[0-00] + +*/ +// --- VS ---- ---- TP ---- +//uint8_t LUTDefault_full[31] = {0x32, 0x02,0x02,0x01,0x11,0x12,0x12,0x22,0x22,0x66,0x69,0x69,0x59,0x58,0x99,0x99,0x88,0x00,0x00,0x00,0x00, 0xF8,0xB4,0x13,0x51,0x35,0x51,0x51,0x19,0x01,0x00}; +uint8_t LUTDefault_full[31] = {0x32, 0x11,0x11,0x10,0x02,0x02,0x22,0x22,0x22,0x22,0x22,0x51,0x51,0x55,0x88,0x08,0x08,0x88,0x88,0x00,0x00, 0x34,0x23,0x12,0x21,0x24,0x28,0x22,0x21,0xA1,0x01}; +uint8_t LUTDefault_part[31] = {0x32, 0x10,0x18,0x18,0x08,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x13,0x14,0x44,0x12,0x00,0x00,0x00,0x00,0x00,0x00}; +uint8_t LUT_gs[31] = {0x32, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +uint8_t LUTFastest[31] = {0x32, 0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + +uint8_t lvl_buf[16] = {32,70,110,150,185,210,220,225,230,235,240,243,248,251,253,255}; +uint8_t lvl_buf_jpg[16] = {4,8,12,16,22,30,40,60,80,110,140,180,220,240,250,255}; +#endif // ==== Functions ===================== -//------------------------------- -esp_err_t IRAM_ATTR disp_select() +//--------------------- +esp_err_t disp_select() { //wait_trans_finish(1); return spi_device_select(disp_spi, 0); } -//--------------------------------- -esp_err_t IRAM_ATTR disp_deselect() +//----------------------- +esp_err_t disp_deselect() { //wait_trans_finish(1); return spi_device_deselect(disp_spi); } // Send command with data to display, display must be selected -//-------------------------------------------------------------------------------- -void IRAM_ATTR disp_spi_transfer_cmd_data(int8_t cmd, uint8_t *data, uint32_t len) +//---------------------------------------------------------------------- +void disp_spi_transfer_cmd_data(int8_t cmd, uint8_t *data, uint32_t len) { while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready @@ -150,8 +192,8 @@ void IRAM_ATTR disp_spi_transfer_cmd_data(int8_t cmd, uint8_t *data, uint32_t le } // Send 1 byte display command, display must be selected -//---------------------------------------------- -void IRAM_ATTR disp_spi_transfer_cmd(int8_t cmd) +//------------------------------------ +void disp_spi_transfer_cmd(int8_t cmd) { while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready @@ -163,8 +205,8 @@ void IRAM_ATTR disp_spi_transfer_cmd(int8_t cmd) } // Set the address window for display write & read commands, display must be selected -//--------------------------------------------------------------------------------------------------- -static void IRAM_ATTR disp_spi_transfer_addrwin(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2) { +//----------------------------------------------------------------------------------------- +static void disp_spi_transfer_addrwin(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2) { uint32_t wd; disp_spi_transfer_cmd(TFT_CASET); @@ -193,8 +235,8 @@ static void IRAM_ATTR disp_spi_transfer_addrwin(uint16_t x1, uint16_t x2, uint16 } // Convert color to gray scale -//---------------------------------------------- -static color_t IRAM_ATTR color2gs(color_t color) +//------------------------------------ +static color_t color2gs(color_t color) { color_t _color; float gs_clr = GS_FACT_R * color.r + GS_FACT_G * color.g + GS_FACT_B * color.b; @@ -208,8 +250,8 @@ static color_t IRAM_ATTR color2gs(color_t color) } // Convert color to 16-bit 565 RGB value -//---------------------------------------------- -static uint16_t IRAM_ATTR color16(color_t color) +//------------------------------------ +static uint16_t color16(color_t color) { uint16_t _color; _color = (uint16_t)(color.r & 0xF8) << 8; @@ -218,8 +260,8 @@ static uint16_t IRAM_ATTR color16(color_t color) return _color; } -//====================================================== -esp_err_t IRAM_ATTR wait_trans_finish(uint8_t free_line) +//============================================ +esp_err_t wait_trans_finish(uint8_t free_line) { _wait_trans_finish(disp_spi); @@ -231,8 +273,8 @@ esp_err_t IRAM_ATTR wait_trans_finish(uint8_t free_line) } // Set display pixel at given coordinates to given color -//======================================================================== -void IRAM_ATTR drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel) +//============================================================== +void drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel) { if ((sel) && (disp_select() != ESP_OK)) return; @@ -266,8 +308,8 @@ void IRAM_ATTR drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel) } // Send colors from color buffer directly, maximum of 512 bits -//--------------------------------------------------------------------------- -static void IRAM_ATTR _direct_send(color_t *color, uint32_t len, uint8_t rep) +//----------------------------------------------------------------- +static void _direct_send(color_t *color, uint32_t len, uint8_t rep) { uint32_t cidx = 0; // color buffer index uint32_t wd = 0; @@ -339,8 +381,8 @@ static void IRAM_ATTR _direct_send(color_t *color, uint32_t len, uint8_t rep) // If rep==false: send 'len' color data from color buffer to display // ** Device must already be selected and address window set ** // ================================================================== -//---------------------------------------------------------------------------------------------- -static void IRAM_ATTR _TFT_pushColorRep(color_t *color, uint32_t len, uint8_t rep, uint8_t wait) +//------------------------------------------------------------------------------------ +static void _TFT_pushColorRep(color_t *color, uint32_t len, uint8_t rep, uint8_t wait) { if (len == 0) return; @@ -428,8 +470,8 @@ static void IRAM_ATTR _TFT_pushColorRep(color_t *color, uint32_t len, uint8_t re } // Write 'len' color data to TFT 'window' (x1,y2),(x2,y2) -//========================================================================================== -void IRAM_ATTR TFT_pushColorRep(int x1, int y1, int x2, int y2, color_t color, uint32_t len) +//================================================================================ +void TFT_pushColorRep(int x1, int y1, int x2, int y2, color_t color, uint32_t len) { wait_trans_finish(1); if (disp_select() != ESP_OK) return; @@ -445,8 +487,8 @@ void IRAM_ATTR TFT_pushColorRep(int x1, int y1, int x2, int y2, color_t color, u // Write 'len' color data to TFT 'window' (x1,y2),(x2,y2) from given buffer // === Device must already be selected === -//================================================================================================ -void IRAM_ATTR send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t *buf, uint8_t wait) +//====================================================================================== +void send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t *buf, uint8_t wait) { wait_trans_finish(1); // ** Send address window ** @@ -456,8 +498,8 @@ void IRAM_ATTR send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t * _TFT_pushColorRep(buf, len, 0, wait); } -//=================================================== -uint32_t IRAM_ATTR read_cmd(uint8_t cmd, uint8_t len) +//========================================= +uint32_t read_cmd(uint8_t cmd, uint8_t len) { if (disp_select() != ESP_OK) return -2; @@ -482,8 +524,8 @@ uint32_t IRAM_ATTR read_cmd(uint8_t cmd, uint8_t len) // Reads 'len' pixels/colors from the TFT's GRAM 'window' // 'buf' is an array of bytes with 1st byte reserved for reading 1 dummy byte // and the rest is actually an array of color_t values -//============================================================================================ -int IRAM_ATTR read_data(int x1, int y1, int x2, int y2, int len, uint8_t *buf, uint8_t set_sp) +//================================================================================== +int read_data(int x1, int y1, int x2, int y2, int len, uint8_t *buf, uint8_t set_sp) { spi_transaction_t t; uint32_t current_clock = 0; @@ -524,8 +566,8 @@ int IRAM_ATTR read_data(int x1, int y1, int x2, int y2, int len, uint8_t *buf, u } // Reads one pixel/color from the TFT's GRAM at position (x,y) -//=============================================== -color_t IRAM_ATTR readPixel(int16_t x, int16_t y) +//===================================== +color_t readPixel(int16_t x, int16_t y) { uint8_t color_buf[sizeof(color_t)+1] = {0}; @@ -540,8 +582,8 @@ color_t IRAM_ATTR readPixel(int16_t x, int16_t y) // get 16-bit data from touch controller for specified type // ** Touch device must already be selected ** -//======================================== -int IRAM_ATTR touch_get_data(uint8_t type) +//============================== +int touch_get_data(uint8_t type) { /* while (ts_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready @@ -572,8 +614,8 @@ int IRAM_ATTR touch_get_data(uint8_t type) // ----- STMPE610 -------------------------------------------------------------------------- -//---------------------------------------------------------------- -static void IRAM_ATTR stmpe610_write_reg(uint8_t reg, uint8_t val) +//------------------------------------------------------ +static void stmpe610_write_reg(uint8_t reg, uint8_t val) { spi_device_select(ts_spi, 0); ts_spi->handle->host->hw->data_buf[0] = (val << 8) | reg; @@ -582,8 +624,8 @@ static void IRAM_ATTR stmpe610_write_reg(uint8_t reg, uint8_t val) spi_device_deselect(ts_spi); } -//------------------------------------------------------ -static uint8_t IRAM_ATTR stmpe610_read_byte(uint8_t reg) +//-------------------------------------------- +static uint8_t stmpe610_read_byte(uint8_t reg) { spi_device_select(ts_spi, 0); ts_spi->handle->host->hw->data_buf[0] = (reg << 8) | (reg | 0x80); @@ -594,8 +636,8 @@ static uint8_t IRAM_ATTR stmpe610_read_byte(uint8_t reg) return res; } -//------------------------------------------------------- -static uint16_t IRAM_ATTR stmpe610_read_word(uint8_t reg) +//--------------------------------------------- +static uint16_t stmpe610_read_word(uint8_t reg) { spi_device_select(ts_spi, 0); ts_spi->handle->host->hw->data_buf[0] = ((((reg+1) << 8) | ((reg+1) | 0x80)) << 16) | (reg << 8) | (reg | 0x80); @@ -1243,4 +1285,5 @@ esp_err_t TFT_display_init(display_config_t *dconfig) return ESP_OK; } +#endif // CONFIG_MICROPY_USE_TFT diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h index a841999b..960d4df4 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h @@ -32,11 +32,12 @@ #ifndef _TFTSPI_H_ #define _TFTSPI_H_ -#include "tftspi.h" -//#include "driver/spi_master.h" -//#include "driver/spi_master_internal.h" -#include "driver/spi_master_utils.h" #include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + + +#include "driver/spi_master_utils.h" #include "stmpe610.h" typedef struct { @@ -104,7 +105,7 @@ typedef struct __attribute__((__packed__)) { #define DEFAULT_TFT_DISPLAY_HEIGHT 320 #define DEFAULT_DISP_TYPE DISP_TYPE_ILI9341 - +/* #define WROVER_V3_CONFIG() {\ .type = DISP_TYPE_ST7789V, \ .host = HSPI_HOST, \ @@ -170,7 +171,7 @@ typedef struct __attribute__((__packed__)) { .bgr = 8, \ .touch = TOUCH_TYPE_NONE \ } - +*/ // ############################################################## // #### Global variables #### @@ -622,4 +623,6 @@ uint32_t stmpe610_getID(); // =============================================================================== +#endif // CONFIG_MICROPY_USE_TFT + #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/m5ui.c b/MicroPython_BUILD/components/micropython/esp32/m5ui.c new file mode 100644 index 00000000..081988d7 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/m5ui.c @@ -0,0 +1,69 @@ +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "rom/ets_sys.h" +#include "esp_system.h" +#include "esp_task_wdt.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" + +#include "m5ui.h" + +color_t ui_bg_color; + +STATIC mp_obj_t m5ui_set_bg_color(mp_obj_t bg_color_in){ + uint32_t cint = mp_obj_get_int(bg_color_in); + + ui_bg_color.r = (cint >> 16) & 0xFF; + ui_bg_color.g = (cint >> 8) & 0xFF; + ui_bg_color.b = cint & 0xFF; + TFT_fillScreen(ui_bg_color); + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_1(m5ui_set_bg_color_obj, m5ui_set_bg_color); + +extern mp_obj_t m5ui_circle_deinit(); +extern mp_obj_t m5ui_rect_deinit(); +extern mp_obj_t m5ui_text_deinit(); + +STATIC mp_obj_t m5ui_deinit(){ + m5ui_text_deinit(); + m5ui_rect_deinit(); + m5ui_circle_deinit(); + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_0(m5ui_deinit_obj, m5ui_deinit); + +STATIC const mp_rom_map_elem_t m5ui_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_clear_bg), (mp_obj_t)&m5ui_set_bg_color_obj}, + { MP_ROM_QSTR(MP_QSTR_M5UI_Deinit), (mp_obj_t)&m5ui_deinit_obj}, + + { MP_OBJ_NEW_QSTR(MP_QSTR_M5Rect), MP_ROM_PTR(&m5ui_rect_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_M5Circle), MP_ROM_PTR(&m5ui_circle_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_M5Title), MP_ROM_PTR(&m5ui_title_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_M5TextBox), MP_ROM_PTR(&m5ui_text_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_M5Button), MP_ROM_PTR(&m5ui_button_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_M5Img), MP_ROM_PTR(&m5ui_img_type) }, + +}; + +STATIC MP_DEFINE_CONST_DICT(m5ui_module_globals, m5ui_module_globals_table); + +//=============================================== +const mp_obj_module_t mp_module_um5ui = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&m5ui_module_globals, +}; +#endif \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/m5ui.h b/MicroPython_BUILD/components/micropython/esp32/m5ui.h new file mode 100644 index 00000000..fc5bcbbb --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/m5ui.h @@ -0,0 +1,19 @@ +#ifndef M5UI_H +#define M5UI_H +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include "py/obj.h" + +#endif + +extern color_t ui_bg_color; +extern const mp_obj_type_t m5ui_rect_type; +extern const mp_obj_type_t m5ui_circle_type; +extern const mp_obj_type_t m5ui_title_type; +extern const mp_obj_type_t m5ui_text_type; +extern const mp_obj_type_t m5ui_button_type; +extern const mp_obj_type_t m5ui_img_type; + +#endif \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_adc.c b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c index 331e77e9..fbaf186b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_adc.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c @@ -3,7 +3,6 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Nick Moore * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -27,80 +26,532 @@ #include +#include +#include -#include "esp_log.h" - +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "driver/gpio.h" #include "driver/adc.h" +#include "driver/timer.h" +#include "driver/i2s.h" #include "esp_adc_cal.h" #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" +#include "esp_log.h" #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" +#include "py/objarray.h" +#include "extmod/vfs_native.h" #define ADC1_CHANNEL_HALL ADC1_CHANNEL_MAX +#define I2S_RD_BUF_SIZE (1024*2) typedef struct _madc_obj_t { mp_obj_base_t base; int gpio_id; - adc1_channel_t adc1_id; + adc_unit_t adc_num; + adc1_channel_t adc_chan; adc_atten_t atten; adc_bits_width_t width; + mp_obj_t callback; + void *buffer; + FILE *fhndl; + uint8_t val_shift; + size_t buf_len; + size_t buf_ptr; + int64_t interval; + int64_t summ; + int64_t rms_summ; + int min; + int max; + uint8_t cal_read; } madc_obj_t; -static uint16_t adc_chan_used = 0; +extern int MainTaskCore; + +bool adc_timer_active = false; +bool collect_active = false; +intr_handle_t adc_timer_handle = NULL; + +static uint16_t adc1_chan_used = 0; +static uint16_t adc2_chan_used = 0; static int8_t adc_width = -1; +static int8_t last_adc_width = -1; +static int8_t last_adc_num = -1; static uint32_t adc_vref = 1100; +static uint32_t last_adc_vref = 0; +static adc_atten_t last_atten = ADC_ATTEN_MAX; +static adc_atten_t last_atten2 = ADC_ATTEN_MAX; +static esp_adc_cal_characteristics_t characteristics; +static uint64_t collect_start_time = 0; +static uint64_t collect_end_time = 0; +static bool task_running = false; +static bool task_stop = false; + +static const uint8_t adc1_gpios[ADC1_CHANNEL_MAX] = {36, 37, 38, 39, 32, 33, 34, 35}; +static const uint8_t adc2_gpios[ADC2_CHANNEL_MAX] = {4, 0, 2, 15, 13, 12, 14, 27, 25, 26}; + + +//------------------------------------- +static void set_width(madc_obj_t *self) +{ + if (adc_width != self->width) { + if (self->adc_num == ADC_UNIT_1) { + esp_err_t err = adc1_config_width(self->width); + if (err != ESP_OK) mp_raise_ValueError("Set width Error"); + } + else { + adc_set_data_width(self->adc_num, self->width); + } + adc_width = self->width; + } +} + +//----------------------------------------------------- +static int get_adc_channel(adc_unit_t adc_num, int pin) +{ + int channel = -1; + if (adc_num == ADC_UNIT_1) { + for (int i=0; i < ADC1_CHANNEL_MAX; i++) { + if (adc1_gpios[i] == pin) { + channel = i; + break; + } + } + } + else { + for (int i=0; i < ADC2_CHANNEL_MAX; i++) { + if (adc2_gpios[i] == pin) { + channel = i; + break; + } + } + } + return channel; +} + +//====================================== +static void adc_task(void *pvParameters) +{ + task_running = true; + madc_obj_t *self = (madc_obj_t *)pvParameters; + uint8_t *buff8 = NULL; + uint16_t *buff16 = NULL; + //char* i2s_read_buff = NULL; + uint16_t *i2s_read_buff = NULL; + int arr_idx = 0; + size_t bytes_read; + //ESP_LOGE("ADC", "To file: %s, len=%d, shift=%d", self->fhndl ? "True" : "False", self->buf_len, self->val_shift); + + if (self->fhndl) { + // Allocate temporary data buffer + if (self->val_shift) buff8 = malloc(I2S_RD_BUF_SIZE/2); + else buff16 = malloc(I2S_RD_BUF_SIZE); + if ((buff8 == NULL) && (buff16 == NULL)) { + fclose(self->fhndl); + ESP_LOGE("ADC", "Error allocating adc buffer"); + goto exit; + } + } + else { + if (self->val_shift) buff8 = (uint8_t *)self->buffer; + else buff16 = (uint16_t *)self->buffer; + } + // allocate i2s read buffer + i2s_read_buff = calloc(I2S_RD_BUF_SIZE, 1); + if (i2s_read_buff == NULL) { + if (self->fhndl) { + fclose(self->fhndl); + if (buff8) free(buff8); + if (buff16) free(buff16); + } + ESP_LOGE("ADC", "Error allocating i2s read buffer"); + goto exit; + } + + self->buf_ptr = 0; + collect_start_time = esp_timer_get_time(); //mp_hal_ticks_us(); + collect_end_time = collect_start_time; + // read ADC data + while (self->buf_ptr < self->buf_len) { + // read data from I2S bus, in this case, from ADC. + i2s_read(0, (void *)i2s_read_buff, I2S_RD_BUF_SIZE, &bytes_read, 1000); + if (bytes_read != I2S_RD_BUF_SIZE) { + ESP_LOGE("ADC", "I2S error reading (%d)", bytes_read); + break; + } + // save read ADC values to the output buffer + for (int i=0; i<(I2S_RD_BUF_SIZE/2); i++) { + if (self->buf_ptr < self->buf_len) { + uint16_t val = i2s_read_buff[i] & 0x0fff; + if (self->val_shift) buff8[arr_idx++] = (uint8_t)(val >> self->val_shift); + else buff16[arr_idx++] = val; + self->buf_ptr++; + } + } + if ( (self->fhndl) && ( (arr_idx >= (I2S_RD_BUF_SIZE/2)) || (self->buf_ptr < self->buf_len) ) ) { + // save buffer to file + int res; + if (self->val_shift) res = fwrite(buff8, 1, arr_idx, self->fhndl); + else res = fwrite(buff16, 2, arr_idx, self->fhndl); + if (res != arr_idx) { + ESP_LOGE("ADC", "Error writing to file at %d", arr_idx); + break; + } + arr_idx = 0; + } + //#if CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 || CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 + //vTaskDelay(0); // allow other core idle task to reset the watchdog + //#endif + } + collect_end_time = esp_timer_get_time(); //mp_hal_ticks_us(); + + if (self->fhndl) { + // reading to file, close file and free the buffer + fclose(self->fhndl); + self->fhndl = NULL; + if (buff8) free(buff8); + if (buff16) free(buff16); + } + + if (self->callback) mp_sched_schedule(self->callback, self, NULL); -//---------------------------------------------------------------------------------------------------------- -STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - esp_err_t err = 0; +exit: + // i2s cleanup + i2s_adc_disable(0); + i2s_driver_uninstall(0); + i2s_driver_installed = false; + if (i2s_read_buff) free(i2s_read_buff); + + esp_log_level_set("I2S", CONFIG_LOG_DEFAULT_LEVEL); + task_stop = false; + task_running = false; + + vTaskDelete(NULL); +} + +//====================================== +// ADC Timer interrupt function +//====================================== +STATIC void adc_timer_isr(void *self_in) +{ + madc_obj_t *self = (madc_obj_t *)self_in; + + // Clear timer interrupt + if (ADC_TIMER_NUM & 2) { + if (ADC_TIMER_NUM & 1) TIMERG1.int_clr_timers.t1 = 1; + else TIMERG1.int_clr_timers.t0 = 1; + } + else { + if (ADC_TIMER_NUM & 1) TIMERG0.int_clr_timers.t1 = 1; + else TIMERG0.int_clr_timers.t0 = 1; + } + + uint16_t *buffer16 = (uint16_t *)self->buffer; + uint8_t *buffer8 = (uint8_t *)self->buffer; + + if (self->buf_ptr == 0) collect_start_time = esp_timer_get_time(); //mp_hal_ticks_us(); + + // --- Read ADC value --- + int val = 0; + esp_err_t err = ESP_OK; + if (self->cal_read) { + err = esp_adc_cal_get_voltage(self->adc_chan, &characteristics, (uint32_t *)&val); + } + else { + if (self->adc_num == ADC_UNIT_1) { + val = adc1_get_raw(self->adc_chan); + if (val == -1) err = ESP_FAIL; + } + else err = adc2_get_raw(self->adc_chan, self->atten, &val); //if (err != ESP_OK) : Cannot read, ADC2 used by Wi-Fi" + } + + // --- Calculate values & save to buffer if provided --- + if (err == ESP_OK) { + if (self->buf_ptr < self->buf_len) { + if (self->buffer) { + // store value in buffer + if (self->val_shift == 0) buffer16[self->buf_ptr] = (uint16_t)val; + else { + if (self->cal_read) { + // calibrated read (mV) converted to 8-bit value + if (val > 2500) buffer8[self->buf_ptr] = 255; + else buffer8[self->buf_ptr] = val / 10; + } + else buffer8[self->buf_ptr] = (uint8_t)(val >> self->val_shift); + } + } + self->buf_ptr++; + self->summ += val; + self->rms_summ += (val * val); + if (val < self->min) self->min = val; + if (val > self->max) self->max = val; + } + } + + if ((err != ESP_OK) || (self->buf_ptr >= self->buf_len)) { + // --- Finished, all data read or ADC read error --- + timer_disable_intr((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + timer_pause((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (adc_timer_handle) { + esp_intr_free(adc_timer_handle); + adc_timer_handle = NULL; + } + collect_end_time = esp_timer_get_time(); //mp_hal_ticks_us(); + if (self->callback) mp_sched_schedule(self->callback, self, NULL); + self->buffer = NULL; + adc_timer_active = false; + collect_active = false; + } + else { + // --- Not yet finished, enable alarm interrupt --- + if (ADC_TIMER_NUM & 2) TIMERG1.hw_timer[ADC_TIMER_NUM & 1].config.alarm_en = true; + else TIMERG0.hw_timer[ADC_TIMER_NUM & 1].config.alarm_en = true; + } +} + +// Initialize and start the timer for ADC data collection +//-------------------------------------------------------------- +STATIC esp_err_t start_adc_timer(madc_obj_t *adc_obj, bool wait) +{ + if (adc_timer_handle) { + esp_intr_free(adc_timer_handle); + adc_timer_handle = NULL; + } + + adc_obj->summ = 0; + adc_obj->rms_summ = 0; + adc_obj->min = 999999; + adc_obj->max = -999999; + collect_start_time = 0; + collect_end_time = 0; + + esp_err_t err = ESP_OK; + // Set width if needed + if (adc_width != adc_obj->width) { + if (adc_obj->adc_num == ADC_UNIT_1) err = adc1_config_width(adc_obj->width); + else err = adc_set_data_width(adc_obj->adc_num, adc_obj->width); + adc_width = adc_obj->width; + if (err != ESP_OK) return err; + } + if (adc_obj->adc_num == ADC_UNIT_2) { + if (last_atten2 != adc_obj->atten) { + err = adc2_config_channel_atten(adc_obj->adc_chan, adc_obj->atten); + last_atten2 = adc_obj->atten; + } + if (err != ESP_OK) return err; + } + if (adc_obj->cal_read) { + if ((last_adc_num != adc_obj->adc_num) || (last_adc_vref != adc_vref) || (last_atten != adc_obj->atten) || (last_adc_width != adc_obj->width)) { + // New characterization needed + esp_adc_cal_characterize(adc_obj->adc_num, adc_obj->atten, adc_obj->width, adc_vref, &characteristics); + adc_vref = characteristics.vref; + last_adc_vref = adc_vref; + last_atten = adc_obj->atten; + last_adc_width = adc_obj->width; + last_adc_num = adc_obj->adc_num; + } + } + + timer_config_t config; + config.counter_dir = TIMER_COUNT_UP; + config.intr_type = TIMER_INTR_LEVEL; + config.counter_en = TIMER_PAUSE; + config.alarm_en = TIMER_ALARM_EN; + config.auto_reload = true; + config.divider = ADC_TIMER_DIVIDER; + + err = timer_init((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, &config); + if (err != ESP_OK) return err; + + // Timer's counter will initially start from value below. + // Also, if auto_reload is set, this value will be automatically reload on alarm + + err = timer_set_counter_value((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, 0x00000000ULL); + if (err != ESP_OK) return err; + + // Configure the alarm value and the interrupt on alarm. + err = timer_set_alarm_value((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, adc_obj->interval); + if (err != ESP_OK) return err; + + // Enable timer interrupt + err = timer_enable_intr((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (err != ESP_OK) return err; + + // Register interrupt callback + err = timer_isr_register((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, adc_timer_isr, (void*)adc_obj, ESP_INTR_FLAG_LEVEL1, &adc_timer_handle); + if (err != ESP_OK) return err; + + // Start the timer + err = timer_start((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (err != ESP_OK) { + timer_pause((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (adc_timer_handle) { + esp_intr_free(adc_timer_handle); + adc_timer_handle = NULL; + } + return err; + } + + if (wait) { + while (collect_active) { + mp_hal_delay_ms(5); + } + } + return ESP_OK; +} + +//------------------------------------------------------------------------------------------------------------ +STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_pin, ARG_unit }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_unit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADC_UNIT_1}}, + }; + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + esp_err_t err = 0; mp_arg_check_num(n_args, n_kw, 1, 1, true); int pin_id = 0; - if (MP_OBJ_IS_INT(args[0])) pin_id = mp_obj_get_int(args[0]); - else pin_id = machine_pin_get_id(args[0]); + pin_id = machine_pin_get_gpio(args[ARG_pin].u_obj); - madc_obj_t *self = m_new_obj(madc_obj_t);; + madc_obj_t *self = m_new_obj(madc_obj_t); self->base.type = &machine_adc_type; - if ((pin_id != ADC1_CHANNEL_HALL) && ((pin_id < 32) || (pin_id > 39))) mp_raise_ValueError("invalid Pin for ADC"); + self->buffer = NULL; + self->buf_len = 0; + self->buf_ptr = 0; + self->interval = 0; + self->cal_read = 0; + self->callback = NULL; - self->atten = ADC_ATTEN_0db; + self->adc_num = args[ARG_unit].u_int; + if ((self->adc_num != 0) && (self->adc_num != ADC_UNIT_1) && (self->adc_num != ADC_UNIT_2)) { + mp_raise_ValueError("invalid ADC unit (1 and 2 allowed)"); + } + self->atten = ADC_ATTEN_DB_0; self->width = ADC_WIDTH_BIT_12; if (pin_id != ADC1_CHANNEL_HALL) { - if (pin_id > 35) self->adc1_id = ADC1_CHANNEL_0 + (pin_id-36); - else self->adc1_id = ADC1_CHANNEL_4 + (pin_id-32); - if ((adc_chan_used & 0x0100) && ((self->adc1_id == 36) || (self->adc1_id == 39))) mp_raise_ValueError("hall used, cannot use pins 36 & 39"); - adc_chan_used |= (1 << self->adc1_id); - self->gpio_id = pin_id; - self->gpio_id = pin_id; - err = adc1_config_channel_atten(self->adc1_id, ADC_ATTEN_0db); - if (err != ESP_OK) mp_raise_ValueError("Parameter Error"); + int channel = -1; + if (self->adc_num == 0) { + channel = get_adc_channel(ADC_UNIT_1, pin_id); + if (channel >= 0) self->adc_num = ADC_UNIT_1; + else { + channel = get_adc_channel(ADC_UNIT_2, pin_id); + if (channel >= 0) self->adc_num = ADC_UNIT_2; + } + } + else channel = get_adc_channel(self->adc_num, pin_id); + if (channel < 0) mp_raise_ValueError("invalid Pin for ADC"); + + self->adc_chan = channel; + self->gpio_id = pin_id; + + if (self->adc_num == ADC_UNIT_1) { + if ((adc1_chan_used & 0x0100) && ((pin_id == 36) || (pin_id == 39))) mp_raise_ValueError("hall used, cannot use pins 36 & 39"); + if (adc1_chan_used & (1 << self->adc_chan)) mp_raise_ValueError("pin already used for adc"); + adc1_chan_used |= (1 << self->adc_chan); + + err = adc_gpio_init(self->adc_num, self->adc_chan); + if (err != ESP_OK) mp_raise_ValueError("Error configuring ADC gpio"); + err = adc1_config_channel_atten(self->adc_chan, ADC_ATTEN_DB_0); + if (err != ESP_OK) mp_raise_ValueError("Error configuring attenuation"); + } + else { + if (adc2_chan_used & (1 << self->adc_chan)) mp_raise_ValueError("pin already used for adc"); + adc2_chan_used |= (1 << self->adc_chan); + + gpio_pad_select_gpio(self->gpio_id); + gpio_set_direction(self->gpio_id, GPIO_MODE_DISABLE); + gpio_set_pull_mode(self->gpio_id, GPIO_FLOATING); + + adc_gpio_init(self->adc_num, self->adc_chan); + if (err != ESP_OK) mp_raise_ValueError("Error configuring ADC gpio"); + if (last_atten2 != self->atten) { + adc2_config_channel_atten(self->adc_chan, self->atten); + last_atten2 = self->atten; + } + } } else { - if (adc_chan_used & 0x09) mp_raise_ValueError("adc on gpio 36 or 39 used"); - self->adc1_id = ADC1_CHANNEL_HALL; + self->adc_num = ADC_UNIT_1; + if (adc1_chan_used & 0x09) mp_raise_ValueError("adc on gpio 36 or 39 used"); + if (adc1_chan_used & 0x0100) mp_raise_ValueError("hall already used"); + adc1_chan_used |= 0x0100; + self->adc_chan = ADC1_CHANNEL_HALL; self->gpio_id = GPIO_NUM_MAX; } - if (adc_width != self->width) { - err = adc1_config_width(self->width); - if (err != ESP_OK) mp_raise_ValueError("Set width Error"); - adc_width = self->width; - } + set_width(self); return MP_OBJ_FROM_PTR(self); } +//------------------------------------------------------------ +static void _is_init(madc_obj_t *self, bool iflag, bool cflag) +{ + if ((iflag) && (self->gpio_id < 0)) { + mp_raise_ValueError("Not initialized"); + } + if ((cflag) && (collect_active | task_running)) { + mp_raise_ValueError("collecting data in progress"); + } + if ((cflag) && (adc_timer_active)) { + mp_raise_ValueError("ADC timer used by other module"); + } +} + +//------------------------------------------- +STATIC mp_obj_t madc_deinit(mp_obj_t self_in) +{ + madc_obj_t *self = self_in; + _is_init(self, false, true); + + if (self->gpio_id < 0) return mp_const_none; + + if (self->adc_num == ADC_UNIT_1) { + if (self->adc_chan == ADC1_CHANNEL_HALL) { + adc1_chan_used &= 0x00FF; + gpio_pad_select_gpio(36); + gpio_pad_select_gpio(39); + } + else { + adc1_chan_used &= (~(1 << self->adc_chan) & 0x1FF); + gpio_pad_select_gpio(self->gpio_id); + gpio_set_direction(self->gpio_id, GPIO_MODE_INPUT); + gpio_set_pull_mode(self->gpio_id, GPIO_FLOATING); + } + } + else { + adc2_chan_used &= (~(1 << self->adc_chan) & 0x3FF); + gpio_pad_select_gpio(self->gpio_id); + gpio_set_direction(self->gpio_id, GPIO_MODE_INPUT); + gpio_set_pull_mode(self->gpio_id, GPIO_FLOATING); + } + self->gpio_id = -1; + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(madc_deinit_obj, madc_deinit); + //--------------------------------------------------------------------------------------- STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { madc_obj_t *self = self_in; + + if (self->gpio_id < 0) { + mp_printf(print, "ADC( deinitialized )"); + return; + } + char satten[16]; char spin[8]; if (self->atten == ADC_ATTEN_DB_0) sprintf(satten, "0dB (1.1V)"); @@ -112,22 +563,30 @@ STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ if (self->gpio_id == GPIO_NUM_MAX) sprintf(spin, "HALL"); else sprintf(spin, "Pin(%u)", self->gpio_id); - mp_printf(print, "ADC(%s: width=%u bits, atten=%s, Vref=%u mV)", spin, self->width+9, satten, adc_vref); + mp_printf(print, "ADC(%s: unit=ADC%d, chan=%d, width=%u bits, atten=%s, Vref=%u mV)", spin, self->adc_num, self->adc_chan, self->width+9, satten, adc_vref); } //---------------------------------------------- STATIC mp_obj_t madc_readraw(mp_obj_t self_in) { madc_obj_t *self = self_in; - if (adc_width != self->width) { - esp_err_t err = adc1_config_width(self->width); - if (err != ESP_OK) mp_raise_ValueError("Set width Error"); - adc_width = self->width; - } + _is_init(self, true, true); int val = 0; - if (self->gpio_id == GPIO_NUM_MAX) val= hall_sensor_read(); - else val = adc1_get_raw(self->adc1_id); - if (val == -1) mp_raise_ValueError("Parameter Error"); + if (self->adc_num == ADC_UNIT_1) { + set_width(self); + + if (self->gpio_id == GPIO_NUM_MAX) val= hall_sensor_read(); + else val = adc1_get_raw(self->adc_chan); + if (val == -1) mp_raise_ValueError("Parameter Error (ADC raw read)"); + } + else { + if (last_atten2 != self->atten) { + adc2_config_channel_atten(self->adc_chan, self->atten); + last_atten2 = self->atten; + } + esp_err_t err = adc2_get_raw(self->adc_chan, self->atten, &val); + if (err != ESP_OK) mp_raise_ValueError("Cannot read, ADC2 used by Wi-Fi"); + } return MP_OBJ_NEW_SMALL_INT(val); } @@ -136,32 +595,57 @@ MP_DEFINE_CONST_FUN_OBJ_1(madc_readraw_obj, madc_readraw); //------------------------------------------- STATIC mp_obj_t madc_read(mp_obj_t self_in) { madc_obj_t *self = self_in; - esp_adc_cal_characteristics_t characteristics; - if (adc_width != self->width) { - esp_err_t err = adc1_config_width(self->width); - if (err != ESP_OK) mp_raise_ValueError("Set width Error"); - } + _is_init(self, true, true); - int val = 0; - if (self->gpio_id == GPIO_NUM_MAX) val= hall_sensor_read(); + set_width(self); + + int adc_val = 0; + if (self->gpio_id == GPIO_NUM_MAX) adc_val= hall_sensor_read(); else { - esp_adc_cal_get_characteristics(adc_vref, self->atten, self->width, &characteristics); - val = adc1_to_voltage(self->adc1_id, &characteristics); + if ((last_adc_num != self->adc_num) || (last_adc_vref != adc_vref) || (last_atten != self->atten) || (last_adc_width != self->width)) { + // New characterization needed + esp_adc_cal_characterize(self->adc_num, self->atten, self->width, adc_vref, &characteristics); + adc_vref = characteristics.vref; + last_adc_vref = adc_vref; + last_atten = self->atten; + last_adc_width = self->width; + last_adc_num = self->adc_num; + } + if ((self->adc_num == ADC_UNIT_2) && (last_atten2 != self->atten)) { + adc2_config_channel_atten(self->adc_chan, self->atten); + last_atten2 = self->atten; + } + esp_err_t err = esp_adc_cal_get_voltage(self->adc_chan, &characteristics, (uint32_t *)&adc_val); + if (err != ESP_OK) { + if (self->adc_num == ADC_UNIT_2) mp_raise_ValueError("Cannot read, ADC2 used by Wi-Fi"); + else mp_raise_ValueError("Error reading"); + } } - return MP_OBJ_NEW_SMALL_INT(val); + return MP_OBJ_NEW_SMALL_INT(adc_val); } MP_DEFINE_CONST_FUN_OBJ_1(madc_read_obj, madc_read); //--------------------------------------------------------------- STATIC mp_obj_t madc_atten(mp_obj_t self_in, mp_obj_t atten_in) { madc_obj_t *self = self_in; + _is_init(self, true, true); + if (self->gpio_id == GPIO_NUM_MAX) return mp_const_none; adc_atten_t atten = mp_obj_get_int(atten_in); if ((atten < ADC_ATTEN_DB_0) || (atten > ADC_ATTEN_DB_11)) mp_raise_ValueError("Unsupported atten value"); - esp_err_t err = adc1_config_channel_atten(self->adc1_id, atten); - if (err != ESP_OK) mp_raise_ValueError("Parameter Error"); + esp_err_t err; + if (self->adc_num == ADC_UNIT_1) { + err = adc1_config_channel_atten(self->adc_chan, atten); + if (err != ESP_OK) mp_raise_ValueError("Parameter Error (config attenuation)"); + } + else { + if (last_atten2 != atten) { + adc2_config_channel_atten(self->adc_chan, atten); + last_atten2 = self->atten; + } + } self->atten = atten; return mp_const_none; } @@ -169,10 +653,12 @@ MP_DEFINE_CONST_FUN_OBJ_2(madc_atten_obj, madc_atten); //--------------------------------------------------------------- STATIC mp_obj_t madc_width(mp_obj_t self_in, mp_obj_t width_in) { - madc_obj_t *self = self_in; + madc_obj_t *self = self_in; + _is_init(self, true, true); + if (self->gpio_id == GPIO_NUM_MAX) return mp_const_none; - adc_bits_width_t width = mp_obj_get_int(width_in); + adc_bits_width_t width = mp_obj_get_int(width_in); if ((width < ADC_WIDTH_9Bit) || (width > ADC_WIDTH_12Bit)) mp_raise_ValueError("Unsupported width value"); if (self) self->width = width; @@ -184,10 +670,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(madc_width_obj, madc_width); //----------------------------------------------------------------------------------------------- STATIC mp_obj_t madc_vref_togpio(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { const mp_arg_t allowed_args[] = { - { MP_QSTR_vref, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_vref_topin, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + { MP_QSTR_vref, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_vref_topin, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[0].u_int > 0) { @@ -197,50 +683,364 @@ STATIC mp_obj_t madc_vref_togpio(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ } uint32_t gpio = 0; if (args[1].u_int > 0) { - gpio = args[1].u_int; - if ((gpio < 25) || (gpio > 27)) mp_raise_ValueError("Only gpios 25,26,27 can be used"); + gpio = args[1].u_int; + if ((gpio < 25) || (gpio > 27)) mp_raise_ValueError("Only gpios 25,26,27 can be used"); - esp_err_t status = adc2_vref_to_gpio(gpio); - if (status != ESP_OK) mp_raise_ValueError("Error routing Vref to gpio"); + esp_err_t status = adc2_vref_to_gpio(gpio); + if (status != ESP_OK) mp_raise_ValueError("Error routing Vref to gpio"); } mp_obj_t tuple[2]; - tuple[0] = mp_obj_new_int(adc_vref); - tuple[1] = mp_obj_new_int(gpio); + tuple[0] = mp_obj_new_int(adc_vref); + if (gpio > 0) tuple[1] = mp_obj_new_int(gpio); + else tuple[1] = mp_const_false; return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(madc_vref_togpio_obj, 0, madc_vref_togpio); +// ==== Collect and i2s read functions ====================================================== + +//------------------------------------------------------------------------------------------- +STATIC mp_obj_t madc_collect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_freq, ARG_len, ARG_readmv, ARG_data, ARG_callback, ARG_wait }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_readmv, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + { MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + }; + + madc_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + _is_init(self, true, true); + + // Get arguments + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + adc_timer_active = true; + + if (mpy_timers_used[ADC_TIMER_NUM]) { + adc_timer_active = false; + mp_raise_ValueError("ADC timer used by Timer module!"); + } + + if (self->gpio_id == GPIO_NUM_MAX) { + adc_timer_active = false; + mp_raise_ValueError("collect for hall sensor not allowed"); + } + + double freq = mp_obj_get_float(args[ARG_freq].u_obj); + if ((freq < 0.001) || (freq > 18000.0)) { + mp_raise_ValueError("frequency out of range (0.001 - 18000 Hz)"); + } + double interv = (1.0 / freq) * ADC_TIMER_FREQ; + self->callback = NULL; + self->buffer = NULL; + self->buf_ptr = 0; + self->cal_read = args[ARG_readmv].u_bool; + self->buf_len = args[ARG_len].u_int; + self->interval = (int64_t)(round(interv)); + + if (args[ARG_callback].u_obj != mp_const_none) { + if ((!MP_OBJ_IS_FUN(args[ARG_callback].u_obj)) && (!MP_OBJ_IS_METH(args[ARG_callback].u_obj))) { + adc_timer_active = false; + mp_raise_ValueError("callback function expected"); + } + self->callback = args[ARG_callback].u_obj; + } + + if (args[ARG_data].u_obj != mp_const_none) { + // Collect to the provided array + if (!MP_OBJ_IS_TYPE(args[ARG_data].u_obj, &mp_type_array)) { + adc_timer_active = false; + mp_raise_ValueError("array argument expected"); + } + mp_obj_array_t * arr = (mp_obj_array_t *)MP_OBJ_TO_PTR(args[ARG_data].u_obj); + if ((arr->typecode == 'h') || (arr->typecode == 'H')) { + self->val_shift = 0; + } + else if (arr->typecode == 'B') { + self->val_shift = self->width + 1; + } + else { + adc_timer_active = false; + mp_raise_ValueError("array argument of type 'h', 'H' or 'B' expected"); + } + if (arr->len < 1) { + self->buf_len = 0; + adc_timer_active = false; + mp_raise_ValueError("array argument length must be >= 1"); + } + self->buffer = arr->items; + if (self->buf_len < 1) self->buf_len = arr->len; + else if (arr->len < self->buf_len) self->buf_len = arr->len; + } + else if (self->buf_len < 1) { + self->buf_len = 0; + adc_timer_active = false; + mp_raise_ValueError("length must be >= 1"); + } + + collect_active = true; + if (start_adc_timer(self, args[ARG_wait].u_bool) != ESP_OK) { + adc_timer_active = false; + collect_active = false; + mp_raise_ValueError("Error starting ADC timer"); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(madc_collect_obj, 0, madc_collect); + +//---------------------------------------------------------------------------------------------- +STATIC mp_obj_t madc_read_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_freq, ARG_len, ARG_byte, ARG_wait, ARG_callback }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_nsamples, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_byte, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + madc_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + _is_init(self, true, true); + + if (self->gpio_id == GPIO_NUM_MAX) { + mp_raise_ValueError("timed read for hall sensor not allowed"); + } + if (i2s_driver_installed) { + mp_raise_ValueError("Error: i2s used by other module"); + } + + // Get arguments + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + self->callback = NULL; + self->buffer = NULL; + self->buf_ptr = 0; + self->cal_read = false; + self->buf_len = 0; + self->interval = 0; + self->val_shift = 0; + + int freq = mp_obj_get_int(args[ARG_freq].u_obj); + if ((freq < 5000) || (freq > 500000)) { + mp_raise_ValueError("frequency out of range (5000 - 500000 Hz)"); + } + + if (args[ARG_callback].u_obj != mp_const_none) { + if ((!MP_OBJ_IS_FUN(args[ARG_callback].u_obj)) && (!MP_OBJ_IS_METH(args[ARG_callback].u_obj))) { + mp_raise_ValueError("callback function expected"); + } + self->callback = args[ARG_callback].u_obj; + } + + bool wait = args[ARG_wait].u_bool; + + size_t length = args[ARG_len].u_int; + + if (MP_OBJ_IS_STR(args[ARG_data].u_obj)) { + // reading to file + if (length < 1) { + mp_raise_ValueError("file length must be >= 1"); + } + const char *dac_file = NULL; + char fullname[128] = {'\0'}; + + dac_file = mp_obj_str_get_str(args[0].u_obj); + int res = physicalPath(dac_file, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + mp_raise_ValueError("Error resolving file name"); + } + self->fhndl = fopen(fullname, "wb"); + if (self->fhndl == NULL) { + mp_raise_ValueError("Error opening file"); + } + // Allocate temporary data buffer + if (args[ARG_byte].u_bool) { + self->val_shift = self->width + 1; + } + self->buf_len = length; + } + else if (MP_OBJ_IS_TYPE(args[ARG_data].u_obj, &mp_type_array)) { + // reading to array + mp_buffer_info_t src; + mp_get_buffer_raise(args[ARG_data].u_obj, &src, MP_BUFFER_WRITE); + + mp_obj_array_t * arr = (mp_obj_array_t *)MP_OBJ_TO_PTR(args[ARG_data].u_obj); + if ((arr->typecode == 'h') && (arr->typecode != 'H') && (arr->typecode != 'B')) { + mp_raise_ValueError("array argument of type 'h', 'H' or 'B' expected"); + } + if (arr->typecode == 'B') { + self->val_shift = self->width + 1; + } + self->buffer = arr->items; + + if (arr->len < 1) { + mp_raise_ValueError("array argument length must be >= 1"); + } + if ((length > 0) && (length < arr->len)) self->buf_len = length; + else self->buf_len = arr->len; + } + else { + mp_raise_ValueError("array or file name argument expected"); + } + + // configure i2s + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN, // Only RX, ADC input + //.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN, + .sample_rate = freq, + .bits_per_sample = 16, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, + .communication_format = I2S_COMM_FORMAT_I2S_MSB, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = false, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, + .fixed_mclk = 0 + }; + + // install and start i2s driver + i2s_driver_install(0, &i2s_config, 0, NULL); + i2s_driver_installed = true; + // init ADC pad + i2s_set_adc_mode(self->adc_num, self->adc_chan); + i2s_adc_enable(0); + //i2s_set_sample_rates(0, freq); + + task_stop = false; + esp_log_level_set("I2S", ESP_LOG_ERROR); + #if CONFIG_MICROPY_USE_BOTH_CORES + xTaskCreate(adc_task, "ADC_task", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, NULL); + #else + xTaskCreatePinnedToCore(adc_task, "ADC_task", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, NULL, MainTaskCore); + #endif + + if (wait) { + mp_hal_delay_ms(3); + while (task_running) { + mp_hal_delay_ms(3); + } + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(madc_read_timed_obj, 0, madc_read_timed); + +//---------------------------------------------------- +STATIC mp_obj_t madc_get_collected(mp_obj_t self_in) { + madc_obj_t *self = self_in; + _is_init(self, true, true); + + if (self->buf_len == 0) { + mp_raise_ValueError("no data collected"); + } + + // return statistics + int rms = self->rms_summ / self->buf_len; + int avrg = self->summ / self->buf_len; + double drms = sqrt((double)(rms)); + rms = (int)(round(drms)); + mp_obj_t tuple[4]; + tuple[0] = mp_obj_new_int(self->min); + tuple[1] = mp_obj_new_int(self->max); + tuple[2] = mp_obj_new_int(avrg); + tuple[3] = mp_obj_new_int(rms); + + return mp_obj_new_tuple(4, tuple); +} +MP_DEFINE_CONST_FUN_OBJ_1(madc_get_collected_obj, madc_get_collected); + +//----------------------------------------------- +STATIC mp_obj_t madc_progress(mp_obj_t self_in) { + madc_obj_t *self = self_in; + _is_init(self, true, false); + + bool active = collect_active | task_running; + mp_obj_t tuple[4]; + tuple[0] = mp_obj_new_bool(active); + tuple[1] = mp_obj_new_int(self->buf_ptr); + tuple[2] = mp_obj_new_int(self->buf_len); + if (active) tuple[3] = mp_obj_new_int_from_ull(esp_timer_get_time() /*mp_hal_ticks_us()*/ - collect_start_time); + else tuple[3] = mp_obj_new_int_from_ull(collect_end_time - collect_start_time); + + return mp_obj_new_tuple(4, tuple); +} +MP_DEFINE_CONST_FUN_OBJ_1(madc_progress_obj, madc_progress); + +//--------------------------------------------------- +STATIC mp_obj_t madc_stop_collect(mp_obj_t self_in) { + madc_obj_t *self = self_in; + _is_init(self, true, false); + + if (task_running) { + task_stop = true; + while (task_running) { + vTaskDelay(2); + } + } + if (collect_active) { + timer_disable_intr((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + timer_pause((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (adc_timer_handle) { + esp_intr_free(adc_timer_handle); + adc_timer_handle = NULL; + } + collect_end_time = esp_timer_get_time(); //mp_hal_ticks_us(); + self->buffer = NULL; + adc_timer_active = false; + collect_active = false; + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(madc_stop_collect_obj, madc_stop_collect); + + //========================================================= STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&madc_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readraw), MP_ROM_PTR(&madc_readraw_obj) }, - { MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&madc_atten_obj) }, - { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&madc_width_obj) }, - { MP_ROM_QSTR(MP_QSTR_vref), MP_ROM_PTR(&madc_vref_togpio_obj) }, - - { MP_ROM_QSTR(MP_QSTR_HALL), MP_ROM_INT(ADC1_CHANNEL_MAX) }, - - { MP_ROM_QSTR(MP_QSTR_ATTN_0DB), MP_ROM_INT(ADC_ATTEN_0db) }, - { MP_ROM_QSTR(MP_QSTR_ATTN_2_5DB), MP_ROM_INT(ADC_ATTEN_2_5db) }, - { MP_ROM_QSTR(MP_QSTR_ATTN_6DB), MP_ROM_INT(ADC_ATTEN_6db) }, - { MP_ROM_QSTR(MP_QSTR_ATTN_11DB), MP_ROM_INT(ADC_ATTEN_11db) }, - - { MP_ROM_QSTR(MP_QSTR_WIDTH_9BIT), MP_ROM_INT(ADC_WIDTH_9Bit) }, - { MP_ROM_QSTR(MP_QSTR_WIDTH_10BIT), MP_ROM_INT(ADC_WIDTH_10Bit) }, - { MP_ROM_QSTR(MP_QSTR_WIDTH_11BIT), MP_ROM_INT(ADC_WIDTH_11Bit) }, - { MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(ADC_WIDTH_12Bit) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&madc_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readraw), MP_ROM_PTR(&madc_readraw_obj) }, + { MP_ROM_QSTR(MP_QSTR_read_timed), MP_ROM_PTR(&madc_read_timed_obj) }, + { MP_ROM_QSTR(MP_QSTR_collect), MP_ROM_PTR(&madc_collect_obj) }, + { MP_ROM_QSTR(MP_QSTR_collected), MP_ROM_PTR(&madc_get_collected_obj) }, + { MP_ROM_QSTR(MP_QSTR_stopcollect), MP_ROM_PTR(&madc_stop_collect_obj) }, + { MP_ROM_QSTR(MP_QSTR_progress), MP_ROM_PTR(&madc_progress_obj) }, + { MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&madc_atten_obj) }, + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&madc_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_vref), MP_ROM_PTR(&madc_vref_togpio_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&madc_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_HALL), MP_ROM_INT(ADC1_CHANNEL_MAX) }, + + { MP_ROM_QSTR(MP_QSTR_ATTN_0DB), MP_ROM_INT(ADC_ATTEN_0db) }, + { MP_ROM_QSTR(MP_QSTR_ATTN_2_5DB), MP_ROM_INT(ADC_ATTEN_2_5db) }, + { MP_ROM_QSTR(MP_QSTR_ATTN_6DB), MP_ROM_INT(ADC_ATTEN_6db) }, + { MP_ROM_QSTR(MP_QSTR_ATTN_11DB), MP_ROM_INT(ADC_ATTEN_11db) }, + + { MP_ROM_QSTR(MP_QSTR_WIDTH_9BIT), MP_ROM_INT(ADC_WIDTH_9Bit) }, + { MP_ROM_QSTR(MP_QSTR_WIDTH_10BIT), MP_ROM_INT(ADC_WIDTH_10Bit) }, + { MP_ROM_QSTR(MP_QSTR_WIDTH_11BIT), MP_ROM_INT(ADC_WIDTH_11Bit) }, + { MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(ADC_WIDTH_12Bit) }, }; STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table); //====================================== const mp_obj_type_t machine_adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = madc_print, - .make_new = madc_make_new, - .locals_dict = (mp_obj_t)&madc_locals_dict, + { &mp_type_type }, + .name = MP_QSTR_ADC, + .print = madc_print, + .make_new = madc_make_new, + .locals_dict = (mp_obj_t)&madc_locals_dict, }; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_dac.c b/MicroPython_BUILD/components/micropython/esp32/machine_dac.c index bd0804ec..6c0af0fd 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_dac.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_dac.c @@ -1,9 +1,9 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) 2017 Nick Moore + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,72 +26,1066 @@ #include +#include +#include +#include -#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/i2s.h" #include "driver/gpio.h" #include "driver/dac.h" +#include "driver/timer.h" +#include "soc/rtc_io_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/sens_reg.h" +#include "soc/rtc.h" +#include "esp_task_wdt.h" +#include "esp_log.h" #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" +#include "py/objarray.h" +#include "extmod/vfs_native.h" + typedef struct _mdac_obj_t { mp_obj_base_t base; - gpio_num_t gpio_id; - dac_channel_t dac_id; + int gpio_id; + dac_channel_t dac_id; + uint8_t *buffer; + size_t buf_len; + size_t buf_ptr; + FILE *fhndl; + uint64_t timer_interval; + uint8_t dac_timer_mode; } mdac_obj_t; -STATIC const mdac_obj_t mdac_obj[] = { - {{&machine_dac_type}, GPIO_NUM_25, DAC_CHANNEL_1}, - {{&machine_dac_type}, GPIO_NUM_26, DAC_CHANNEL_2}, -}; +extern int MainTaskCore; + +static bool trepeat = false; +static bool task_running = false; +static bool task_stop = false; +static bool timer_stop = false; +static bool cosine_enabled = false; +static bool dac_i2s_driver_installed = false; +static bool dac_timer_active = false; +static intr_handle_t dac_timer_handle = NULL; + +// === ESP32 cosine generator functions === + +//------------------------------ +static void dac_cosine_disable() +{ + // Disable tone generator common to both channels + CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN); + + // Disable / disconnect tone tone generator + CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M); + CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M); + // Invert MSB, otherwise part of waveform will have inverted + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV1, 0, SENS_DAC_INV1_S); + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV2, 0, SENS_DAC_INV2_S); + + cosine_enabled = false; +} + +//-------------------------------------------------- +static void dac_cosine_enable(dac_channel_t channel) +{ + dac_cosine_disable(); + // Enable tone generator common to both channels + SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN); + switch(channel) { + case DAC_CHANNEL_1: + // Enable / connect tone tone generator on / to this channel + SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M); + // Invert MSB, otherwise part of waveform will have inverted + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV1, 2, SENS_DAC_INV1_S); + break; + case DAC_CHANNEL_2: + SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M); + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV2, 2, SENS_DAC_INV2_S); + break; + default: + break; + } + cosine_enabled = true; +} + +/* + * Set frequency of internal CW generator common to both DAC channels + * + * clk_8m_div: 0b000 - 0b111 + * frequency_step: range 0x0001 - 0xFFFF + * + */ +//--------------------------------------------------------------- +static void dac_frequency_set(int clk_8m_div, int frequency_step) +{ + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, clk_8m_div); + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL1_REG, SENS_SW_FSTEP, frequency_step, SENS_SW_FSTEP_S); +} + + +/* + * Scale output of a DAC channel using two bit pattern: + * + * - 00: no scale + * - 01: scale to 1/2 + * - 10: scale to 1/4 + * - 11: scale to 1/8 + * + */ +//--------------------------------------------------------- +static void dac_scale_set(dac_channel_t channel, int scale) +{ + switch(channel) { + case DAC_CHANNEL_1: + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_SCALE1, scale, SENS_DAC_SCALE1_S); + break; + case DAC_CHANNEL_2: + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_SCALE2, scale, SENS_DAC_SCALE2_S); + break; + default : + printf("Channel %d\n", channel); + } +} -STATIC mp_obj_t mdac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, - const mp_obj_t *args) { + +/* + * Offset output of a DAC channel + * + * Range 0x00 - 0xFF + * + */ +//----------------------------------------------------------- +static void dac_offset_set(dac_channel_t channel, int offset) +{ + switch(channel) { + case DAC_CHANNEL_1: + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_DC1, offset, SENS_DAC_DC1_S); + break; + case DAC_CHANNEL_2: + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_DC2, offset, SENS_DAC_DC2_S); + break; + default : + printf("Channel %d\n", channel); + } +} + + +/* + * Invert output pattern of a DAC channel + * + * - 00: does not invert any bits, + * - 01: inverts all bits, + * - 10: inverts MSB, + * - 11: inverts all bits except for MSB + * + */ +//----------------------------------------------------------- +static void dac_invert_set(dac_channel_t channel, int invert) +{ + switch(channel) { + case DAC_CHANNEL_1: + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV1, invert, SENS_DAC_INV1_S); + break; + case DAC_CHANNEL_2: + SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV2, invert, SENS_DAC_INV2_S); + break; + default : + printf("Channel %d\n", channel); + } +} + +// === DAC functions === + +//====================================== +static void dac_task(void *pvParameters) +{ + task_running = true; + mdac_obj_t *self = (mdac_obj_t *)pvParameters; + + int buf_idx = 0; + int write_size = self->buf_len; + if (write_size > 4096) write_size = 4096; + + size_t i2s_bytes_write; + while (true) { + if (task_stop) break; + if (buf_idx >= self->buf_len) break; + // write the buffer/file + while (buf_idx < self->buf_len) { + if (task_stop) break; + if (self->fhndl) { + // from file + write_size = fread(self->buffer, 1, write_size, self->fhndl); + if (write_size > 0) { + i2s_write(0, self->buffer, write_size, &i2s_bytes_write, 1000); + if (i2s_bytes_write != write_size) { + ESP_LOGE("DAC", "I2S error writing"); + task_stop = true; + break; + } + } + else { + ESP_LOGE("DAC", "error reading from file"); + task_stop = true; + break; + } + } + else { + // from buffer + i2s_write(0, self->buffer + buf_idx, write_size, &i2s_bytes_write, 1000); + if (i2s_bytes_write != write_size) { + ESP_LOGE("DAC", "I2S error writing"); + task_stop = true; + break; + } + } + buf_idx += write_size; + if (buf_idx >= self->buf_len) break; + write_size = self->buf_len - buf_idx; + if (write_size > 4096) write_size = 4096; + + //#if CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 || CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 + //vTaskDelay(0); // allow other core idle task to reset the watchdog + //#endif + } + if (trepeat == 0) break; + // Repeat writing from start of file/buffer + buf_idx = 0; + write_size = self->buf_len; + if (write_size > 4096) write_size = 4096; + if (self->fhndl) { + if (fseek(self->fhndl, 0, SEEK_SET) != 0) break; + } + } + + if (self->fhndl) { + fclose(self->fhndl); + free(self->buffer); + } + i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE); + i2s_stop(0); + i2s_driver_uninstall(0); + dac_i2s_driver_installed = false; + i2s_driver_installed = false; + dac_i2s_disable(); + dac_output_enable(self->dac_id); + dac_output_voltage(self->dac_id, 128); + + esp_log_level_set("I2S", CONFIG_LOG_DEFAULT_LEVEL); + task_stop = false; + task_running = false; + + vTaskDelete(NULL); +} + +//-------------------------------------- +STATIC void dac_timer_isr(void *self_in) +{ + mdac_obj_t *self = (mdac_obj_t *)self_in; + + // Clear timer interrupt + if (ADC_TIMER_NUM & 2) { + if (ADC_TIMER_NUM & 1) TIMERG1.int_clr_timers.t1 = 1; + else TIMERG1.int_clr_timers.t0 = 1; + } + else { + if (ADC_TIMER_NUM & 1) TIMERG0.int_clr_timers.t1 = 1; + else TIMERG0.int_clr_timers.t0 = 1; + } + + if (self->dac_timer_mode == 1) { + // Generate random noise + uint32_t rnd = esp_random(); + rnd = ((rnd & 0xff) ^ ((rnd >> 8) & 0xff) ^ ((rnd >> 16) & 0xff) ^ ((rnd >> 24) & 0xff)); + //rnd = ((rnd & 0xff) + ((rnd >> 8) & 0xff) + ((rnd >> 16) & 0xff) + ((rnd >> 24) & 0xff)); + dac_output_voltage(self->dac_id, (uint8_t)rnd); + } + else if (self->dac_timer_mode == 2) { + // Output DAC values from buffer + dac_output_voltage(self->dac_id, self->buffer[self->buf_ptr]); + self->buf_ptr++; + if (self->buf_ptr >= self->buf_len) { + if (trepeat) self->buf_ptr = 0; + else timer_stop = true; + } + } + else timer_stop = true; + + if (timer_stop) { + // --- Finished, all data read or ADC read error --- + timer_disable_intr((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + timer_pause((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (dac_timer_handle) { + esp_intr_free(dac_timer_handle); + dac_timer_handle = NULL; + } + adc_timer_active = false; + dac_timer_active = false; + timer_stop = false; + } + else { + // --- Not yet finished, enable alarm interrupt --- + if (ADC_TIMER_NUM & 2) TIMERG1.hw_timer[ADC_TIMER_NUM & 1].config.alarm_en = true; + else TIMERG0.hw_timer[ADC_TIMER_NUM & 1].config.alarm_en = true; + } +} + +//------------------------------------------------ +STATIC esp_err_t start_dac_timer(mdac_obj_t *self) +{ + if (dac_timer_handle) { + esp_intr_free(dac_timer_handle); + dac_timer_handle = NULL; + } + + timer_config_t config; + config.counter_dir = TIMER_COUNT_UP; + config.intr_type = TIMER_INTR_LEVEL; + config.counter_en = TIMER_PAUSE; + config.alarm_en = TIMER_ALARM_EN; + config.auto_reload = true; + config.divider = ADC_TIMER_DIVIDER; // 1 MHz + + esp_err_t err = timer_init((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, &config); + if (err != ESP_OK) return -1; + + // Timer's counter will initially start from value below. + // Also, if auto_reload is set, this value will be automatically reload on alarm + + err = timer_set_counter_value((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, 0x00000000ULL); + if (err != ESP_OK) return -2; + + // Configure the alarm value and the interrupt on alarm. + err = timer_set_alarm_value((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, self->timer_interval); + if (err != ESP_OK) return -3; + + // Enable timer interrupt + err = timer_enable_intr((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (err != ESP_OK) return -4; + + // Register interrupt callback + err = timer_isr_register((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1, dac_timer_isr, (void*)self, 0, &dac_timer_handle); + if (err != ESP_OK) return -5; + + // Start the timer + err = timer_start((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (err != ESP_OK) { + timer_pause((ADC_TIMER_NUM >> 1) & 1, ADC_TIMER_NUM & 1); + if (dac_timer_handle) { + esp_intr_free(dac_timer_handle); + dac_timer_handle = NULL; + } + return -6; + } + return ESP_OK; +} + + +//----------------------------------------- +static void dac_func_stop(mdac_obj_t *self) +{ + if (dac_timer_active) { + timer_stop = true; + while (dac_timer_active) { + vTaskDelay(2); + } + } + if (cosine_enabled) dac_cosine_disable(); + if (task_running) { + task_stop = true; + while (task_running) { + vTaskDelay(2); + } + } + if (dac_i2s_driver_installed) { + i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE); + i2s_stop(0); + i2s_driver_uninstall(0); + dac_i2s_driver_installed = false; + i2s_driver_installed = false; + dac_i2s_disable(); + dac_output_enable(self->dac_id); + dac_output_voltage(self->dac_id, 128); + } +} + +//------------------------------------------------------------ +static void _is_init(mdac_obj_t *self, bool iflag, bool cflag) +{ + if ((iflag) && (self->gpio_id < 0)) { + mp_raise_ValueError("Not initialized"); + } + if ((cflag) && ((task_running) || (dac_i2s_driver_installed) || (cosine_enabled) || (dac_timer_active))) { + mp_raise_ValueError("timed write or waveform in progress"); + } +} + +//------------------------------------------ +static bool gen_waveform(int type, int freq) +{ + if ((type < 1) || (type > 3)) return false; + + size_t i2s_bytes_write; + int j = 0; + int buflen = 1024; + int nsamples = 256; + + if (type == 1) { + nsamples *= 2; + buflen *= 2; + } + else freq = freq / 2; + + uint8_t *samples_data = malloc(buflen); + if (samples_data == NULL) return false; + + if (type == 1) { + // triangle wave + for (int i = 0; ibase.type = &machine_dac_type; + self->gpio_id = pin_id; + if (pin_id == 25) self->dac_id = DAC_CHANNEL_1; + else self->dac_id = DAC_CHANNEL_2; + self->buffer = NULL; + self->buf_len = 0; + self->fhndl = NULL; + + dac_i2s_disable(); esp_err_t err = dac_output_enable(self->dac_id); if (err == ESP_OK) { err = dac_output_voltage(self->dac_id, 0); } - if (err == ESP_OK) return MP_OBJ_FROM_PTR(self); - mp_raise_ValueError("Parameter Error"); + if (err != ESP_OK) mp_raise_ValueError("DAC Parameter Error"); + return MP_OBJ_FROM_PTR(self); } +//--------------------------------------------------------------------------------------- STATIC void mdac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mdac_obj_t *self = self_in; - mp_printf(print, "DAC(Pin(%u))", self->gpio_id); + + if (self->gpio_id < 0) { + mp_printf(print, "DAC( deinitialized )"); + return; + } + mp_printf(print, "DAC(Pin(%u), channel: %d)", self->gpio_id, self->dac_id); } +//--------------------------------------------------------------- STATIC mp_obj_t mdac_write(mp_obj_t self_in, mp_obj_t value_in) { mdac_obj_t *self = self_in; + _is_init(self, true, true); + int value = mp_obj_get_int(value_in); if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); esp_err_t err = dac_output_voltage(self->dac_id, value); - if (err == ESP_OK) return mp_const_none; - mp_raise_ValueError("Parameter Error"); + if (err != ESP_OK) mp_raise_ValueError("Parameter Error"); + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(mdac_write_obj, mdac_write); + +//-------------------------------------------------------------------------------------------- +STATIC mp_obj_t mdac_waveform(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_freq, ARG_type, ARG_duration, ARG_scale, ARG_offset, ARG_invert, ARG_len }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 1000} }, + { MP_QSTR_type, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_duration, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_scale, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 2}}, + }; + + mdac_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + _is_init(self, true, false); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + dac_func_stop(self); + + int type = args[ARG_type].u_int; + int freq = args[ARG_freq].u_int; + if (type < 0 || type > 4) mp_raise_ValueError("Unknown function type"); + + if (type == 0) { + // --- sine generator using ESP32 hw cosine generator --- + // freq = 8000000 x frequency_step / 65536 + // frequency_step = (freq * 65536) / 8000000 + if (freq < 16 || freq > 32000) mp_raise_ValueError("Frequency out of range (16-32000 Hz)"); + uint64_t fs = freq * 65536; + int fdiv = 1; + if (freq < 256) fdiv = 4; + if (freq < 64) fdiv = 8; + fs /= (8000000 / fdiv); + dac_frequency_set((fdiv-1), (int)fs); + dac_scale_set(self->dac_id, args[ARG_scale].u_int & 3); + dac_offset_set(self->dac_id, (int8_t)args[ARG_offset].u_int); + dac_invert_set(self->dac_id, args[ARG_invert].u_int & 3); + dac_cosine_enable(self->dac_id); + + goto exit; + } + + if (type == 4) { + // Noise + if ((mpy_timers_used[ADC_TIMER_NUM]) || (adc_timer_active)) { + mp_raise_ValueError("DAC timer used by other module!"); + } + adc_timer_active = true; + dac_timer_active = true; + self->dac_timer_mode = 1; + timer_stop = false; + if (freq < 500 || freq > 32000) mp_raise_ValueError("Frequency out of range (500-32000 Hz)"); + self->timer_interval = (int)ADC_TIMER_FREQ / freq; + int err = start_dac_timer(self) != ESP_OK; + if (err) { + ESP_LOGE("DAC", "Error starting DAC timer (%d)", err); + } + goto exit; + } + + // --- For other waveforms we use I2S peripheral to generate the waveform --- + if ((!dac_i2s_driver_installed) && (i2s_driver_installed)) { + mp_raise_ValueError("Error: i2s used by other module"); + } + + if ((type == 1) && (freq < 170 || freq > 3600)) mp_raise_ValueError("Frequency out of range (170 - 3600 Hz)"); + else if ((freq < 170 || freq > 7200)) mp_raise_ValueError("Frequency out of range (170 - 7200 Hz)"); + + i2s_config_t i2s_config = { + //.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, // Only TX, DAC output + .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN, + .sample_rate = freq * 64, + .bits_per_sample = 16, + .channel_format = (self->dac_id == DAC_CHANNEL_1) ? I2S_CHANNEL_FMT_ALL_RIGHT : I2S_CHANNEL_FMT_ALL_LEFT, + .communication_format = I2S_COMM_FORMAT_I2S_MSB, + .dma_buf_count = 2, + .dma_buf_len = 256, + .use_apll = true, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, //Interrupt level 1 + .fixed_mclk = 0 + }; + //install and start i2s driver + i2s_driver_install(0, &i2s_config, 0, NULL); + i2s_driver_installed = true; + dac_i2s_driver_installed = true; + //init DAC pad + i2s_set_dac_mode((self->dac_id == DAC_CHANNEL_1) ? I2S_DAC_CHANNEL_RIGHT_EN : I2S_DAC_CHANNEL_LEFT_EN); + //i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); + + // start the wave + if (!gen_waveform(type, freq)) { + i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE); + i2s_stop(0); + i2s_driver_uninstall(0); + dac_i2s_driver_installed = false; + i2s_driver_installed = false; + dac_i2s_disable(); + dac_output_enable(self->dac_id); + dac_output_voltage(self->dac_id, 128); + mp_raise_ValueError("Error allocating wave buffer"); + } + +exit: + if (args[ARG_duration].u_int > 0) { + mp_hal_delay_ms(args[ARG_duration].u_int); + dac_func_stop(self); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdac_waveform_obj, 0, mdac_waveform); + +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t mdac_write_buffer(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_freq, ARG_mode, ARG_wait }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_freq, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + }; + + mdac_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + _is_init(self, true, false); + + dac_func_stop(self); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + double freq = mp_obj_get_float(args[ARG_freq].u_obj); + if ((freq < 0.001) || (freq > 18000.0)) { + mp_raise_ValueError("frequency out of range (0.001 - 18000 Hz)"); + } + double interv = (1.0 / freq) * ADC_TIMER_FREQ; + + // Get arguments + bool wait = false; + trepeat = args[ARG_mode].u_bool; + // only wait if if not continuous mode + if (!trepeat) wait = args[ARG_wait].u_bool; + + adc_timer_active = true; + dac_timer_active = true; + self->buffer = NULL; + self->buf_len = 0; + self->buf_ptr = 0; + + if (args[ARG_data].u_obj != mp_const_none) { + // Play from the provided array + if (!MP_OBJ_IS_TYPE(args[ARG_data].u_obj, &mp_type_array)) { + adc_timer_active = false; + dac_timer_active = false; + mp_raise_ValueError("array argument expected"); + } + mp_obj_array_t * arr = (mp_obj_array_t *)MP_OBJ_TO_PTR(args[ARG_data].u_obj); + if (arr->typecode != 'B') { + adc_timer_active = false; + dac_timer_active = false; + mp_raise_ValueError("array argument of type 'B' expected"); + } + if (arr->len < 1) { + self->buf_len = 0; + adc_timer_active = false; + dac_timer_active = false; + mp_raise_ValueError("array argument length must be >= 1"); + } + self->buffer = arr->items; + if (self->buf_len < 1) self->buf_len = arr->len; + else if (arr->len < self->buf_len) self->buf_len = arr->len; + } + else { + adc_timer_active = false; + dac_timer_active = false; + mp_raise_ValueError("array argument expected"); + } + + self->dac_timer_mode = 2; + self->timer_interval = (int64_t)(round(interv)); + int err = start_dac_timer(self) != ESP_OK; + if (err) { + adc_timer_active = false; + dac_timer_active = false; + self->buffer = NULL; + self->buf_len = 0; + self->buf_ptr = 0; + ESP_LOGE("DAC", "Error starting DAC timer (%d)", err); + } + + if (wait) { + mp_hal_delay_ms(3); + while (dac_timer_active) { + mp_hal_delay_ms(3); + } + } + + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdac_write_buffer_obj, 0, mdac_write_buffer); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t mdac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_freq, ARG_mode, ARG_wait }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_samplerate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 1000} }, + { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + }; + + mdac_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + _is_init(self, true, false); + if ((!dac_i2s_driver_installed) && (i2s_driver_installed)) { + mp_raise_ValueError("Error: i2s used by other module"); + } + + dac_func_stop(self); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + int freq = args[ARG_freq].u_int; + if ((freq < 5000) || (freq > 500000)) { + mp_raise_ValueError("sample rate out of range (5000 - 500000 Hz)"); + } + + // Get arguments + bool wait = false; + trepeat = args[ARG_mode].u_bool; + // only wait if if not continuous mode + if (!trepeat) wait = args[ARG_wait].u_bool; + + mp_buffer_info_t src; + self->fhndl = NULL; + self->timer_interval = 0; + + if (MP_OBJ_IS_STR(args[ARG_data].u_obj)) { + const char *dac_file = NULL; + char fullname[128] = {'\0'}; + + dac_file = mp_obj_str_get_str(args[0].u_obj); + int res = physicalPath(dac_file, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + mp_raise_ValueError("Error resolving file name"); + } + self->buffer = NULL; + struct stat sb; + if (stat(fullname, &sb) != 0) { + mp_raise_ValueError("Error opening file"); + } + self->fhndl = fopen(fullname, "rb"); + if (self->fhndl == NULL) { + mp_raise_ValueError("Error opening file"); + } + self->buffer = malloc(4096); + if (self->buffer == NULL) { + fclose(self->fhndl); + mp_raise_ValueError("Error allocating dac buffer"); + } + self->buf_len = sb.st_size; + wait = false; + } + else { + mp_get_buffer_raise(args[ARG_data].u_obj, &src, MP_BUFFER_READ); + self->buffer = (uint8_t *)src.buf; + self->buf_len = src.len; + } + + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, // Only TX + //.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN, + .sample_rate = freq/2, + .bits_per_sample = 16, + .channel_format = (self->dac_id == DAC_CHANNEL_1) ? I2S_CHANNEL_FMT_ALL_RIGHT : I2S_CHANNEL_FMT_ALL_LEFT, + .communication_format = I2S_COMM_FORMAT_I2S_MSB, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = false, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, //Interrupt level 1 + .fixed_mclk = 0 + }; + //install and start i2s driver + i2s_driver_install(0, &i2s_config, 0, NULL); + i2s_driver_installed = true; + dac_i2s_driver_installed = true; + //init DAC pad + i2s_set_dac_mode((self->dac_id == DAC_CHANNEL_1) ? I2S_DAC_CHANNEL_RIGHT_EN : I2S_DAC_CHANNEL_LEFT_EN); + //i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); + //i2s_set_clk(0, freq, 16, I2S_CHANNEL_MONO); + //i2s_set_sample_rates(0, freq/2); + + task_stop = false; + esp_log_level_set("I2S", ESP_LOG_ERROR); + #if CONFIG_MICROPY_USE_BOTH_CORES + xTaskCreate(dac_task, "DAC_task", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, NULL); + #else + xTaskCreatePinnedToCore(dac_task, "DAC_task", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, NULL, MainTaskCore); + #endif + + if (wait) { + mp_hal_delay_ms(3); + while (task_running) { + mp_hal_delay_ms(3); + } + } + + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdac_write_timed_obj, 0, mdac_write_timed); + +//------------------------------------------------------------------ +STATIC mp_obj_t mdac_play_wav(size_t n_args, const mp_obj_t *args) { + + mdac_obj_t *self = MP_OBJ_TO_PTR(args[0]); + _is_init(self, true, false); + if ((!dac_i2s_driver_installed) && (i2s_driver_installed)) { + mp_raise_ValueError("Error: i2s used by other module"); + } + + dac_func_stop(self); + + self->buffer = NULL; + self->buf_len = 0; + self->fhndl = NULL; + int freq = 0; + float fdiv = 0; + + if (n_args == 3) { + fdiv = mp_obj_get_float(args[2]); + if ((fdiv < -8.0) || (fdiv > 8.0)) fdiv = 0.0; + } + const char *dac_file = NULL; + char fullname[128] = {'\0'}; + uint8_t hdr[44]; + + if (!MP_OBJ_IS_STR(args[1])) { + mp_raise_ValueError("File name expected"); + } + dac_file = mp_obj_str_get_str(args[1]); + int res = physicalPath(dac_file, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + mp_raise_ValueError("Error resolving file name"); + } + struct stat sb; + if (stat(fullname, &sb) != 0) { + mp_raise_ValueError("Error opening file"); + } + self->buf_len = sb.st_size; + if (self->buf_len < 45) { + mp_raise_ValueError("Not a WAV file"); + } + + self->fhndl = fopen(fullname, "rb"); + if (self->fhndl == NULL) { + mp_raise_ValueError("Error opening file"); + } + if (fread(hdr, 1, 44, self->fhndl) != 44) { + fclose(self->fhndl); + mp_raise_ValueError("Not a WAV file"); + } + if (((hdr[0] != 'R') || (hdr[1] != 'I') || (hdr[2] != 'F') || (hdr[3] != 'F')) || + ((hdr[8] != 'W') || (hdr[9] != 'A') || (hdr[10] != 'V') || (hdr[11] != 'E')) || + ((hdr[12] != 'f') || (hdr[13] != 'm') || (hdr[14] != 't') || (hdr[15] != ' ')) || + ((hdr[36] != 'd') || (hdr[37] != 'a') || (hdr[38] != 't') || (hdr[39] != 'a')) ) { + fclose(self->fhndl); + mp_raise_ValueError("Not a WAV file"); + } + if (((uint16_t)(hdr[20] | (hdr[21] << 8)) != 1) || ((uint16_t)(hdr[22] | (hdr[23] << 8)) != 1) || + ((uint16_t)(hdr[32] | (hdr[33] << 8)) != 1) || ((uint16_t)(hdr[34] | (hdr[35] << 8)) != 8)) { + fclose(self->fhndl); + mp_raise_ValueError("Only PCM, 8-bit mono can be played"); + } + int ffreq = (int)((int)hdr[24] | (int)(hdr[25] << 8) | (int)(hdr[26] << 16) | (int)(hdr[27] << 24)); + freq = ffreq / 4; + if (fdiv < -0.999) freq = (int)(round((float)freq / (fdiv * -1.0))); + else if (fdiv > 0.999) freq = (int)(round((float)freq * fdiv)); + if ((freq < 5000) || (freq > 500000)) { + fclose(self->fhndl); + mp_raise_ValueError("invalid sample rate (5000 - 500000 Hz)"); + } + + int data_size = (int)((int)hdr[40] | (int)(hdr[41] << 8) | (int)(hdr[42] << 16) | (int)(hdr[43] << 24)); + if ((data_size + 44) > sb.st_size) { + fclose(self->fhndl); + mp_raise_ValueError("invalid file size"); + } + self->buf_len = data_size; + + self->buffer = malloc(4096); + if (self->buffer == NULL) { + fclose(self->fhndl); + mp_raise_ValueError("Error allocating dac buffer"); + } + + ESP_LOGD("DAC", "Playing WAV, %d Hz, %d bytes", ffreq, data_size); + i2s_config_t i2s_config = { + .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, // Only TX + //.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN, + .sample_rate = freq, + .bits_per_sample = 16, + .channel_format = (self->dac_id == DAC_CHANNEL_1) ? I2S_CHANNEL_FMT_ALL_RIGHT : I2S_CHANNEL_FMT_ALL_LEFT, + .communication_format = I2S_COMM_FORMAT_I2S_MSB, + .dma_buf_count = 2, + .dma_buf_len = 1024, + .use_apll = false, + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, //Interrupt level 1 + .fixed_mclk = 0 + }; + //install and start i2s driver + i2s_driver_install(0, &i2s_config, 0, NULL); + i2s_driver_installed = true; + dac_i2s_driver_installed = true; + //init DAC pad + i2s_set_dac_mode((self->dac_id == DAC_CHANNEL_1) ? I2S_DAC_CHANNEL_RIGHT_EN : I2S_DAC_CHANNEL_LEFT_EN); + + task_stop = false; + esp_log_level_set("I2S", ESP_LOG_ERROR); + #if CONFIG_MICROPY_USE_BOTH_CORES + xTaskCreate(dac_task, "DAC_task", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, NULL); + #else + xTaskCreatePinnedToCore(dac_task, "DAC_task", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, NULL, MainTaskCore); + #endif + + return mp_const_true; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mdac_play_wav_obj, 2, 3, mdac_play_wav); + +//----------------------------------------------- +STATIC mp_obj_t mdac_stopfunc(mp_obj_t self_in) { + mdac_obj_t *self = self_in; + + dac_func_stop(self); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mdac_stopfunc_obj, mdac_stopfunc); + +//-------------------------------------------------------------- +STATIC mp_obj_t mdac_beep(size_t n_args, const mp_obj_t *args) { + mdac_obj_t *self = args[0]; + + _is_init(self, true, false); + + dac_func_stop(self); + + int freq = mp_obj_get_int(args[1]); + int duration = mp_obj_get_int(args[2]); + int scale = 0; + if (n_args == 4) scale = mp_obj_get_int(args[3]) & 3; + if (freq < 16 || freq > 32000) mp_raise_ValueError("Frequency out of range (16-32000 Hz)"); + if (duration < 10 || duration > 2000) mp_raise_ValueError("Duration out of range (10-2000 ms)"); + + // use cosine generator + uint64_t fs = freq * 65536; + int fdiv = 1; + if (freq < 256) fdiv = 4; + if (freq < 64) fdiv = 8; + fs /= (8000000 / fdiv); + dac_frequency_set((fdiv-1), (int)fs); + dac_scale_set(self->dac_id, scale); + dac_cosine_enable(self->dac_id); + + // wait for duration ms + mp_hal_delay_ms(duration); + dac_cosine_disable(); + dac_output_voltage(self->dac_id, 128); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mdac_beep_obj, 3, 4, mdac_beep); + +//---------------------------------------------------------------- +STATIC mp_obj_t mdac_setfreq(mp_obj_t self_in, mp_obj_t freq_in) { + //mdac_obj_t *self = self_in; + + int freq = mp_obj_get_int(freq_in); + if (cosine_enabled) { + if (freq < 130 || freq > 32000) mp_raise_ValueError("Frequency out of range (130-32000 Hz)"); + uint64_t fs = freq * 65536; + fs /= 8000000; + dac_frequency_set(0, (int)fs); + } + else if (dac_i2s_driver_installed && !task_running) { + if (freq < 170 || freq > 3600) mp_raise_ValueError("Frequency out of range (170-3600 Hz)"); + i2s_set_clk(0, freq * 64, 16, I2S_CHANNEL_MONO); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(mdac_setfreq_obj, mdac_setfreq); + +//------------------------------------------- +STATIC mp_obj_t mdac_deinit(mp_obj_t self_in) +{ + mdac_obj_t *self = self_in; + _is_init(self, false, true); + + if (self->gpio_id < 0) return mp_const_none; + + dac_cosine_disable(); + dac_output_disable(self->dac_id); + gpio_pad_select_gpio(self->gpio_id); + self->gpio_id = -1; + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mdac_deinit_obj, mdac_deinit); + + +//========================================================= STATIC const mp_rom_map_elem_t mdac_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mdac_write_obj) }, -}; + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mdac_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_timed), MP_ROM_PTR(&mdac_write_timed_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_buffer),MP_ROM_PTR(&mdac_write_buffer_obj) }, + { MP_ROM_QSTR(MP_QSTR_wavplay), MP_ROM_PTR(&mdac_play_wav_obj) }, + { MP_ROM_QSTR(MP_QSTR_waveform), MP_ROM_PTR(&mdac_waveform_obj) }, + { MP_ROM_QSTR(MP_QSTR_stopwave), MP_ROM_PTR(&mdac_stopfunc_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mdac_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&mdac_setfreq_obj) }, + { MP_ROM_QSTR(MP_QSTR_beep), MP_ROM_PTR(&mdac_beep_obj) }, + + { MP_ROM_QSTR(MP_QSTR_SINE), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_TRIANGLE), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_RAMP), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_SAWTOOTH), MP_ROM_INT(3) }, + { MP_ROM_QSTR(MP_QSTR_NOISE), MP_ROM_INT(4) }, + { MP_ROM_QSTR(MP_QSTR_CIRCULAR), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(1) }, +}; STATIC MP_DEFINE_CONST_DICT(mdac_locals_dict, mdac_locals_dict_table); +//====================================== const mp_obj_type_t machine_dac_type = { - { &mp_type_type }, - .name = MP_QSTR_DAC, - .print = mdac_print, - .make_new = mdac_make_new, - .locals_dict = (mp_obj_t)&mdac_locals_dict, + { &mp_type_type }, + .name = MP_QSTR_DAC, + .print = mdac_print, + .make_new = mdac_make_new, + .locals_dict = (mp_obj_t)&mdac_locals_dict, }; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_dht.c b/MicroPython_BUILD/components/micropython/esp32/machine_dht.c index 8965fd1f..154399d2 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_dht.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_dht.c @@ -280,8 +280,8 @@ static int ldht_compute_data11( uint8_t *data, double *temp, double *humi ) //------------------------------------------------------------------------- static int ldht_compute_data2x( uint8_t *data, double *temp, double *humi ) { - *humi = (uint16_t)((data[0] * 256 + data[1])) / 10; - *temp = (uint16_t)(((data[2] & 0x7f) * 256 + data[3])) / 10; + *humi = (double)((data[0] * 256 + data[1])) / 10; + *temp = (double)(((data[2] & 0x7f) * 256 + data[3])) / 10; if (data[2] & 0x80) *temp = - *temp; @@ -329,7 +329,7 @@ mp_obj_t machine_dht_make_new(const mp_obj_type_t *type, size_t n_args, size_t n uint8_t pin; uint8_t dht_type = args[ARG_type].u_int; - pin = machine_pin_get_id(args[ARG_pin].u_obj); + pin = machine_pin_get_gpio(args[ARG_pin].u_obj); // Setup the DHT object machine_dht_obj_t *self = m_new_obj(machine_dht_obj_t ); diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_gps.c b/MicroPython_BUILD/components/micropython/esp32/machine_gps.c new file mode 100644 index 00000000..066b6d49 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/machine_gps.c @@ -0,0 +1,756 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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. + */ + +/* GPS module based on nmea parsing library from + * 'https://github.com/jacketizer/libnmea', modified by LoBo + */ + +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_GPS + +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "driver/uart.h" + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "machine_uart.h" +#include "modmachine.h" +#include "nmea.h" +#include "gpgll.h" +#include "gpgga.h" +#include "gprmc.h" +#include "gpgst.h" +#include "gpvtg.h" + +#define EARTH_RADIUS_KM 6371.0 + + +const char *GPS_TAG = "MODGPS"; + +typedef struct { + struct tm datetime; + float latitude; + float longitude; + float altitude; + float speed; + float course; + float dop; + uint8_t quality; + uint8_t nsat; +} gps_data_t; + +typedef struct { + void *cb_func; + uint8_t type; + uint8_t compare; + nmea_position position; +} cb_func_coord_t; + +typedef struct { + void *cb_func; + uint8_t compare; + float value; +} cb_func_float_t; + +typedef struct { + void *cb_func; + uint8_t compare; + int value; +} cb_func_int_t; + +//--------------------------------- +typedef struct _machine_gps_obj_t { + mp_obj_base_t base; + mp_obj_t uart; + int timeout; + bool use_crc; + bool task_running; + bool task_stop; + uint32_t sent_read; + gps_data_t gps_data; + gps_data_t last_gps_data; + cb_func_coord_t cb_latitude; + cb_func_coord_t cb_longitude; +} machine_gps_obj_t; + +static const char* const known_parsers[] = { + "RMC", + "GGA", + "GGL", + "GST", + "VTG", +}; + +static const char* const known_talkers[] = { + "GP", + "GN", + "GL", +}; + +extern int MainTaskCore; + +static QueueHandle_t gps_mutex = NULL; + +const mp_obj_type_t machine_gps_type; + +//--------------------------------------------------- +static float coord_to_degrees(nmea_position position) +{ + double sign = 1.0; + if ((position.cardinal == NMEA_CARDINAL_DIR_SOUTH) || (position.cardinal == NMEA_CARDINAL_DIR_WEST)) sign = -1.0; + return (float)(((double)position.degrees + (position.minutes / 60.0)) * sign); +} + +//--------------------------------------------------- +static float coord_to_radians(nmea_position position) +{ + return (coord_to_degrees(position) * M_PI / 180.0); +} + +//------------------------------------------------------------------------------- +static float distance(float lat_from, float lat_to, float lon_from, float lon_to) +{ + float dLat = (lat_to - lat_from) * M_PI / 180.0; + float dLon = (lon_to - lon_from) * M_PI / 180.0; + + float lat1 = lat_from * M_PI / 180.0; + float lat2 = lat_to * M_PI / 180.0; + + float a = sin(dLat/2) * sin(dLat/2) + sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2); + float c = 2 * atan2(sqrt(a), sqrt(1-a)); + + return (EARTH_RADIUS_KM * c); +} + +//------------------------------------------ +static mp_obj_t _getTime(struct tm *tm_info) +{ + mp_obj_t tuple[8] = { + mp_obj_new_int(tm_info->tm_year + 1900), + mp_obj_new_int(tm_info->tm_mon + 1), + mp_obj_new_int(tm_info->tm_mday), + mp_obj_new_int(tm_info->tm_hour), + mp_obj_new_int(tm_info->tm_min), + mp_obj_new_int(tm_info->tm_sec), + mp_obj_new_int(tm_info->tm_wday + 1), + mp_obj_new_int(tm_info->tm_yday + 1) + }; + + return mp_obj_new_tuple(8, tuple); +} + +//------------------------------- +static long _currTime(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec*1000) + (tv.tv_usec / 1000); +} + +//-------------------------------------------------------------------------------------------- +static nmea_s *get_nmea_data(uart_port_t uart_num, char *sent_type, int timeout, bool use_crc) +{ + long end_time = _currTime() + timeout; + + nmea_s *data; + char *sentence = NULL;; + + while (_currTime() < end_time) { + sentence = _uart_read(uart_num, timeout, "\r\n", "$G"); + if (sentence) { + if (strstr(sentence, sent_type) == sentence) { + data = nmea_parse((char *)sentence, strlen(sentence), use_crc); + free(sentence); + if (data == NULL) continue; + return data; + } + else { + // not expected sentence type + free(sentence); + continue; + } + } + } + return NULL; // no date received, timeout +} + +//----------------------------------------------------------------------------------------------------- +static mp_obj_t nmea_data(nmea_s *data, bool settuple, gps_data_t *gps_data, gps_data_t *gps_last_data) +{ + mp_obj_t res_tuple = mp_const_none; + + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + if (data->errors != 0) { + if (settuple) { + mp_obj_t tuple[2] = { + mp_obj_new_str("ERRORS", 6), + mp_obj_new_int(data->errors) + }; + + res_tuple = mp_obj_new_tuple(2, tuple); + } + if (gps_mutex) xSemaphoreGive(gps_mutex); + return res_tuple; + } + + if ((gps_data) && (gps_last_data)) { + memcpy(gps_last_data, gps_data, sizeof(gps_data_t)); + } + + if (NMEA_GGA == data->type) { + nmea_gpgga_s *gpgga = (nmea_gpgga_s *) data; + if (gps_data) { + gps_data->nsat = gpgga->n_satellites; + gps_data->quality = (uint8_t)gpgga->quality; + if ((gpgga->n_satellites > 0) && (gpgga->quality > 0)) { + gps_data->altitude = gpgga->altitude; + gps_data->dop = gpgga->dop; + gps_data->latitude = coord_to_degrees(gpgga->latitude); + gps_data->longitude = coord_to_degrees(gpgga->longitude); + gps_data->datetime.tm_hour = gpgga->time.tm_hour; + gps_data->datetime.tm_min = gpgga->time.tm_min; + gps_data->datetime.tm_sec = gpgga->time.tm_sec; + } + } + if (settuple) { + if ((gpgga->n_satellites > 0) && (gpgga->quality > 0)) { + mp_obj_t tuple[8] = { + mp_obj_new_str("GGA", 3), + _getTime(&gpgga->time), + mp_obj_new_float(coord_to_degrees(gpgga->latitude)), + mp_obj_new_float(coord_to_degrees(gpgga->longitude)), + mp_obj_new_float(gpgga->altitude), + mp_obj_new_int(gpgga->n_satellites), + mp_obj_new_int(gpgga->quality), + mp_obj_new_float(gpgga->dop) + }; + res_tuple = mp_obj_new_tuple(8, tuple); + } + else { + mp_obj_t tuple[3] = { + mp_obj_new_str("GGA", 3), + mp_obj_new_int(gpgga->n_satellites), + mp_obj_new_int(gpgga->quality) + }; + res_tuple = mp_obj_new_tuple(3, tuple); + } + } + } + else if (NMEA_GLL == data->type) { + nmea_gpgll_s *gpgll = (nmea_gpgll_s *) data; + if ((gps_data) && (gpgll->valid)) { + gps_data->latitude = coord_to_degrees(gpgll->latitude); + gps_data->longitude = coord_to_degrees(gpgll->longitude); + gps_data->datetime.tm_hour = gpgll->time.tm_hour; + gps_data->datetime.tm_min = gpgll->time.tm_min; + gps_data->datetime.tm_sec = gpgll->time.tm_sec; + } + if (settuple) { + if (gpgll->valid) { + mp_obj_t tuple[5] = { + mp_obj_new_str("GLL", 3), + mp_obj_new_bool(gpgll->valid), + _getTime(&gpgll->time), + mp_obj_new_float(coord_to_degrees(gpgll->latitude)), + mp_obj_new_float(coord_to_degrees(gpgll->longitude)) + }; + res_tuple = mp_obj_new_tuple(5, tuple); + } + else { + mp_obj_t tuple[2] = { + mp_obj_new_str("GLL", 3), + mp_obj_new_bool(gpgll->valid) + }; + res_tuple = mp_obj_new_tuple(2, tuple); + } + } + } + else if (NMEA_RMC == data->type) { + nmea_gprmc_s *gprmc = (nmea_gprmc_s *) data; + if ((gps_data) && (gprmc->valid)) { + gps_data->speed = gprmc->speed * 1.85200; // knots -> km/h + gps_data->course = gprmc->course; + gps_data->latitude =coord_to_degrees(gprmc->latitude); + gps_data->longitude = coord_to_degrees(gprmc->longitude); + memcpy(&gps_data->datetime, &gprmc->time, sizeof(struct tm)); + } + if (settuple) { + if (gprmc->valid) { + mp_obj_t tuple[7] = { + mp_obj_new_str("RMC", 3), + mp_obj_new_bool(gprmc->valid), + _getTime(&gprmc->time), + mp_obj_new_float(coord_to_degrees(gprmc->latitude)), + mp_obj_new_float(coord_to_degrees(gprmc->longitude)), + mp_obj_new_float(gprmc->speed * 1.85200), // knots -> km/h + mp_obj_new_float(gprmc->course) + }; + res_tuple = mp_obj_new_tuple(7, tuple); + } + else { + mp_obj_t tuple[2] = { + mp_obj_new_str("RMC", 3), + mp_obj_new_bool(gprmc->valid) + }; + res_tuple = mp_obj_new_tuple(2, tuple); + } + } + } + else if (NMEA_VTG == data->type) { + nmea_gpvtg_s *gpvtg = (nmea_gpvtg_s *) data; + if (gps_data) { + gps_data->speed = gpvtg->speed_kmh; + gps_data->course = gpvtg->course; + } + if (settuple) { + mp_obj_t tuple[4] = { + mp_obj_new_str("VTG", 3), + mp_obj_new_float(gpvtg->speed_kmh), + mp_obj_new_float(gpvtg->speed_kn), + mp_obj_new_float(gpvtg->course) + }; + res_tuple = mp_obj_new_tuple(4, tuple); + } + } + else if (NMEA_GST == data->type) { + if (settuple) { + nmea_gpgst_s *gpgst = (nmea_gpgst_s *) data; + mp_obj_t tuple[9] = { + mp_obj_new_str("GST", 3), + _getTime(&gpgst->time), + mp_obj_new_float(gpgst->rmssd), + mp_obj_new_float(gpgst->sdmaj), + mp_obj_new_float(gpgst->sdmin), + mp_obj_new_float(gpgst->ori), + mp_obj_new_float(gpgst->latsd), + mp_obj_new_float(gpgst->lonsd), + mp_obj_new_float(gpgst->altsd) + }; + res_tuple = mp_obj_new_tuple(9, tuple); + } + } + if (gps_mutex) xSemaphoreGive(gps_mutex); + return res_tuple; +} + +//------------------------------------------ +static char *_get_sent_type(const char *sent) +{ + char *sent_type = calloc(8, 1); + if (sent_type == NULL) return NULL; + + if (sent[0] != '$') snprintf(sent_type, 7, "$%s", sent); + else snprintf(sent_type, 7, "%s", sent); + + bool f = false; + if (strcmp(sent_type, "$G") == 0) { + f = true; + } + else { + for (int i=0; itask_running = true; + if (gps_mutex) xSemaphoreGive(gps_mutex); + machine_uart_obj_t *uart = (machine_uart_obj_t *)gps_obj->uart; + + nmea_s *data; + char *sentence; + + while (true) { + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + if (gps_obj->task_stop) { + gps_obj->task_stop = false; + if (gps_mutex) xSemaphoreGive(gps_mutex); + break; + } + if (gps_mutex) xSemaphoreGive(gps_mutex); + sentence = _uart_read(uart->uart_num, 2000, "\r\n", "$G"); + if (sentence) { + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + data = nmea_parse(sentence, strlen(sentence), gps_obj->use_crc); + if (data != NULL) gps_obj->sent_read++; + if (gps_mutex) xSemaphoreGive(gps_mutex); + if (data != NULL) { + // store to gps_data only + nmea_data(data, false, &gps_obj->gps_data, &gps_obj->last_gps_data); + nmea_free(data); + } + free(sentence); + // Check callbacks + if (gps_obj->cb_latitude.cb_func) { + + } + } + } + + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + gps_obj->task_running = false; + if (gps_mutex) xSemaphoreGive(gps_mutex); + + esp_log_level_set(GPS_TAG, CONFIG_MICRO_PY_LOG_LEVEL); + ESP_LOGI(GPS_TAG, "GPS task ended, min free stack: %d", uxTaskGetStackHighWaterMark(NULL)); + + vTaskDelete(NULL); +} + +//---------------------------------------------------------- +static bool _check_task(machine_gps_obj_t *self, bool start) +{ + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + bool res = self->task_running; + if (gps_mutex) xSemaphoreGive(gps_mutex); + + if ((!res) && (start)) { + esp_log_level_set(GPS_TAG, ESP_LOG_ERROR); + esp_log_level_set(NMEA_TAG, ESP_LOG_ERROR); + self->sent_read = 0; + #if CONFIG_MICROPY_USE_BOTH_CORES + int tres = xTaskCreate(gps_task, "gps_task", CONFIG_MICROPY_GPS_SERVICE_STACK, self, CONFIG_MICROPY_TASK_PRIORITY, NULL); + #else + int tres = xTaskCreatePinnedToCore(gps_task, "gps_task", CONFIG_MICROPY_GPS_SERVICE_STACK, self, CONFIG_MICROPY_TASK_PRIORITY, NULL, MainTaskCore); + #endif + if (tres != pdTRUE) { + ESP_LOGE(GPS_TAG, "Error creating GPS task"); + res = false; + } + else res = true; + } + return res; +} + +/******************************************************************************/ +// MicroPython bindings for GPS + +//-------------------------------------------------------------------------------------------- +STATIC void machine_gps_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + bool task_running = self->task_running; + uint32_t sent_read = self->sent_read; + if (gps_mutex) xSemaphoreGive(gps_mutex); + + mp_printf(print, "GPS(default_timeout=%u, use_crc=%s, task_running=%s, read_sentences=%u)", + self->timeout, self->use_crc ? "True" : "False", task_running ? "True" : "False", sent_read); +} + +//-------------------------------------- +static const mp_arg_t allowed_args[] = { + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_crc, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_service, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, +}; + +enum { ARG_timeout, ARG_crc, ARG_service }; + +//------------------------------------------------------------------------------------------------------------------------ +STATIC void machine_gps_init_helper(machine_gps_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_timeout].u_int > 0) self->timeout = args[ARG_timeout].u_int; + if (args[ARG_crc].u_int >= 0) self->use_crc = (args[ARG_crc].u_int != 0); + if (args[ARG_service].u_bool) { + _check_task(self, true); + } +} + +//----------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_gps_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + machine_gps_obj_t *self = m_new_obj(machine_gps_obj_t); + memset(self, 0, sizeof(machine_gps_obj_t)); + + self->base.type = &machine_gps_type; + + if (!MP_OBJ_IS_TYPE(args[0], &machine_uart_type)) { + mp_raise_ValueError("uart object expected as 1st argument"); + } + self->uart = args[0]; + self->timeout = 1500; + self->use_crc = true; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + + mp_arg_val_t kargs[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, args+1, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, kargs); + + machine_gps_init_helper(self, n_args - 1, args + 1, &kw_args); + + if (gps_mutex == NULL) { + gps_mutex = xSemaphoreCreateMutex(); + } + + self->gps_data.datetime.tm_mday = 1; + + return MP_OBJ_FROM_PTR(self); +} + +//-------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_gps_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + machine_gps_init_helper(args[0], n_args - 1, args + 1, kw_args); + if (gps_mutex) xSemaphoreGive(gps_mutex); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_gps_init_obj, 1, machine_gps_init); + +//--------------------------------------------------------------------------- +STATIC mp_obj_t machine_gps_readsentence(size_t n_args, const mp_obj_t *args) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (_check_task(self, false)) { + mp_raise_ValueError("GPS task running"); + } + machine_uart_obj_t *uart = (machine_uart_obj_t *)self->uart; + + char *sentence = NULL; + char *sent_type = NULL; + int timeout = 0; + if (n_args > 1) timeout = mp_obj_get_int(args[1]); + if (n_args > 2) { + const char *sent = mp_obj_str_get_str(args[2]); + sent_type = _get_sent_type(sent); + if (sent_type == NULL) { + mp_raise_ValueError("Invalid sentence type"); + } + MP_THREAD_GIL_EXIT(); + sentence = _uart_read(uart->uart_num, timeout, "\r\n", sent_type); + MP_THREAD_GIL_ENTER(); + free(sent_type); + } + else { + MP_THREAD_GIL_EXIT(); + sentence = _uart_read(uart->uart_num, timeout, "\r\n", "$G"); + MP_THREAD_GIL_ENTER(); + } + + + if (sentence == NULL) return mp_obj_new_str("", 0); + + mp_obj_t res_str = mp_obj_new_str((const char *)sentence, strlen(sentence)); + + if (sentence != NULL) free(sentence); + return res_str; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_gps_readsentence_obj, 1, 3, machine_gps_readsentence); + +//------------------------------------------------------------------- +STATIC mp_obj_t machine_gps_parse(mp_obj_t self_in, mp_obj_t sent_in) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(self_in); + + const char *sentence = mp_obj_str_get_str(sent_in); + mp_obj_t res = mp_const_none; + + char *sent = strdup(sentence); + if (sent) { + nmea_s *data = nmea_parse(sent, strlen(sent), self->use_crc); + if (data != NULL) { + // store to dict only + res = nmea_data(data, true, NULL, NULL); + nmea_free(data); + } + free(sent); + } + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_gps_parse_obj, machine_gps_parse); + +//------------------------------------------------------------------------- +STATIC mp_obj_t machine_gps_read_parse(size_t n_args, const mp_obj_t *args) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (_check_task(self, false)) { + mp_raise_ValueError("GPS task running"); + } + + machine_uart_obj_t *uart = (machine_uart_obj_t *)self->uart; + const char *sent = mp_obj_str_get_str(args[1]); + char *sent_type = NULL; + + sent_type = _get_sent_type(sent); + if (sent_type == NULL) { + mp_raise_ValueError("Invalid sentence type"); + } + + int timeout = self->timeout; + if (n_args > 2) { + timeout = mp_obj_get_int(args[2]); + } + + if (timeout < 1200) timeout = 1200; + mp_obj_t res = mp_const_none; + + MP_THREAD_GIL_EXIT(); + nmea_s *data = get_nmea_data(uart->uart_num, sent_type, timeout, self->use_crc); + MP_THREAD_GIL_ENTER(); + free(sent_type); + + if (data != NULL) { + // store to dict and gps_data + res = nmea_data(data, true, &self->gps_data, NULL); + nmea_free(data); + } + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_gps_read_parse_obj, 2, 3, machine_gps_read_parse); + +//--------------------------------------------------- +STATIC mp_obj_t machine_gps_getdata(mp_obj_t self_in) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + mp_obj_t tuple[9] = { + _getTime(&self->gps_data.datetime), + mp_obj_new_float(self->gps_data.latitude), + mp_obj_new_float(self->gps_data.longitude), + mp_obj_new_float(self->gps_data.altitude), + mp_obj_new_int(self->gps_data.nsat), + mp_obj_new_int(self->gps_data.quality), + mp_obj_new_float(self->gps_data.speed), + mp_obj_new_float(self->gps_data.course), + mp_obj_new_float(self->gps_data.dop) + }; + if (gps_mutex) xSemaphoreGive(gps_mutex); + + return mp_obj_new_tuple(9, tuple);; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_gps_getdata_obj, machine_gps_getdata); + +//-------------------------------------------------------- +STATIC mp_obj_t machine_gps_startservice(mp_obj_t self_in) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (_check_task(self, true)) return mp_const_true; + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_gps_startservice_obj, machine_gps_startservice); + +//------------------------------------------------------- +STATIC mp_obj_t machine_gps_stopservice(mp_obj_t self_in) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + if (self->task_running) { + self->task_stop = true; + } + if (gps_mutex) xSemaphoreGive(gps_mutex); + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_gps_stopservice_obj, machine_gps_stopservice); + +//------------------------------------------------------- +STATIC mp_obj_t machine_gps_taskrunning(mp_obj_t self_in) +{ + machine_gps_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (gps_mutex) xSemaphoreTake(gps_mutex, 200 / portTICK_PERIOD_MS); + bool res = self->task_running; + if (gps_mutex) xSemaphoreGive(gps_mutex); + + if (res) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_gps_taskrunning_obj, machine_gps_taskrunning); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_gps_distance(size_t n_args, const mp_obj_t *args) +{ + float lat1 = mp_obj_get_float(args[1]); + float lon1 = mp_obj_get_float(args[2]); + float lat2 = mp_obj_get_float(args[3]); + float lon2 = mp_obj_get_float(args[4]); + + return mp_obj_new_float(distance(lat1, lat2, lon1, lon2)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_gps_distance_obj, 5, 5, machine_gps_distance); + + +//================================================================ +STATIC const mp_rom_map_elem_t machine_gps_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_gps_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_parse), MP_ROM_PTR(&machine_gps_parse_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_gps_readsentence_obj) }, + { MP_ROM_QSTR(MP_QSTR_read_parse), MP_ROM_PTR(&machine_gps_read_parse_obj) }, + { MP_ROM_QSTR(MP_QSTR_getdata), MP_ROM_PTR(&machine_gps_getdata_obj) }, + { MP_ROM_QSTR(MP_QSTR_startservice), MP_ROM_PTR(&machine_gps_startservice_obj) }, + { MP_ROM_QSTR(MP_QSTR_stopservice), MP_ROM_PTR(&machine_gps_stopservice_obj) }, + { MP_ROM_QSTR(MP_QSTR_service), MP_ROM_PTR(&machine_gps_taskrunning_obj) }, + { MP_ROM_QSTR(MP_QSTR_distance), MP_ROM_PTR(&machine_gps_distance_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_gps_locals_dict, machine_gps_locals_dict_table); + + +//====================================== +const mp_obj_type_t machine_gps_type = { + { &mp_type_type }, + .name = MP_QSTR_GPS, + .print = machine_gps_print, + .make_new = machine_gps_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_gps_locals_dict, +}; + + +#endif + diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_hw_i2c.c b/MicroPython_BUILD/components/micropython/esp32/machine_hw_i2c.c index d8b31f71..6493db5a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_hw_i2c.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_hw_i2c.c @@ -30,21 +30,28 @@ #include "freertos/FreeRTOS.h" #include "sdkconfig.h" +#include "driver/i2c.h" +#include "driver/gpio.h" +#include "driver/periph_ctrl.h" +#include "esp_log.h" + #include "py/mpstate.h" #include "py/runtime.h" #include "py/obj.h" -#include "machine_pin.h" -#include "driver/i2c.h" -#include "driver/gpio.h" -#include "driver/periph_ctrl.h" +#include "modmachine.h" #define I2C_ACK_CHECK_EN (1) #define I2C_RX_MAX_BUFF_LEN 2048 // maximum low level commands receive buffer length -#define I2C_SLAVE_MAX_BUFF_LEN 2048 // maximum slave buffer length (max 4096 !) #define I2C_SLAVE_DEFAULT_BUFF_LEN 256 // default slave buffer length #define I2C_SLAVE_ADDR_DEFAULT 32 // default slave address #define I2C_SLAVE_MUTEX_TIMEOUT (500 / portTICK_PERIOD_MS) +#define I2C_SLAVE_TASK_STACK_SIZE 832 + +#define I2C_SLAVE_CBTYPE_NONE 0 +#define I2C_SLAVE_CBTYPE_ADDR 1 +#define I2C_SLAVE_CBTYPE_DATA_RX 2 +#define I2C_SLAVE_CBTYPE_DATA_TX 4 typedef struct _mp_machine_i2c_obj_t { mp_obj_base_t base; @@ -59,25 +66,28 @@ typedef struct _mp_machine_i2c_obj_t { uint8_t *rx_data; // low level commands receive buffer int8_t slave_addr; // slave only, slave 8-bit address uint16_t slave_buflen; // slave only, data buffer length - uint8_t *slave_data; // slave only, data buffer - uint32_t *slave_cb_read; // slave only, slave callback function for read data - uint32_t *slave_cb_write; // slave only, slave callback function for write data - uint32_t *slave_cb_data; // slave only, slave callback function for data + uint16_t slave_rolen; // slave only, read only buffer area length + uint32_t *slave_cb; // slave only, slave callback function + bool slave_busy; + uint8_t slave_cbtype; } mp_machine_i2c_obj_t; +extern int MainTaskCore; + const mp_obj_type_t machine_hw_i2c_type; static int i2c_used[I2C_MODE_MAX] = { -1, -1 }; -static QueueHandle_t slave_mutex = NULL; -static TaskHandle_t i2c_slave_task_handle[I2C_MODE_MAX] = { NULL, NULL }; +static QueueHandle_t slave_mutex[I2C_MODE_MAX] = { NULL, NULL }; +static TaskHandle_t i2c_slave_task_handle = NULL; +static i2c_slave_state_t slave_state; // ============================================================================================ // === Low level I2C functions using esp-idf i2c-master driver ================================ // ============================================================================================ -//--------------------------------------------------------- +//-------------------------------------------------------------- STATIC esp_err_t i2c_init_master (mp_machine_i2c_obj_t *i2c_obj) { i2c_config_t conf; @@ -90,11 +100,11 @@ STATIC esp_err_t i2c_init_master (mp_machine_i2c_obj_t *i2c_obj) conf.master.clk_speed = i2c_obj->speed; i2c_param_config(i2c_obj->bus_id, &conf); - return i2c_driver_install(i2c_obj->bus_id, I2C_MODE_MASTER, 0, 0, 0); + return i2c_driver_install(i2c_obj->bus_id, I2C_MODE_MASTER, 0, 0, false, ESP_INTR_FLAG_IRAM); } -//-------------------------------------------------------- -STATIC esp_err_t i2c_init_slave (mp_machine_i2c_obj_t *i2c_obj) +//------------------------------------------------------------------------ +STATIC esp_err_t i2c_init_slave (mp_machine_i2c_obj_t *i2c_obj, bool busy) { i2c_config_t conf; @@ -107,11 +117,11 @@ STATIC esp_err_t i2c_init_slave (mp_machine_i2c_obj_t *i2c_obj) conf.slave.slave_addr = i2c_obj->slave_addr; i2c_param_config(i2c_obj->bus_id, &conf); - return i2c_driver_install(i2c_obj->bus_id, conf.mode, i2c_obj->slave_buflen + 8, i2c_obj->slave_buflen + 8, 0); + return i2c_driver_install(i2c_obj->bus_id, conf.mode, i2c_obj->slave_buflen, i2c_obj->slave_rolen, busy, ESP_INTR_FLAG_IRAM); } -//------------------------------------------------------------------------------------------------------------------------------------------------------------- -STATIC void mp_i2c_master_write(mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_addr, uint8_t memwrite, uint32_t memaddr, uint8_t *data, uint16_t len, bool stop) +//------------------------------------------------------------------------------------------------------------------------------------------------------------ +STATIC int mp_i2c_master_write(mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_addr, uint8_t memwrite, uint32_t memaddr, uint8_t *data, uint16_t len, bool stop) { esp_err_t ret = ESP_FAIL; @@ -128,7 +138,9 @@ STATIC void mp_i2c_master_write(mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_ad } // send data - if (i2c_master_write(cmd, data, len, I2C_ACK_CHECK_EN) != ESP_OK) {ret=5; goto error;}; + if ((data) && (len > 0)) { + if (i2c_master_write(cmd, data, len, I2C_ACK_CHECK_EN) != ESP_OK) {ret=5; goto error;}; + } if (stop) { if (i2c_master_stop(cmd) != ESP_OK) {ret=6; goto error;}; } @@ -138,15 +150,11 @@ STATIC void mp_i2c_master_write(mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_ad error: i2c_cmd_link_delete(cmd); - if (ret != ESP_OK) { - char errs[32]; - sprintf(errs, "I2C bus error (%d)", ret); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, errs)); - } + return ret; } -//----------------------------------------------------------------------------------------------------------------------------------------------------------- -STATIC void mp_i2c_master_read(mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_addr, uint8_t memread, uint32_t memaddr, uint8_t *data, uint16_t len, bool stop) +//---------------------------------------------------------------------------------------------------------------------------------------------------------- +STATIC int mp_i2c_master_read(mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_addr, uint8_t memread, uint32_t memaddr, uint8_t *data, uint16_t len, bool stop) { esp_err_t ret = ESP_FAIL; @@ -198,11 +206,7 @@ STATIC void mp_i2c_master_read(mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_add error: i2c_cmd_link_delete(cmd); - if (ret != ESP_OK) { - char errs[32]; - sprintf(errs, "I2C bus error (%d)", ret); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, errs)); - } + return ret; } //---------------------------------------------------------------------------------- @@ -223,127 +227,163 @@ STATIC bool hw_i2c_slave_detect (mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_a return (ret == ESP_OK) ? true : false; } +//--------------------------------------------------------------------------------------------------- +STATIC void _sched_callback(mp_obj_t function, int cbtype, int addr, int len, int ovf, uint8_t *data) +{ + mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); + if (carg == NULL) return; + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_INT, cbtype, NULL, NULL)) return; + if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_INT, addr, NULL, NULL)) return; + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_INT, len, NULL, NULL)) return; + if (!make_carg_entry(carg, 3, MP_SCHED_ENTRY_TYPE_INT, ovf, NULL, NULL)) return; + if (data) { + if (!make_carg_entry(carg, 4, MP_SCHED_ENTRY_TYPE_BYTES, len, data, NULL)) return; + } + else { + if (!make_carg_entry(carg, 4, MP_SCHED_ENTRY_TYPE_NONE, 0, NULL, NULL)) return; + } + mp_sched_schedule(function, mp_const_none, carg); +} + +//-------------------------------------------- +STATIC void i2c_slave_task(void *pvParameters) +{ + mp_machine_i2c_obj_t *i2c_obj = (mp_machine_i2c_obj_t *)pvParameters; + + int len, ovf, rdlen, addr; + uint8_t cb_type; + uint32_t notify_val = 0; + int notify_res = 0; + uint8_t *data; + + if (i2c_obj->slave_buflen == 0) goto exit; + + if (i2c_slave_add_task(i2c_obj->bus_id, &i2c_slave_task_handle, &slave_state) != ESP_OK) goto exit; + + //ESP_LOGD("[I2C]", "Slave task started"); + while (1) { + // === Wait for notification from I2C interrupt routine === + notify_val = 0; + notify_res = xTaskNotifyWait(0, ULONG_MAX, ¬ify_val, 1000 / portTICK_RATE_MS); + + if (slave_mutex[i2c_obj->bus_id]) xSemaphoreTake(slave_mutex[i2c_obj->bus_id], I2C_SLAVE_MUTEX_TIMEOUT); + if (notify_res != pdPASS) { + if ((i2c_used[0] != I2C_MODE_SLAVE) && (i2c_used[1] != I2C_MODE_SLAVE)) { + //ESP_LOGD("[I2C]", "all i2c slave instances deleted"); + if (slave_mutex[i2c_obj->bus_id]) xSemaphoreGive(slave_mutex[i2c_obj->bus_id]); + break; + } + if (slave_mutex[i2c_obj->bus_id]) xSemaphoreGive(slave_mutex[i2c_obj->bus_id]); + continue; + } + + // *** notification received + // Check if task exit requested or all i2c instances are deinitialized + if (notify_val == I2C_SLAVE_DRIVER_DELETED) { + //ESP_LOGD("[I2C]", "i2c driver deleted (%d)", i2c_obj->bus_id); + } + if ((notify_val == I2C_SLAVE_DRIVER_DELETED) && ((i2c_used[0] != I2C_MODE_SLAVE) && (i2c_used[1] != I2C_MODE_SLAVE))) { + if (slave_mutex[i2c_obj->bus_id]) xSemaphoreGive(slave_mutex[i2c_obj->bus_id]); + break; + } + if ((i2c_used[0] != I2C_MODE_SLAVE) && (i2c_used[1] != I2C_MODE_SLAVE)) { + //ESP_LOGD("[I2C]", "all i2c slave instances deleted"); + if (slave_mutex[i2c_obj->bus_id]) xSemaphoreGive(slave_mutex[i2c_obj->bus_id]); + break; + } + + if ((slave_state.rxptr == 0) && (slave_state.txptr == 0)) { + // address received from master + cb_type = I2C_SLAVE_CBTYPE_ADDR; + ovf = 0; + len = 0; + addr = slave_state.rxaddr; + } + else if (slave_state.status & 0x02) { + // read transaction, data sent to master + cb_type = I2C_SLAVE_CBTYPE_DATA_TX; + ovf = slave_state.txovf; + len = slave_state.txptr; + addr = slave_state.txaddr; + } + else { + // write transaction, data received from master + cb_type = I2C_SLAVE_CBTYPE_DATA_RX; + ovf = slave_state.rxovf; + len = slave_state.rxptr; + addr = slave_state.rxaddr; + } + cb_type &= i2c_obj->slave_cbtype; // mask allowed callback types + + if ((cb_type) && (i2c_obj->slave_cb)) { + data = NULL; + if (len > 0) { + data = malloc(len); + if (data) { + rdlen = i2c_slave_read_buffer(i2c_obj->bus_id, data, addr, len, I2C_SLAVE_MUTEX_TIMEOUT); + if (rdlen != len) { + free(data); + data = NULL; + } + } + } + _sched_callback(i2c_obj->slave_cb, cb_type, addr, len, ovf, data); + if (data) free(data); + } + if (slave_mutex[i2c_obj->bus_id]) xSemaphoreGive(slave_mutex[i2c_obj->bus_id]); + } + +exit: + i2c_slave_remove_task(i2c_obj->bus_id); + //ESP_LOGD("[I2C]", "Slave task deleted"); + i2c_slave_task_handle = NULL; + vTaskDelete(NULL); +} + // ============================================================================================ // === I2C MicroPython bindings =============================================================== // ============================================================================================ -enum { ARG_id, ARG_mode, ARG_speed, ARG_freq, ARG_sda, ARG_scl, ARG_slaveaddr, ARG_slavebuflen }; +enum { ARG_id, ARG_mode, ARG_speed, ARG_freq, ARG_sda, ARG_scl, ARG_slaveaddr, ARG_slavebuflen, ARG_rolen, ARG_busy }; +// Arguments for new object and init method //---------------------------------------------------------- STATIC const mp_arg_t mp_machine_i2c_init_allowed_args[] = { - { MP_QSTR_id, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_mode, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_speed, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_slave_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_slave_bufflen, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_id, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_mode, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_speed, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_slave_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_slave_bufflen, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_slave_rolen, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_slave_busy, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; -//--------------------------------------------------------------------------------------- -STATIC void _sched_callback(mp_obj_t function, int cmd, int addr, int len, uint8_t *sarg) +//---------------------------------------------- +static uint8_t * get_buffer(void *buff, int len) { - mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); - if (carg == NULL) return; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_INT, cmd, NULL, NULL)) return; - if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_INT, addr, NULL, NULL)) return; - if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_INT, len, NULL, NULL)) return; - if (sarg) { - if (!make_carg_entry(carg, 3, MP_SCHED_ENTRY_TYPE_BYTES, len, sarg, NULL)) return; - } - else { - if (!make_carg_entry(carg, 3, MP_SCHED_ENTRY_TYPE_NONE, 0, NULL, NULL)) return; - } - mp_sched_schedule(function, mp_const_none, carg); + if (len > 0) { + uint8_t *buf = heap_caps_malloc(len, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + if (buf == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating I2C data buffer")); + } + memcpy(buf, buff, len); + return buf; + } + return NULL; } -//-------------------------------------------- -STATIC void i2c_slave_task(void *pvParameters) +//---------------------------------- +static void i2c_check_error(int err) { - mp_machine_i2c_obj_t *i2c_obj = (mp_machine_i2c_obj_t *)pvParameters; - - int rd_len; - uint8_t cmd; - int16_t mem_addr, mem_len; - uint32_t trans_size = 0; - int notify_res = 0; - if (i2c_obj->slave_data == NULL) goto exit; - - if (i2c_slave_add_task(i2c_obj->bus_id, &i2c_slave_task_handle[i2c_obj->bus_id]) != ESP_OK) goto exit; - - while (1) { - // === Wait for transaction data === - trans_size = 0; - notify_res = xTaskNotifyWait(0, ULONG_MAX, &trans_size, portMAX_DELAY); - if ((notify_res != pdPASS) || (trans_size < 1)) continue; - - // === Check if the i2c object is still initialized === - if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); - if (i2c_obj->bus_id < 0) { - if (slave_mutex) xSemaphoreGive(slave_mutex); - break; - } - if (i2c_obj->slave_data == NULL) { - if (slave_mutex) xSemaphoreGive(slave_mutex); - break; - } - if (slave_mutex) xSemaphoreGive(slave_mutex); - - // Allocate the transaction data buffer - uint8_t *data = malloc(trans_size); - if (data) { - // Read the transaction data - rd_len = i2c_slave_read_buffer(i2c_obj->bus_id, data, trans_size, 0); - if (rd_len > 0) { - if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); - // --- Analyze the received data based on first byte received --- - cmd = data[0] & 0xF0; // 4-bit command id - - if ((cmd == 0x00) && (rd_len == 4)) { - // READ data from buffer, 4 bytes received are buffer address & read length - mem_addr = ((data[0] << 8) | data[1]) & 0x0FFF; // 12-bit address - mem_len = ((data[2] << 8) | data[3]) & 0x0FFF; // 12-bit length - if ((mem_addr + mem_len) > i2c_obj->slave_buflen) mem_len = i2c_obj->slave_buflen - mem_addr; - if ((mem_addr < i2c_obj->slave_buflen) && (mem_len > 0)) { - // Put the response data into i2c transmit buffer - i2c_slave_write_buffer(i2c_obj->bus_id, i2c_obj->slave_data + mem_addr, mem_len, 500 / portTICK_PERIOD_MS); - if (i2c_obj->slave_cb_read) { - _sched_callback(i2c_obj->slave_cb_read, cmd>>4, mem_addr, mem_len, i2c_obj->slave_data + mem_addr); - } - } - } - else if ((cmd == 0x10) && (rd_len > 2)) { - // WRITE data to buffer, first 2 bytes are buffer address - mem_addr = ((data[0] << 8) | data[1]) & 0x0FFF; // 12-bit address - mem_len = rd_len - 2; - if ((mem_addr + mem_len) > i2c_obj->slave_buflen) mem_len = i2c_obj->slave_buflen - mem_addr; - if ((mem_addr < i2c_obj->slave_buflen) && (mem_len > 0)) { - // Save the received data to the i2c data buffer - memcpy(i2c_obj->slave_data + mem_addr, data + 2, mem_len); - if (i2c_obj->slave_cb_write) { - _sched_callback(i2c_obj->slave_cb_write, cmd>>4, mem_addr, mem_len, i2c_obj->slave_data + mem_addr); - } - } - } - else if ((cmd >= 0x20) && (cmd <= 0xF0)) { - // COMMAND, optionally with DATA to pass to the callback function - if (i2c_obj->slave_cb_data) { - uint8_t *dataptr = NULL; - if (rd_len > 1) dataptr = data+1; - _sched_callback(i2c_obj->slave_cb_data, data[0], trans_size, rd_len-1, dataptr); - } - } - if (slave_mutex) xSemaphoreGive(slave_mutex); - } - free(data); - } - } -exit: - i2c_slave_remove_task(i2c_obj->bus_id); - i2c_slave_task_handle[i2c_obj->bus_id] = NULL; - vTaskDelete(NULL); + if (err != ESP_OK) { + char errs[32]; + sprintf(errs, "I2C bus error (%d)", err); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, errs)); + } } //---------------------------------- @@ -378,12 +418,11 @@ STATIC void mp_machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_p if (self->mode == I2C_MODE_MASTER) mp_printf(print, "I2C (Port=%u, Mode=MASTER, Speed=%u Hz, sda=%d, scl=%d)", self->bus_id, self->speed, self->sda, self->scl); else { - mp_printf(print, "I2C (Port=%u, Mode=SLAVE, Speed=%u Hz, sda=%d, scl=%d, addr=%d, buffer=%d B)", - self->bus_id, self->speed, self->sda, self->scl, self->slave_addr, self->slave_buflen); - mp_printf(print, "\n ReadCB=%s, WriteCB=%s, DataCB=%s", - self->slave_cb_read ? "True" : "False", self->slave_cb_write ? "True" : "False", self->slave_cb_data ? "True" : "False"); - if (i2c_slave_task_handle[self->bus_id]) { - mp_printf(print, "\n I2C task minimum free stack: %u", uxTaskGetStackHighWaterMark(i2c_slave_task_handle[self->bus_id])); + mp_printf(print, "I2C (Port=%u, Mode=SLAVE, Speed=%u Hz, sda=%d, scl=%d, addr=%d, buffer=%d B, read-only=%d B)", + self->bus_id, self->speed, self->sda, self->scl, self->slave_addr, self->slave_buflen, self->slave_rolen); + mp_printf(print, "\n Callback=%s (%d)", self->slave_cb ? "True" : "False", self->slave_cbtype); + if (i2c_slave_task_handle) { + mp_printf(print, "\n I2C task minimum free stack: %u", uxTaskGetStackHighWaterMark(i2c_slave_task_handle)); } } } @@ -419,9 +458,12 @@ mp_obj_t mp_machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_ int mode = args[ARG_mode].u_int; if (mode < 0) mode = I2C_MODE_MASTER; if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_SLAVE)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "MASTER or SLAVE mode must be selected")); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "MASTER or SLAVE mode must be selected")); } + if ((args[ARG_sda].u_obj == MP_OBJ_NULL) || (args[ARG_sda].u_obj == MP_OBJ_NULL)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "sda & scl must be given")); + } sda = machine_pin_get_gpio(args[ARG_sda].u_obj); scl = machine_pin_get_gpio(args[ARG_scl].u_obj); @@ -438,11 +480,11 @@ mp_obj_t mp_machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_ self->rx_bufidx = 0; self->rx_data = NULL; self->slave_buflen = 0; + self->slave_rolen = 0; self->slave_addr = 0; - self->slave_data = NULL; - self->slave_cb_read = NULL; - self->slave_cb_write = NULL; - self->slave_cb_data = NULL; + self->slave_cb = NULL; + self->slave_busy = false; + self->slave_cbtype = I2C_SLAVE_CBTYPE_NONE; if (mode == I2C_MODE_MASTER) { // Setup I2C master @@ -451,8 +493,10 @@ mp_obj_t mp_machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_ } } else { - if (slave_mutex == NULL) { - slave_mutex = xSemaphoreCreateMutex(); + if (args[ARG_busy].u_int == 1) self->slave_busy = true; + + if (slave_mutex[self->bus_id] == NULL) { + slave_mutex[self->bus_id] = xSemaphoreCreateMutex(); } // Set I2C slave address if (args[ARG_slaveaddr].u_int > 0) { @@ -462,24 +506,29 @@ mp_obj_t mp_machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_ else self->slave_addr = I2C_SLAVE_ADDR_DEFAULT; // Set I2C slave buffers - if ((args[ARG_slavebuflen].u_int > I2C_SLAVE_DEFAULT_BUFF_LEN) && (args[ARG_slavebuflen].u_int <= I2C_SLAVE_MAX_BUFF_LEN)) + if ((args[ARG_slavebuflen].u_int >= I2C_SLAVE_MIN_BUFFER_LENGTH) && (args[ARG_slavebuflen].u_int <= I2C_SLAVE_MAX_BUFFER_LENGTH)) self->slave_buflen = args[ARG_slavebuflen].u_int; else self->slave_buflen = I2C_SLAVE_DEFAULT_BUFF_LEN; - self->slave_data = malloc(self->slave_buflen); - if (self->slave_data == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating slave data buffer")); - } - memset(self->slave_data, 0, self->slave_buflen); + if ((args[ARG_rolen].u_int > 0) && (args[ARG_rolen].u_int < (self->slave_buflen / 2))) + self->slave_rolen = args[ARG_rolen].u_int; + else self->slave_rolen = 0; + if ((self->slave_busy) && (self->slave_rolen == 0)) self->slave_rolen = 1; - if (i2c_init_slave(self) != ESP_OK) { - free(self->slave_data); - self->slave_data = NULL; + if (i2c_init_slave(self, self->slave_busy) != ESP_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error installing I2C driver")); } - if (i2c_slave_task_handle[self->bus_id] == NULL) { - xTaskCreate(i2c_slave_task, "i2c_slave_task", 1024, (void *)self, 8, &i2c_slave_task_handle[self->bus_id]); + if (i2c_slave_task_handle == NULL) { + #if CONFIG_MICROPY_USE_BOTH_CORES + int res = xTaskCreate(i2c_slave_task, "i2c_slave_task", I2C_SLAVE_TASK_STACK_SIZE, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &i2c_slave_task_handle); + #else + int res = xTaskCreatePinnedToCore(i2c_slave_task, "i2c_slave_task", I2C_SLAVE_TASK_STACK_SIZE, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &i2c_slave_task_handle, MainTaskCore); + #endif + if (res != pdPASS) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error installing I2C driver")); + } + vTaskDelay(100 / portTICK_PERIOD_MS); } } @@ -496,11 +545,10 @@ STATIC mp_obj_t mp_machine_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_arg_val_t args[MP_ARRAY_SIZE(mp_machine_i2c_init_allowed_args)]; mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(mp_machine_i2c_init_allowed_args), mp_machine_i2c_init_allowed_args, args); - int8_t sda; - int8_t scl; - int8_t slave_addr; + int8_t sda, scl, slave_addr; int32_t speed; uint8_t changed = 0; + int buff_len, ro_len; int8_t old_bus_id = self->bus_id; int8_t bus_id = args[ARG_id].u_int; @@ -526,6 +574,9 @@ STATIC mp_obj_t mp_machine_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, scl = self->scl; sda = self->sda; + buff_len = self->slave_buflen; + ro_len = self->slave_rolen; + slave_addr = self->slave_addr; if (args[ARG_sda].u_obj != MP_OBJ_NULL) { sda = machine_pin_get_gpio(args[ARG_sda].u_obj); @@ -540,21 +591,51 @@ STATIC mp_obj_t mp_machine_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, if (self->scl != scl) changed++; if (self->sda != sda) changed++; - if (args[ARG_slaveaddr].u_int > 0) { - _checkAddr(args[ARG_slaveaddr].u_int); - slave_addr = args[ARG_slaveaddr].u_int; - changed++; - } - else slave_addr = self->slave_addr; + if (mode == I2C_MODE_SLAVE) { + if (args[ARG_busy].u_int >= 0) { + if (self->slave_busy != ((args[ARG_busy].u_int == 1) ? true : false)) { + self->slave_busy = (args[ARG_busy].u_int == 1) ? true : false; + if ((self->slave_busy) && (self->slave_rolen == 0)) self->slave_rolen = 1; + changed++; + } + } + if (args[ARG_slaveaddr].u_int > 0) { + _checkAddr(args[ARG_slaveaddr].u_int); + if (args[ARG_slaveaddr].u_int != slave_addr) { + slave_addr = args[ARG_slaveaddr].u_int; + changed++; + } + } + if ((args[ARG_slavebuflen].u_int >= I2C_SLAVE_MIN_BUFFER_LENGTH) && (args[ARG_slavebuflen].u_int <= I2C_SLAVE_MAX_BUFFER_LENGTH)) { + if (args[ARG_slavebuflen].u_int != buff_len) { + buff_len = args[ARG_slavebuflen].u_int; + changed++; + } + } + if ((args[ARG_rolen].u_int > 0) && (args[ARG_rolen].u_int < (buff_len/2))) { + if (args[ARG_rolen].u_int != ro_len) { + ro_len = args[ARG_rolen].u_int; + if ((self->slave_busy) && (self->slave_rolen == 0)) self->slave_rolen = 1; + changed++; + } + } + } if (changed) { - if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); if (i2c_used[old_bus_id] >= 0) { + // Delete old driver, if it was a slave, the task will be stopped + i2c_used[old_bus_id] = -1; i2c_driver_delete(old_bus_id); - i2c_used[old_bus_id] = -1; + vTaskDelay(100 / portTICK_PERIOD_MS); + } + if (self->mode == I2C_MODE_SLAVE) { + if (slave_mutex[self->bus_id] == NULL) { + slave_mutex[self->bus_id] = xSemaphoreCreateMutex(); + } + if (slave_mutex[self->bus_id]) xSemaphoreTake(slave_mutex[self->bus_id], I2C_SLAVE_MUTEX_TIMEOUT); } if (i2c_used[bus_id] >= 0) { - if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreGive(slave_mutex); + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex[self->bus_id])) xSemaphoreGive(slave_mutex[self->bus_id]); nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus already used")); } @@ -570,18 +651,32 @@ STATIC mp_obj_t mp_machine_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, else { // Setup I2C slave self->slave_addr = slave_addr; - if (i2c_init_slave(self) != ESP_OK) { - if (self->slave_data) free(self->slave_data); - self->slave_data = NULL; - if (slave_mutex) xSemaphoreGive(slave_mutex); + self->slave_buflen = buff_len; + self->slave_rolen = ro_len; + if (i2c_init_slave(self, self->slave_busy) != ESP_OK) { + if (slave_mutex[self->bus_id]) xSemaphoreGive(slave_mutex[self->bus_id]); nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error installing I2C driver")); } - if (i2c_slave_task_handle[self->bus_id] == NULL) { - xTaskCreate(i2c_slave_task, "i2c_slave_task", 1024, (void *)self, 8, &i2c_slave_task_handle[self->bus_id]); + if (i2c_slave_task_handle == NULL) { + #if CONFIG_MICROPY_USE_BOTH_CORES + int res = xTaskCreate(i2c_slave_task, "i2c_slave_task", I2C_SLAVE_TASK_STACK_SIZE, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &i2c_slave_task_handle); + #else + int res = xTaskCreatePinnedToCore(i2c_slave_task, "i2c_slave_task", I2C_SLAVE_TASK_STACK_SIZE, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &i2c_slave_task_handle, MainTaskCore); + #endif + if (res != pdPASS) { + ESP_LOGE("[I2C]", "Error creating slave task"); + } + vTaskDelay(100 / portTICK_PERIOD_MS); + } + else { + if (i2c_slave_add_task(self->bus_id, &i2c_slave_task_handle, &slave_state) != ESP_OK) { + ESP_LOGW("[I2C]", "Error adding slave task"); + } } } i2c_used[bus_id] = mode; - if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreGive(slave_mutex); + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex[self->bus_id])) xSemaphoreGive(slave_mutex[self->bus_id]); + self->mode = mode; } return mp_const_none; @@ -607,6 +702,19 @@ STATIC mp_obj_t mp_machine_i2c_scan(mp_obj_t self_in) } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_scan_obj, mp_machine_i2c_scan); +//------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_is_ready(mp_obj_t self_in, mp_obj_t addr_in) +{ + mp_machine_i2c_obj_t *self = self_in; + _checkMaster(self); + + int addr = mp_obj_get_int(addr_in); + _checkAddr(addr); + + return hw_i2c_slave_detect(self, addr) ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_i2c_is_ready_obj, mp_machine_i2c_is_ready); + //---------------------------------------------------------------------------------------------------- STATIC mp_obj_t mp_machine_i2c_readfrom(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -624,12 +732,24 @@ STATIC mp_obj_t mp_machine_i2c_readfrom(mp_uint_t n_args, const mp_obj_t *pos_ar _checkAddr(args[0].u_int); - vstr_t vstr; - vstr_init_len(&vstr, args[1].u_int); - mp_i2c_master_read(self, args[0].u_int, false, 0, (uint8_t*)vstr.buf, vstr.len, false); - - // Return read data as string - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + if (args[1].u_int > 0) { + uint8_t *buf = heap_caps_malloc(args[1].u_int, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + if (buf == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating I2C data buffer")); + } + int ret = mp_i2c_master_read(self, args[0].u_int, false, 0, buf, args[1].u_int, false); + if (ret != ESP_OK) { + free(buf); + i2c_check_error(ret); + } + vstr_t vstr; + vstr_init_len(&vstr, args[1].u_int); + memcpy(vstr.buf, buf, args[1].u_int); + free(buf); + // Return read data as string + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + } + return mp_const_empty_bytes; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_readfrom_obj, 1, mp_machine_i2c_readfrom); @@ -653,8 +773,16 @@ STATIC mp_obj_t mp_machine_i2c_readfrom_into(mp_uint_t n_args, const mp_obj_t *p mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1].u_obj, &bufinfo, MP_BUFFER_WRITE); - mp_i2c_master_read(self, args[0].u_int, false, 0, bufinfo.buf, bufinfo.len, false); - + uint8_t *buf = get_buffer(bufinfo.buf, bufinfo.len); + if (buf) { + int ret = mp_i2c_master_read(self, args[0].u_int, false, 0, buf, bufinfo.len, false); + if (ret != ESP_OK) { + free(buf); + i2c_check_error(ret); + } + memcpy(bufinfo.buf, buf, bufinfo.len); + free(buf); + } // Return read length return mp_obj_new_int(bufinfo.len); } @@ -681,13 +809,18 @@ STATIC mp_obj_t mp_machine_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_arg mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1].u_obj, &bufinfo, MP_BUFFER_READ); - mp_i2c_master_write(self, args[0].u_int, 0, 0, bufinfo.buf, bufinfo.len, args[2].u_bool); + uint8_t *buf = get_buffer(bufinfo.buf, bufinfo.len); + if (buf) { + int ret = mp_i2c_master_write(self, args[0].u_int, 0, 0, buf, bufinfo.len, args[2].u_bool); + free(buf); + i2c_check_error(ret); + } return mp_obj_new_int(bufinfo.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_writeto_obj, 1, mp_machine_i2c_writeto); - +// Arguments for memory read/write methods //--------------------------------------------------------- STATIC const mp_arg_t mp_machine_i2c_mem_allowed_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, @@ -729,12 +862,20 @@ STATIC mp_obj_t mp_machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_a if (n > 0) { uint32_t addr = (uint32_t)mp_obj_get_int64(args[ARG_memaddr].u_obj); uint8_t memlen = getMemAdrLen(args[ARG_memlen].u_int, addr); - // Create the data output buffer + + uint8_t *buf = heap_caps_malloc(n, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + if (buf == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating I2C data buffer")); + } + int ret = mp_i2c_master_read(self, args[ARG_addr].u_int, memlen, addr, buf, n, args[ARG_stop].u_bool); + if (ret != ESP_OK) { + free(buf); + i2c_check_error(ret); + } vstr_t vstr; vstr_init_len(&vstr, n); - - // Transfer data - mp_i2c_master_read(self, args[ARG_addr].u_int, memlen, addr, (uint8_t *)vstr.buf, vstr.len, args[ARG_stop].u_bool); + memcpy(vstr.buf, buf, n); + free(buf); // Return read data as string return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } @@ -763,8 +904,18 @@ STATIC mp_obj_t mp_machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t * if (bufinfo.len > 0) { uint32_t addr = (uint32_t)mp_obj_get_int64(args[ARG_memaddr].u_obj); uint8_t memlen = getMemAdrLen(args[ARG_memlen].u_int, addr); - // Transfer data into buffer - mp_i2c_master_read(self, args[ARG_addr].u_int, memlen, addr, bufinfo.buf, bufinfo.len, args[ARG_stop].u_bool); + + uint8_t *buf = get_buffer(bufinfo.buf, bufinfo.len); + if (buf) { + // Transfer data into buffer + int ret = mp_i2c_master_read(self, args[ARG_addr].u_int, memlen, addr, buf, bufinfo.len, args[ARG_stop].u_bool); + if (ret != ESP_OK) { + free(buf); + i2c_check_error(ret); + } + memcpy(bufinfo.buf, buf, bufinfo.len); + free(buf); + } } return mp_obj_new_int(bufinfo.len); } @@ -783,16 +934,24 @@ STATIC mp_obj_t mp_machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_ar _checkAddr(args[ARG_addr].u_int); - // Get the input data buffer - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); - - uint32_t addr = (uint32_t)mp_obj_get_int64(args[ARG_memaddr].u_obj); - uint8_t memlen = getMemAdrLen(args[ARG_memlen].u_int, addr); - // Transfer data from buffer - mp_i2c_master_write(self, args[ARG_addr].u_int, memlen, addr, bufinfo.buf, bufinfo.len, true); + uint32_t addr = (uint32_t)mp_obj_get_int64(args[ARG_memaddr].u_obj); + uint8_t memlen = getMemAdrLen(args[ARG_memlen].u_int, addr); + + uint8_t *buf = NULL; + int len = 0; + if (args[ARG_buf].u_obj != mp_const_none) { + // Get the input data buffer + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); + buf = get_buffer(bufinfo.buf, bufinfo.len); + len = bufinfo.len; + } - return mp_obj_new_int(bufinfo.len); + // Transfer address and data + int ret = mp_i2c_master_write(self, args[ARG_addr].u_int, memlen, addr, buf, len, true); + if (buf) free(buf); + i2c_check_error(ret); + return mp_obj_new_int(len); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_writeto_mem_obj, 1, mp_machine_i2c_writeto_mem); @@ -801,14 +960,12 @@ STATIC mp_obj_t mp_machine_i2c_deinit(mp_obj_t self_in) { mp_machine_i2c_obj_t *self = self_in; if (i2c_used[self->bus_id] >= 0) { - if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex[self->bus_id])) xSemaphoreTake(slave_mutex[self->bus_id], I2C_SLAVE_MUTEX_TIMEOUT); - i2c_driver_delete(self->bus_id); i2c_used[self->bus_id] = -1; - if (self->slave_data) free(self->slave_data); - self->slave_data = NULL; + i2c_driver_delete(self->bus_id); - if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreGive(slave_mutex); + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex[self->bus_id])) xSemaphoreGive(slave_mutex[self->bus_id]); } return mp_const_none; @@ -847,7 +1004,8 @@ STATIC mp_obj_t mp_machine_i2c_begin(mp_obj_t self_in, mp_obj_t rxlen_in) { if (self->rx_data) free(self->rx_data); self->rx_data = NULL; if (rxbuflen) { - self->rx_data = malloc(rxbuflen); + //self->rx_data = malloc(rxbuflen); + self->rx_data = heap_caps_malloc(rxbuflen, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); if (self->rx_data == NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating rx buffer")); } @@ -1032,54 +1190,58 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_end_obj, mp_machine_i2c_end); // ==== I2C slave functions =================================================================== // ============================================================================================ +//----------------------------------------------------------------- +void _check_addr_len(mp_machine_i2c_obj_t *self, int addr, int len) +{ + if ((len < 1) || (len > self->slave_buflen)) { + mp_raise_ValueError("Length out of range"); + } + if (addr >= self->slave_buflen) { + mp_raise_ValueError("Address not in slave data buffer"); + } + if ((addr + len) > self->slave_buflen) { + mp_raise_ValueError("Data outside buffer"); + } +} -//--------------------------------------------------------------------------- -STATIC mp_obj_t mp_machine_i2c_slave_write(mp_obj_t self_in, mp_obj_t buf_in) +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_slave_setdata(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t addr_in) { mp_machine_i2c_obj_t *self = self_in; _checkSlave(self); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + int addr = mp_obj_get_int(addr_in); + _check_addr_len(self, addr, bufinfo.len); - if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + if (slave_mutex[self->bus_id]) xSemaphoreTake(slave_mutex[self->bus_id], I2C_SLAVE_MUTEX_TIMEOUT); - int res = i2c_slave_write_buffer(self->bus_id, bufinfo.buf, bufinfo.len, 500 / portTICK_PERIOD_MS); + int res = i2c_slave_write_buffer(self->bus_id, bufinfo.buf, addr, bufinfo.len, I2C_SLAVE_MUTEX_TIMEOUT); - if (slave_mutex) xSemaphoreGive(slave_mutex); + if (slave_mutex[self->bus_id]) xSemaphoreGive(slave_mutex[self->bus_id]); - if (res < 0) return mp_const_false; - return mp_obj_new_int(res); + if (res <= 0) return mp_const_false; + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_i2c_slave_write_obj, mp_machine_i2c_slave_write); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_i2c_slave_setdata_obj, mp_machine_i2c_slave_setdata); -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t mp_machine_i2c_slave_setdata(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t addr_in) +//--------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_slave_reset_busy(mp_obj_t self_in) { mp_machine_i2c_obj_t *self = self_in; _checkSlave(self); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - int addr = mp_obj_get_int(addr_in); + if (slave_mutex[self->bus_id]) xSemaphoreTake(slave_mutex[self->bus_id], I2C_SLAVE_MUTEX_TIMEOUT); - if (addr >= self->slave_buflen) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Address not in slave data buffer")); - } - - if ((addr + bufinfo.len) > self->slave_buflen) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Data does not fit into slave data buffer")); - } + int res = i2c_slave_reset_busy(self->bus_id, I2C_SLAVE_MUTEX_TIMEOUT); - if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + if (slave_mutex[self->bus_id]) xSemaphoreGive(slave_mutex[self->bus_id]); - memcpy(self->slave_data + addr, bufinfo.buf, bufinfo.len); - - if (slave_mutex) xSemaphoreGive(slave_mutex); - - return mp_const_none; + if (res <= 0) return mp_const_false; + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_i2c_slave_setdata_obj, mp_machine_i2c_slave_setdata); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_slave_reset_busy_obj, mp_machine_i2c_slave_reset_busy); //----------------------------------------------------------------------------------------------- STATIC mp_obj_t mp_machine_i2c_slave_getdata(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t len_in) @@ -1089,65 +1251,144 @@ STATIC mp_obj_t mp_machine_i2c_slave_getdata(mp_obj_t self_in, mp_obj_t addr_in, int addr = mp_obj_get_int(addr_in); int len = mp_obj_get_int(len_in); + _check_addr_len(self, addr, len); - if (addr >= self->slave_buflen) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Address not in slave data buffer")); + uint8_t *databuf = malloc(len); + if (databuf == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating data buffer")); } - if ((addr + len) > self->slave_buflen) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Requested data outside buffer")); - } - - if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + mp_obj_t data; + if (slave_mutex[self->bus_id]) xSemaphoreTake(slave_mutex[self->bus_id], I2C_SLAVE_MUTEX_TIMEOUT); - mp_obj_t data = mp_obj_new_bytes(self->slave_data + addr, len); + int res = i2c_slave_read_buffer(self->bus_id, databuf, addr, len, I2C_SLAVE_MUTEX_TIMEOUT); + if (res > 0) data = mp_obj_new_bytes(databuf, res); + else data = mp_const_empty_bytes; - if (slave_mutex) xSemaphoreGive(slave_mutex); + if (slave_mutex[self->bus_id]) xSemaphoreGive(slave_mutex[self->bus_id]); + free(databuf); // Return read data as byte array return data; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_i2c_slave_getdata_obj, mp_machine_i2c_slave_getdata); //---------------------------------------------------------------------------------------------- -STATIC mp_obj_t mp_machine_i2c_slave_callback(mp_obj_t self_in, mp_obj_t type_in, mp_obj_t func) +STATIC mp_obj_t mp_machine_i2c_slave_callback(mp_obj_t self_in, mp_obj_t func, mp_obj_t type_in) { mp_machine_i2c_obj_t *self = self_in; _checkSlave(self); + int type = mp_obj_get_int(type_in); + if ((!MP_OBJ_IS_FUN(func)) && (!MP_OBJ_IS_METH(func)) && (func != mp_const_none)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Function argument required")); } - int ftype = mp_obj_get_int(type_in); - if ((ftype < 1) || (ftype > 3)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Wrong callback type")); + if ((type < 0) || (type > 7)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid callback type")); } - if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + if (slave_mutex[self->bus_id]) xSemaphoreTake(slave_mutex[self->bus_id], I2C_SLAVE_MUTEX_TIMEOUT); - if (func == mp_const_none) { - if (ftype == 1) self->slave_cb_read = NULL; - else if (ftype == 2) self->slave_cb_write = NULL; - else if (ftype == 3) self->slave_cb_data = NULL; - } - else { - if (ftype == 1) self->slave_cb_read = func; - else if (ftype == 2) self->slave_cb_write = func; - else if (ftype == 3) self->slave_cb_data = func; - } + if (func == mp_const_none) self->slave_cb = NULL; + else self->slave_cb = func; + self->slave_cbtype = type; - if (slave_mutex) xSemaphoreGive(slave_mutex); + if (slave_mutex[self->bus_id]) xSemaphoreGive(slave_mutex[self->bus_id]); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_i2c_slave_callback_obj, mp_machine_i2c_slave_callback); +//---------------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_timing(size_t n_args, const mp_obj_t *args, int type) +{ + mp_machine_i2c_obj_t *self = args[0]; + + int setup_time = -1; + int hold_time = -1; + if (n_args == 3) { + setup_time = mp_obj_get_int(args[1]); + hold_time = mp_obj_get_int(args[2]); + if (type == 1) i2c_set_start_timing(self->bus_id, setup_time, hold_time); + else if (type == 2) i2c_set_stop_timing(self->bus_id, setup_time, hold_time); + else if (type == 3) i2c_set_data_timing(self->bus_id, setup_time, hold_time); + else if (type == 4) i2c_set_period(self->bus_id, setup_time, hold_time); + } + if (type == 1) i2c_get_start_timing(self->bus_id, &setup_time, &hold_time); + else if (type == 2) i2c_get_stop_timing(self->bus_id, &setup_time, &hold_time); + else if (type == 3) i2c_get_data_timing(self->bus_id, &setup_time, &hold_time); + else if (type == 4) i2c_get_period(self->bus_id, &setup_time, &hold_time); + + mp_obj_t tuple[2]; + + tuple[0] = mp_obj_new_int(setup_time); + tuple[1] = mp_obj_new_int(hold_time); + return mp_obj_new_tuple(2, tuple); +} + +//------------------------------------------------------------------------------ +STATIC mp_obj_t mp_machine_i2c_start_timing(size_t n_args, const mp_obj_t *args) +{ + mp_obj_t res = mp_machine_i2c_timing(n_args, args, 1); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_i2c_start_timing_obj, 1, 3, mp_machine_i2c_start_timing); + +//----------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_stop_timing(size_t n_args, const mp_obj_t *args) +{ + mp_obj_t res = mp_machine_i2c_timing(n_args, args, 2); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_i2c_stop_timing_obj, 1, 3, mp_machine_i2c_stop_timing); + +//----------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_data_timing(size_t n_args, const mp_obj_t *args) +{ + mp_obj_t res = mp_machine_i2c_timing(n_args, args, 3); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_i2c_data_timing_obj, 1, 3, mp_machine_i2c_data_timing); + +//------------------------------------------------------------------------------ +STATIC mp_obj_t mp_machine_i2c_clock_timing(size_t n_args, const mp_obj_t *args) +{ + mp_obj_t res = mp_machine_i2c_timing(n_args, args, 4); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_i2c_clock_timing_obj, 1, 3, mp_machine_i2c_clock_timing); + +//------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_timeout(size_t n_args, const mp_obj_t *args) +{ + mp_machine_i2c_obj_t *self = args[0]; + _checkMaster(self); + + int tmo = -1; + if (n_args == 2) { + tmo = mp_obj_get_int(args[1]); + i2c_set_timeout(self->bus_id, tmo * 80); + } + i2c_get_timeout(self->bus_id, &tmo); + tmo /= 80; + + return mp_obj_new_int(tmo); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_i2c_timeout_obj, 1, 2, mp_machine_i2c_timeout); + //=================================================================== STATIC const mp_rom_map_elem_t mp_machine_i2c_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&mp_machine_i2c_init_obj }, { MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&mp_machine_i2c_deinit_obj }, { MP_ROM_QSTR(MP_QSTR_scan), (mp_obj_t)&mp_machine_i2c_scan_obj }, + { MP_ROM_QSTR(MP_QSTR_is_ready), (mp_obj_t)&mp_machine_i2c_is_ready_obj }, + { MP_ROM_QSTR(MP_QSTR_start_timing), (mp_obj_t)&mp_machine_i2c_start_timing_obj }, + { MP_ROM_QSTR(MP_QSTR_stop_timing), (mp_obj_t)&mp_machine_i2c_stop_timing_obj }, + { MP_ROM_QSTR(MP_QSTR_data_timing), (mp_obj_t)&mp_machine_i2c_data_timing_obj }, + { MP_ROM_QSTR(MP_QSTR_clock_timing), (mp_obj_t)&mp_machine_i2c_clock_timing_obj }, + { MP_ROM_QSTR(MP_QSTR_timeout), (mp_obj_t)&mp_machine_i2c_timeout_obj }, // Standard methods { MP_ROM_QSTR(MP_QSTR_readfrom), (mp_obj_t)&mp_machine_i2c_readfrom_obj }, @@ -1155,7 +1396,7 @@ STATIC const mp_rom_map_elem_t mp_machine_i2c_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_writeto), (mp_obj_t)&mp_machine_i2c_writeto_obj }, { MP_ROM_QSTR(MP_QSTR_setdata), (mp_obj_t)&mp_machine_i2c_slave_setdata_obj }, { MP_ROM_QSTR(MP_QSTR_getdata), (mp_obj_t)&mp_machine_i2c_slave_getdata_obj }, - { MP_ROM_QSTR(MP_QSTR_slavewrite), (mp_obj_t)&mp_machine_i2c_slave_write_obj }, + { MP_ROM_QSTR(MP_QSTR_resetbusy), (mp_obj_t)&mp_machine_i2c_slave_reset_busy_obj }, { MP_ROM_QSTR(MP_QSTR_callback), (mp_obj_t)&mp_machine_i2c_slave_callback_obj }, // Memory methods @@ -1179,9 +1420,10 @@ STATIC const mp_rom_map_elem_t mp_machine_i2c_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_SLAVE), MP_OBJ_NEW_SMALL_INT(I2C_MODE_SLAVE) }, { MP_OBJ_NEW_QSTR(MP_QSTR_READ), MP_OBJ_NEW_SMALL_INT(I2C_MASTER_READ) }, { MP_OBJ_NEW_QSTR(MP_QSTR_WRITE), MP_OBJ_NEW_SMALL_INT(I2C_MASTER_WRITE) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_CB_READ), MP_OBJ_NEW_SMALL_INT(1) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_CB_WRITE), MP_OBJ_NEW_SMALL_INT(2) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_CB_DATA), MP_OBJ_NEW_SMALL_INT(3) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CBTYPE_NONE), MP_OBJ_NEW_SMALL_INT(I2C_SLAVE_CBTYPE_NONE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CBTYPE_ADDR), MP_OBJ_NEW_SMALL_INT(I2C_SLAVE_CBTYPE_ADDR) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CBTYPE_RXDATA), MP_OBJ_NEW_SMALL_INT(I2C_SLAVE_CBTYPE_DATA_RX) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CBTYPE_TXDATA), MP_OBJ_NEW_SMALL_INT(I2C_SLAVE_CBTYPE_DATA_TX) }, }; STATIC MP_DEFINE_CONST_DICT(mp_machine_i2c_locals_dict, mp_machine_i2c_locals_dict_table); diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c b/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c index fe107835..699e634a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c @@ -37,7 +37,7 @@ #include "py/stream.h" #include "py/mphal.h" #include "modmachine.h" -#include "machine_pin.h" +#include "py/objstr.h" #include "machine_hw_spi.h" @@ -107,9 +107,11 @@ void machine_hw_spi_init_internal( self->spi.buscfg = SPIbus_configs[self->spi.spihost]; // Init pins - gpio_pad_select_gpio(cs); - gpio_set_direction(cs, GPIO_MODE_OUTPUT); - gpio_set_level(cs, 1); + if (cs >= 0) { + gpio_pad_select_gpio(cs); + gpio_set_direction(cs, GPIO_MODE_OUTPUT); + gpio_set_level(cs, 1); + } gpio_pad_select_gpio(miso); gpio_pad_select_gpio(mosi); gpio_pad_select_gpio(sck); @@ -396,7 +398,7 @@ STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf, return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto); -#include "py/objstr.h" + //--------------------------------------------------------------------------------------------------------- STATIC mp_obj_t mp_machine_spi_read_from_mem(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_i2s.c b/MicroPython_BUILD/components/micropython/esp32/machine_i2s.c new file mode 100644 index 00000000..590c41fb --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/machine_i2s.c @@ -0,0 +1,442 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 M5Stack (https://github.com/m5stack) + * + * 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 "py/obj.h" +#include "py/objstr.h" +#include "driver/i2s.h" +#include "driver/dac.h" +#include "py/runtime.h" +#include "py/mperrno.h" + + +typedef struct { + mp_obj_base_t base; + i2s_port_t port; + i2s_config_t config; + i2s_channel_t num_channels; + uint16_t volume; +} machine_i2s_obj_t; + +extern const mp_obj_type_t machine_i2s_type; + + +STATIC void machine_i2s_obj_init_helper(machine_i2s_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_rate, ARG_bits, ARG_channel_format, ARG_data_format, ARG_dma_count, ARG_dma_len}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN} }, + { MP_QSTR_rate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16000} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} }, + { MP_QSTR_channel_format, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2S_CHANNEL_FMT_RIGHT_LEFT} }, + { MP_QSTR_data_format, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = I2S_COMM_FORMAT_I2S_MSB} }, + { MP_QSTR_dma_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_dma_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1024} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + self->config.mode = (i2s_mode_t)(args[ARG_mode].u_int); + self->config.sample_rate = (int)args[ARG_rate].u_int; + self->config.bits_per_sample = (i2s_bits_per_sample_t)args[ARG_bits].u_int; + self->config.channel_format = (i2s_channel_fmt_t)args[ARG_channel_format].u_int; + self->config.communication_format = (i2s_comm_format_t)args[ARG_data_format].u_int; + // self->config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL3, + self->config.intr_alloc_flags = 0, + self->config.dma_buf_count = (int)args[ARG_dma_count].u_int; + self->config.dma_buf_len = (int)args[ARG_dma_len].u_int; + self->config.use_apll = 0; + + self->num_channels = 2; + self->volume = 100; + + if (i2s_driver_install(self->port, &self->config, 0, NULL) != ESP_OK) { + mp_raise_ValueError("I2S: failed to enable"); + } + + if ((self->config.mode & I2S_MODE_DAC_BUILT_IN) || (self->config.mode & I2S_MODE_PDM)) { + i2s_set_pin(self->port, NULL); + i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN); // default + } + + i2s_set_clk(self->port, self->config.sample_rate, self->config.bits_per_sample, 1); +} + +//---------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_int_t port = I2S_NUM_0; + if (n_args > 0) { + port = mp_obj_get_int(args[0]); + n_args--; + args++; + } + + if (port >= I2S_NUM_MAX || port < I2S_NUM_0) { + mp_raise_ValueError("invalid I2S peripheral"); + } + + // Create I2S object + machine_i2s_obj_t *self = m_new_obj(machine_i2s_obj_t); + self->base.type = &machine_i2s_type; + self->port = port; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_i2s_obj_init_helper(self, n_args, args, &kw_args); + return (machine_i2s_obj_t*)self; // discard const +} + +//---------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_i2s_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_init_obj, 2, machine_i2s_init); + +//---------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_deinit(mp_obj_t self_in) { + const machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + // char sample[8] = {0}; + // i2s_push_sample(self->port, (char *)sample, portMAX_DELAY); + if (self->config.mode & I2S_MODE_DAC_BUILT_IN) { + dac_output_voltage(DAC_CHANNEL_1, 0); + i2s_set_dac_mode(I2S_DAC_CHANNEL_DISABLE); + } + i2s_driver_uninstall(self->port); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_i2s_deinit_obj, machine_i2s_deinit); + +//---------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_start(mp_obj_t self_in) { + const machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + i2s_start(self->port); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_i2s_start_obj, machine_i2s_start); + +//---------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_stop(mp_obj_t self_in) { + const machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->config.mode & I2S_MODE_DAC_BUILT_IN) + dac_output_voltage(DAC_CHANNEL_1, 0); + i2s_stop(self->port); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_i2s_stop_obj, machine_i2s_stop); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_sample_rates(mp_obj_t self_in, mp_obj_t rate) { + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->config.sample_rate = mp_obj_get_int(rate); + i2s_set_sample_rates(self->port, (uint32_t)(self->config.sample_rate)); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_sample_rates_obj, machine_i2s_sample_rates); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_bits_per_sample(mp_obj_t self_in, mp_obj_t bits) { + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->config.bits_per_sample = (i2s_bits_per_sample_t)mp_obj_get_int(bits); + i2s_set_clk(self->port, self->config.sample_rate, self->config.bits_per_sample, 1); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_bits_per_sample_obj, machine_i2s_bits_per_sample); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_set_channel(mp_obj_t self_in, mp_obj_t channel) { + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->num_channels = (i2s_channel_t)mp_obj_get_int(channel); + i2s_set_clk(self->port, self->config.sample_rate, self->config.bits_per_sample, 1); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_set_channel_obj, machine_i2s_set_channel); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_set_dac_mode(mp_obj_t self_in, mp_obj_t dac_mode) { + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uint8_t _dac_mode = mp_obj_get_int(dac_mode); + + if (self->port == I2S_NUM_0) { + i2s_set_dac_mode((i2s_dac_mode_t)_dac_mode); + } else { + mp_raise_ValueError("PDM and built-in DAC functions are only supported on I2S0 for current ESP32 chip."); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_set_dac_mode_obj, machine_i2s_set_dac_mode); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_set_adc_mode(mp_obj_t self_in, mp_obj_t pin) { + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uint8_t adc_pin = mp_obj_get_int(pin); + uint8_t adc1_channel[] = { + ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */ + ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */ + ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */ + ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */ + ADC1_CHANNEL_0, /*!< ADC1 channel 0 is GPIO36 */ + ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */ + ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */ + ADC1_CHANNEL_3 /*!< ADC1 channel 3 is GPIO39 */ + }; + + if (adc_pin < 32 || adc_pin > 39) { + mp_raise_ValueError("built-in ADC functions are only supported ADC1 channel."); + } + + if (self->port == I2S_NUM_0) { + i2s_set_adc_mode(ADC_UNIT_1, (adc1_channel_t)(adc1_channel[adc_pin - 32])); + } else { + mp_raise_ValueError("built-in ADC functions are only supported on I2S0 for current ESP32 chip."); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_set_adc_mode_obj, machine_i2s_set_adc_mode); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_adc_enable(mp_obj_t self_in, mp_obj_t enable) { + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + uint8_t _enable = mp_obj_get_int(enable); + + if (_enable) { + i2s_adc_enable(self->port); + } else { + i2s_adc_disable(self->port); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_adc_enable_obj, machine_i2s_adc_enable); + +//------------------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_set_pin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + const mp_arg_t allowed_args[] = { + { MP_QSTR_bck, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_ws, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_out, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_in, MP_ARG_INT, { .u_int = -1 } }, + }; + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t bck_io_num = args[0].u_int; + mp_int_t ws_io_num = args[1].u_int; + mp_int_t data_out_num = args[2].u_int; + mp_int_t data_in_num = -1; + + if (args[3].u_int >= 0) { + data_in_num = args[3].u_int; + } + + i2s_pin_config_t pin_config = { + .bck_io_num = bck_io_num, + .ws_io_num = ws_io_num, + .data_out_num = data_out_num, + .data_in_num = data_in_num, + }; + + if (i2s_set_pin(self->port, &pin_config) != ESP_OK) { + i2s_driver_uninstall(self->port); + mp_raise_ValueError("I2S: failed to set pins in"); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_set_pin_obj, 3, machine_i2s_set_pin); + +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_set_volume(mp_obj_t self_in, mp_obj_t volume) { + machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->volume = mp_obj_get_int(volume); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_set_volume_obj, machine_i2s_set_volume); + +//---------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_read(const mp_obj_t self_in, mp_obj_t buf_len) { + const machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + size_t _buf_len = mp_obj_get_int(buf_len); + vstr_t vstr; + int16_t* sample; + vstr_init_len(&vstr, _buf_len); + + if (i2s_read_bytes(self->port, (char*)vstr.buf, vstr.len, portMAX_DELAY) == ESP_FAIL) { + mp_raise_OSError(MP_EIO); + return mp_const_none; + } + // MAX: 28671 MIN: 24576 + if (self->config.mode & I2S_MODE_ADC_BUILT_IN) { + sample = (int16_t*)(vstr.buf); + for (uint16_t i=0; i < vstr.len/2; i++) { + sample[i] -= 26623; + sample[i] *= 4; + } + } + + // Return read data as string + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_read_obj, machine_i2s_read); + +//---------------------------------------------------------------------- +STATIC mp_obj_t machine_i2s_write(const mp_obj_t self_in, mp_obj_t buf_in) { + const machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + + // support only 16 bit buffers for now + if(self->config.bits_per_sample != I2S_BITS_PER_SAMPLE_16BIT) { + mp_raise_ValueError("support only 16 bit buffers for now"); + return mp_const_none; + } + + if (self->config.mode & I2S_MODE_DAC_BUILT_IN) { + + uint8_t buf_bytes_per_sample = (self->config.bits_per_sample / 8); + uint32_t num_samples = bufinfo.len / buf_bytes_per_sample / self->num_channels; + + // pointer to left / right sample position + char *ptr_l = bufinfo.buf; + char *ptr_r = bufinfo.buf + buf_bytes_per_sample; + uint8_t stride = buf_bytes_per_sample * self->num_channels;; + + if (self->num_channels == (i2s_channel_t)1) { + ptr_r = ptr_l; + } + + int bytes_pushed = 0; + TickType_t max_wait = 20 / portTICK_PERIOD_MS; // portMAX_DELAY = bad idea + for (int i = 0; i < num_samples; i++) { + + // assume 16 bit src bit_depth + short left = *(short *) ptr_l; + short right = *(short *) ptr_r; + left = (int)left * self->volume / 100; + right = (int)right * self->volume / 100; + + // The built-in DAC wants unsigned samples, so we shift the range + // from -32768-32767 to 0-65535. + left = left + 0x8000; + right = right + 0x8000; + + uint32_t sample = (uint16_t) left; + sample = (sample << 16 & 0xffff0000) | ((uint16_t) right); + bytes_pushed = i2s_push_sample(self->port, (const char*) &sample, max_wait); + + // DMA buffer full - retry + if (bytes_pushed == 0) { + i--; + } else { + ptr_l += stride; + ptr_r += stride; + } + } + } else { + + if (i2s_write_bytes(self->port, bufinfo.buf, bufinfo.len, 0) == ESP_FAIL) + mp_raise_OSError(MP_EIO); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_write_obj, machine_i2s_write); + +//---------------------------------------------------------------------- +STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = { + + // Standard methods + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2s_init_obj)}, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2s_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_i2s_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_i2s_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&machine_i2s_sample_rates_obj) }, + { MP_ROM_QSTR(MP_QSTR_bits), MP_ROM_PTR(&machine_i2s_bits_per_sample_obj) }, + { MP_ROM_QSTR(MP_QSTR_nchannels), MP_ROM_PTR(&machine_i2s_set_channel_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_pin), MP_ROM_PTR(&machine_i2s_set_pin_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_dac_mode), MP_ROM_PTR(&machine_i2s_set_dac_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_adc_pin), MP_ROM_PTR(&machine_i2s_set_adc_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_adc_enable), MP_ROM_PTR(&machine_i2s_adc_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_i2s_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2s_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_volume), MP_ROM_PTR(&machine_i2s_set_volume_obj) }, + + // Constants + { MP_ROM_QSTR(MP_QSTR_I2S_NUM_0), MP_ROM_INT(I2S_NUM_0) }, + { MP_ROM_QSTR(MP_QSTR_I2S_NUM_1), MP_ROM_INT(I2S_NUM_1) }, + + { MP_ROM_QSTR(MP_QSTR_MODE_MASTER), MP_ROM_INT(I2S_MODE_MASTER) }, + { MP_ROM_QSTR(MP_QSTR_MODE_SLAVE), MP_ROM_INT(I2S_MODE_SLAVE) }, + { MP_ROM_QSTR(MP_QSTR_MODE_TX), MP_ROM_INT(I2S_MODE_TX) }, + { MP_ROM_QSTR(MP_QSTR_MODE_RX), MP_ROM_INT(I2S_MODE_RX) }, + { MP_ROM_QSTR(MP_QSTR_MODE_DAC_BUILT_IN), MP_ROM_INT(I2S_MODE_DAC_BUILT_IN) }, + { MP_ROM_QSTR(MP_QSTR_MODE_ADC_BUILT_IN), MP_ROM_INT(I2S_MODE_ADC_BUILT_IN) }, + { MP_ROM_QSTR(MP_QSTR_MODE_PDM), MP_ROM_INT(I2S_MODE_PDM) }, + + { MP_ROM_QSTR(MP_QSTR_CHANNEL_RIGHT_LEFT),MP_ROM_INT(I2S_CHANNEL_FMT_RIGHT_LEFT) }, + { MP_ROM_QSTR(MP_QSTR_CHANNEL_ALL_RIGHT), MP_ROM_INT(I2S_CHANNEL_FMT_ALL_RIGHT) }, + { MP_ROM_QSTR(MP_QSTR_CHANNEL_ALL_LEFT), MP_ROM_INT(I2S_CHANNEL_FMT_ALL_LEFT) }, + { MP_ROM_QSTR(MP_QSTR_CHANNEL_ONLY_RIGHT),MP_ROM_INT(I2S_CHANNEL_FMT_ONLY_RIGHT) }, + { MP_ROM_QSTR(MP_QSTR_CHANNEL_ONLY_LEFT), MP_ROM_INT(I2S_CHANNEL_FMT_ONLY_LEFT) }, + + { MP_ROM_QSTR(MP_QSTR_FORMAT_I2S), MP_ROM_INT(I2S_COMM_FORMAT_I2S) }, + { MP_ROM_QSTR(MP_QSTR_FORMAT_I2S_MSB), MP_ROM_INT(I2S_COMM_FORMAT_I2S_MSB) }, + { MP_ROM_QSTR(MP_QSTR_FORMAT_I2S_LSB), MP_ROM_INT(I2S_COMM_FORMAT_I2S_LSB) }, + { MP_ROM_QSTR(MP_QSTR_FORMAT_PCM), MP_ROM_INT(I2S_COMM_FORMAT_PCM) }, + { MP_ROM_QSTR(MP_QSTR_FORMAT_PCM_SHORT), MP_ROM_INT(I2S_COMM_FORMAT_PCM_SHORT) }, + { MP_ROM_QSTR(MP_QSTR_FORMAT_PCM_LONG), MP_ROM_INT(I2S_COMM_FORMAT_PCM_LONG) }, + + { MP_ROM_QSTR(MP_QSTR_DAC_DISABLE), MP_ROM_INT(I2S_DAC_CHANNEL_DISABLE) }, + { MP_ROM_QSTR(MP_QSTR_DAC_RIGHT_EN), MP_ROM_INT(I2S_DAC_CHANNEL_RIGHT_EN) }, + { MP_ROM_QSTR(MP_QSTR_DAC_LEFT_EN), MP_ROM_INT(I2S_DAC_CHANNEL_LEFT_EN) }, + { MP_ROM_QSTR(MP_QSTR_DAC_BOTH_EN), MP_ROM_INT(I2S_DAC_CHANNEL_BOTH_EN) }, +}; + +STATIC MP_DEFINE_CONST_DICT(machine_i2s_locals_dict, machine_i2s_locals_dict_table); + +const mp_obj_type_t machine_i2s_type = { + { &mp_type_type }, + .name = MP_QSTR_I2S, + .make_new = machine_i2s_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_i2s_locals_dict, +}; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c b/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c index 3a24498a..8df7aeb0 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c @@ -64,8 +64,11 @@ STATIC void machine_neopixel_print(const mp_print_t *print, mp_obj_t self_in, mp machine_neopixel_obj_t *self = self_in; if (self->px.pixels != NULL) { - mp_printf(print, "Neopixel(Pin=%d, Pixels: %d, bit/pix=%d, RMTChannel=%d, PixBufLen=%u, Color order: %s\n", - self->gpio_num, self->px.pixel_count, self->px.nbits, self->channel, sizeof(uint32_t) * self->px.pixel_count, self->px.color_order); + char colorder[5]; + sprintf(colorder, self->px.color_order); + if (self->px.nbits == 24) colorder[3] = '\0'; + mp_printf(print, "Neopixel(Pin=%d, Pixels: %d, bit/pix=%d, RMTChannel=%d, PixBufLen=%u, Color order: '%s'\n", + self->gpio_num, self->px.pixel_count, self->px.nbits, self->channel, sizeof(uint32_t) * self->px.pixel_count, colorder); mp_printf(print, " Timings (ns): T1H=%d, T1L=%d, T0H=%d, T0L=%d, Treset=%d\n)", self->px.timings.mark.duration0 * RMT_PERIOD_NS, self->px.timings.mark.duration1 * RMT_PERIOD_NS, self->px.timings.space.duration0 * RMT_PERIOD_NS, self->px.timings.space.duration1 * RMT_PERIOD_NS, @@ -95,9 +98,7 @@ STATIC mp_obj_t machine_neopixel_make_new(const mp_obj_type_t *type, size_t n_ar mp_raise_ValueError("Cannot acquire RMT channel"); } - int8_t pin; - if (MP_OBJ_IS_INT(args[ARG_pin].u_obj)) pin = mp_obj_get_int(args[ARG_pin].u_obj); - else pin = machine_pin_get_id(args[ARG_pin].u_obj); + int8_t pin = machine_pin_get_gpio(args[ARG_pin].u_obj); int pixels = args[ARG_pixels].u_int; int wstype = args[ARG_type].u_int; @@ -160,7 +161,7 @@ STATIC mp_obj_t machine_neopixel_make_new(const mp_obj_type_t *type, size_t n_ar self->base.type = &machine_neopixel_type; np_clear(&self->px); - np_show(&self->px, self->channel, 1); + np_show(&self->px, self->channel); return MP_OBJ_FROM_PTR(self); @@ -180,7 +181,7 @@ STATIC mp_obj_t machine_neopixel_deinit(mp_obj_t self_in) np_check(self); np_clear(&self->px); - np_show(&self->px, self->channel, 1); + np_show(&self->px, self->channel); neopixel_deinit(self->channel); @@ -201,7 +202,7 @@ STATIC mp_obj_t machine_neopixel_clear(mp_obj_t self_in) np_clear(&self->px); MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); return mp_const_none; } @@ -214,7 +215,7 @@ STATIC mp_obj_t machine_neopixel_show(mp_obj_t self_in) np_check(self); MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); return mp_const_none; } @@ -254,7 +255,7 @@ STATIC mp_obj_t machine_neopixel_set(size_t n_args, const mp_obj_t *pos_args, mp if (args[4].u_bool) { MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); } @@ -295,7 +296,7 @@ STATIC mp_obj_t machine_neopixel_set_white(size_t n_args, const mp_obj_t *pos_ar if (args[3].u_bool) { MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); } } @@ -341,7 +342,7 @@ STATIC mp_obj_t machine_neopixel_setHSB(size_t n_args, const mp_obj_t *pos_args, if (args[5].u_bool) { MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); } @@ -392,7 +393,7 @@ STATIC mp_obj_t machine_neopixel_setHSB_int(size_t n_args, const mp_obj_t *pos_a if (args[5].u_bool) { MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); } @@ -400,32 +401,56 @@ STATIC mp_obj_t machine_neopixel_setHSB_int(size_t n_args, const mp_obj_t *pos_a } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_neopixel_setHSB_int_obj, 5, machine_neopixel_setHSB_int); -//--------------------------------------------------------------------- -STATIC mp_obj_t machine_neopixel_get(mp_obj_t self_in, mp_obj_t pos_in) +//----------------------------------------------------------------------- +STATIC mp_obj_t machine_neopixel_get(size_t n_args, const mp_obj_t *args) { - machine_neopixel_obj_t *self = self_in; + machine_neopixel_obj_t *self = args[0]; np_check(self); - int pos = mp_obj_get_int(pos_in); + uint8_t white; + uint32_t icolor; + int pos = mp_obj_get_int(args[1]); if (pos < 1) pos = 1; if (pos > self->px.pixel_count) pos = self->px.pixel_count; - - uint8_t white; - uint32_t icolor = np_get_pixel_color(&self->px, pos-1, &white); - if (self->px.nbits == 24) { - return mp_obj_new_int(icolor); + int cnt = 0; + if (n_args > 2) { + cnt = mp_obj_get_int(args[2]); + if (cnt < 1) cnt = 1; + if ((cnt + pos - 1) > self->px.pixel_count) cnt = self->px.pixel_count - pos + 1; } - else { - mp_obj_t tuple[2]; + if (cnt < 2) { + icolor = np_get_pixel_color(&self->px, pos-1, &white); + if (self->px.nbits == 24) { + return mp_obj_new_int(icolor); + } + else { + mp_obj_t tuple[2]; - tuple[0] = mp_obj_new_int(icolor); - tuple[1] = mp_obj_new_int(white); + tuple[0] = mp_obj_new_int(icolor); + tuple[1] = mp_obj_new_int(white); - return mp_obj_new_tuple(2, tuple); + return mp_obj_new_tuple(2, tuple); + } + } + else { + mp_obj_t pix_tuple[cnt]; + mp_obj_t tuple[2]; + for (int i=0; ipx, pos+i-1, &white); + if (self->px.nbits == 24) { + pix_tuple[i] = mp_obj_new_int(icolor); + } + else { + tuple[0] = mp_obj_new_int(icolor); + tuple[1] = mp_obj_new_int(white); + + pix_tuple[i] = mp_obj_new_tuple(2, tuple); + } + } + return mp_obj_new_tuple(cnt, pix_tuple); } - } -MP_DEFINE_CONST_FUN_OBJ_2(machine_neopixel_get_obj, machine_neopixel_get); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_neopixel_get_obj, 2, 3, machine_neopixel_get); //----------------------------------------------------------------------------------------------------- STATIC mp_obj_t machine_neopixel_brightness(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) @@ -444,7 +469,7 @@ STATIC mp_obj_t machine_neopixel_brightness(size_t n_args, const mp_obj_t *pos_a self->px.brightness = bright & 0xFF; if (args[1].u_bool) { MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); } } @@ -569,7 +594,7 @@ STATIC mp_obj_t machine_neopixel_corder(size_t n_args, const mp_obj_t *pos_args, } sprintf(colorder, self->px.color_order); if (self->px.nbits == 24) colorder[3] = '\0'; - return mp_obj_new_str(colorder, strlen(colorder), 0); + return mp_obj_new_str(colorder, strlen(colorder)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_neopixel_corder_obj, 0, machine_neopixel_corder); @@ -661,12 +686,36 @@ STATIC mp_obj_t machine_neopixel_rainbow(mp_obj_t self_in, mp_obj_t pos_in, mp_o np_set_pixel_color(&self->px, i, color); } MP_THREAD_GIL_EXIT(); - np_show(&self->px, self->channel, 0); + np_show(&self->px, self->channel); MP_THREAD_GIL_ENTER(); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(machine_neopixel_rainbow_obj, machine_neopixel_rainbow); +//----------------------------------------------------- +STATIC mp_obj_t machine_neopixel_info(mp_obj_t self_in) +{ + machine_neopixel_obj_t *self = self_in; + np_check(self); + + char colorder[5]; + sprintf(colorder, self->px.color_order); + if (self->px.nbits == 24) colorder[3] = '\0'; + + mp_obj_t tuple[6]; + + tuple[0] = mp_obj_new_int(self->gpio_num); + tuple[1] = mp_obj_new_int(self->px.pixel_count); + tuple[2] = mp_obj_new_int(self->px.nbits); + tuple[3] = mp_obj_new_int(self->channel); + tuple[4] = mp_obj_new_int(sizeof(uint32_t) * self->px.pixel_count); + tuple[5] = mp_obj_new_str(colorder, strlen(colorder)); + + return mp_obj_new_tuple(6, tuple); + +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_neopixel_info_obj, machine_neopixel_info); + //===================================================================== STATIC const mp_rom_map_elem_t machine_neopixel_locals_dict_table[] = { @@ -685,6 +734,7 @@ STATIC const mp_rom_map_elem_t machine_neopixel_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_timings), (mp_obj_t)&machine_neopixel_timings_obj }, { MP_ROM_QSTR(MP_QSTR_color_order),(mp_obj_t)&machine_neopixel_corder_obj }, { MP_ROM_QSTR(MP_QSTR_rainbow), (mp_obj_t)&machine_neopixel_rainbow_obj }, + { MP_ROM_QSTR(MP_QSTR_info), (mp_obj_t)&machine_neopixel_info_obj }, { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(0x000000) }, { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(0xFFFFFF) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_ow.c b/MicroPython_BUILD/components/micropython/esp32/machine_ow.c index 93f8ec4c..9592c614 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_ow.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_ow.c @@ -134,9 +134,7 @@ STATIC mp_obj_t machine_onewire_make_new(const mp_obj_type_t *type, size_t n_arg mp_raise_ValueError("Cannot acquire rx RMT channel"); } - int8_t pin; - if (MP_OBJ_IS_INT(args[0].u_obj)) pin = mp_obj_get_int(args[0].u_obj); - else pin = machine_pin_get_id(args[0].u_obj); + int8_t pin = machine_pin_get_gpio(args[0].u_obj); // ToDo: Check valid pin (not input only) // Check pin @@ -231,7 +229,7 @@ STATIC mp_obj_t machine_onewire_readbytes(mp_obj_t self_in, mp_obj_t len_in) { owb_read_bytes(self->owb, buff, len); - return mp_obj_new_str((const char *)buff, len, 0); + return mp_obj_new_str((const char *)buff, len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_onewire_readbytes_obj, machine_onewire_readbytes); @@ -292,7 +290,7 @@ STATIC mp_obj_t machine_onewire_rom_code(mp_obj_t self_in, mp_obj_t device_in) { char rom_code[17]; owb_string_from_rom_code(self->device_rom_codes[device], rom_code, sizeof(rom_code)); - return mp_obj_new_str(rom_code, strlen(rom_code), 0); + return mp_obj_new_str(rom_code, strlen(rom_code)); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_onewire_rom_code_obj, machine_onewire_rom_code); @@ -330,7 +328,7 @@ STATIC mp_obj_t machine_onewire_search(size_t n_args, const mp_obj_t *pos_args, } else { owb_string_from_rom_code(self->device_rom_codes[i], rom_code_s, sizeof(rom_code_s)); - tuple[i] = mp_obj_new_str(rom_code_s, strlen(rom_code_s), 0); + tuple[i] = mp_obj_new_str(rom_code_s, strlen(rom_code_s)); } } @@ -582,8 +580,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_ds18x20_get_pwrmode_obj, machine_ds18x2 //-------------------------------------------------------------- STATIC mp_obj_t machine_ds18x20_get_convtime(mp_obj_t self_in) { - ds18x20_obj_t *self = self_in; - int64_t conv_time = 0; if (conv_end_time) { conv_time = mp_hal_ticks_ms() - conv_end_time; @@ -600,7 +596,7 @@ STATIC mp_obj_t machine_ds18x20_rom_code(mp_obj_t self_in) { char rom_code[17]; owb_string_from_rom_code(self->owb_obj->device_rom_codes[self->device], rom_code, sizeof(rom_code)); - return mp_obj_new_str(rom_code, strlen(rom_code), 0); + return mp_obj_new_str(rom_code, strlen(rom_code)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_ds18x20_rom_code_obj, machine_ds18x20_rom_code); diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_pin.c b/MicroPython_BUILD/components/micropython/esp32/machine_pin.c index df1f081d..690f4e3a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_pin.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_pin.c @@ -29,143 +29,309 @@ #include #include +#include "driver/rtc_io.h" +#include "driver/gpio.h" #include "py/runtime.h" #include "py/mphal.h" -#include "modmachine.h" #include "extmod/virtpin.h" -#include "machine_pin.h" - -STATIC const machine_pin_obj_t machine_pin_obj[] = { - {{&machine_pin_type}, GPIO_NUM_0}, - {{&machine_pin_type}, GPIO_NUM_1}, - {{&machine_pin_type}, GPIO_NUM_2}, - {{&machine_pin_type}, GPIO_NUM_3}, - {{&machine_pin_type}, GPIO_NUM_4}, - {{&machine_pin_type}, GPIO_NUM_5}, - {{&machine_pin_type}, GPIO_NUM_6}, - {{&machine_pin_type}, GPIO_NUM_7}, - {{&machine_pin_type}, GPIO_NUM_8}, - {{&machine_pin_type}, GPIO_NUM_9}, - {{&machine_pin_type}, GPIO_NUM_10}, - {{&machine_pin_type}, GPIO_NUM_11}, - {{&machine_pin_type}, GPIO_NUM_12}, - {{&machine_pin_type}, GPIO_NUM_13}, - {{&machine_pin_type}, GPIO_NUM_14}, - {{&machine_pin_type}, GPIO_NUM_15}, - {{&machine_pin_type}, GPIO_NUM_16}, - {{&machine_pin_type}, GPIO_NUM_17}, - {{&machine_pin_type}, GPIO_NUM_18}, - {{&machine_pin_type}, GPIO_NUM_19}, - {{NULL}, -1}, - {{&machine_pin_type}, GPIO_NUM_21}, - {{&machine_pin_type}, GPIO_NUM_22}, - {{&machine_pin_type}, GPIO_NUM_23}, - {{NULL}, -1}, - {{&machine_pin_type}, GPIO_NUM_25}, - {{&machine_pin_type}, GPIO_NUM_26}, - {{&machine_pin_type}, GPIO_NUM_27}, - {{NULL}, -1}, - {{NULL}, -1}, - {{NULL}, -1}, - {{NULL}, -1}, - {{&machine_pin_type}, GPIO_NUM_32}, - {{&machine_pin_type}, GPIO_NUM_33}, - {{&machine_pin_type}, GPIO_NUM_34}, - {{&machine_pin_type}, GPIO_NUM_35}, - {{&machine_pin_type}, GPIO_NUM_36}, - {{&machine_pin_type}, GPIO_NUM_37}, - {{&machine_pin_type}, GPIO_NUM_38}, - {{&machine_pin_type}, GPIO_NUM_39}, +#include "modmachine.h" + +extern bool mpy_use_spiram; +extern int MainTaskCore; + +static const uint8_t pin_modes[5] = { + GPIO_MODE_INPUT, + GPIO_MODE_OUTPUT, + GPIO_MODE_OUTPUT_OD, + GPIO_MODE_INPUT_OUTPUT_OD, + GPIO_MODE_INPUT_OUTPUT +}; +static const uint8_t pin_pull_modes[4] = { + GPIO_PULLUP_ONLY, + GPIO_PULLDOWN_ONLY, + GPIO_PULLUP_PULLDOWN, + GPIO_FLOATING }; -// forward declaration -STATIC const machine_pin_irq_obj_t machine_pin_irq_object[]; +//---------------------------------------------- +gpio_num_t machine_pin_get_id(mp_obj_t pin_in) { + if (mp_obj_get_type(pin_in) != &machine_pin_type) { + mp_raise_ValueError("expecting a pin"); + } + machine_pin_obj_t *self = pin_in; + return self->id; +} //--------------------------------------- int machine_pin_get_gpio(mp_obj_t pin_in) { if (MP_OBJ_IS_INT(pin_in)) { int wanted_pin = mp_obj_get_int(pin_in); - - machine_pin_obj_t *Pin = NULL; - if ((0 <= wanted_pin) && (wanted_pin < MP_ARRAY_SIZE(machine_pin_obj))) { - Pin = (machine_pin_obj_t*)&machine_pin_obj[wanted_pin]; - } - if ((Pin == NULL) || (Pin->base.type == NULL) || (Pin->id < 0)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); - } - return Pin->id; + if (!GPIO_IS_VALID_GPIO(wanted_pin)) { + mp_raise_ValueError("Invalid pin number"); + } + return wanted_pin; } return machine_pin_get_id(pin_in); } +//---------------------------- void machine_pins_init(void) { static bool did_install = false; if (!did_install) { gpio_install_isr_service(0); did_install = true; } - memset(&MP_STATE_PORT(machine_pin_irq_handler[0]), 0, sizeof(MP_STATE_PORT(machine_pin_irq_handler))); + + machine_rtc_config.ext0_pin = -1; + for (int i=0; iid]; - mp_sched_schedule(handler, MP_OBJ_FROM_PTR(self), NULL); +//--------------------------------------------------- +static void _pin_disable_irq(machine_pin_obj_t *self) +{ + gpio_isr_handler_remove(self->id); + self->irq_handler = NULL; + self->irq_type = GPIO_PIN_INTR_DISABLE; + self->irq_debounce = 0; + self->irq_active_time = 0; + self->irq_retvalue = -1; + self->irq_any_level = gpio_get_level(self->id); } -gpio_num_t machine_pin_get_id(mp_obj_t pin_in) { - if (mp_obj_get_type(pin_in) != &machine_pin_type) { - mp_raise_ValueError("expecting a pin"); +//-------------------------------------------------- +static void _pin_enable_irq(machine_pin_obj_t *self) +{ + if (self->irq_type == GPIO_INTR_ANYEDGE) { + // use level interrupts for 'any edge' interrupt type! + self->irq_any_level = gpio_get_level(self->id); + gpio_set_intr_type(self->id, self->irq_any_level ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL); + } + else gpio_set_intr_type(self->id, self->irq_type); +} + +// gpio interrupt is disabled on entry! +//-------------------------------------------- +static void debounce_task(void *pvParameters) +{ + machine_pin_obj_t *self = (machine_pin_obj_t *)pvParameters; + + // get current pin level + uint8_t levl = 0; + uint8_t active_level = 0; + if (self->irq_type == GPIO_INTR_POSEDGE) active_level = 1; + else if (self->irq_type == GPIO_INTR_NEGEDGE) active_level = 0; + else if (self->irq_type == GPIO_INTR_ANYEDGE) active_level = self->irq_any_level; + + int64_t curr_time = mp_hal_ticks_us(); + int64_t start_time = curr_time; + int64_t total_time = 0; + int32_t loop_time = 0; + int32_t active_time = 0; + + if (self->irq_active_time > 0) { + // Pin must on active level for some time + while (total_time < self->irq_active_time) { + ets_delay_us(100); + curr_time = mp_hal_ticks_us(); + loop_time = (curr_time - start_time); + start_time = curr_time; + total_time += loop_time; + active_time += loop_time; + + levl = gpio_get_level(self->id); + if (levl == active_level) active_time += loop_time; + else active_time = 0; + + if (active_time >= self->irq_active_time) { + self->irq_retvalue = levl; + if (self->irq_handler) { + // schedule the callback function + mp_sched_schedule(self->irq_handler, MP_OBJ_FROM_PTR(self), NULL); + } + break; + } + vTaskDelay(0); + } + } + + int32_t remaining_time = self->irq_debounce - total_time; + if (remaining_time > 0) { + if (remaining_time > 2000) { + uint32_t dus = remaining_time % 2000; // remaining micro seconds + vTaskDelay(remaining_time/2000); + if (dus) ets_delay_us(dus); + } + else ets_delay_us(remaining_time); + } + + if (self->irq_handler) { + // schedule the callback function + self->irq_retvalue = gpio_get_level(self->id); + mp_sched_schedule(self->irq_handler, MP_OBJ_FROM_PTR(self), NULL); + } + + // Re-enable interrupt ONLY for edge types + if ((self->irq_type != GPIO_INTR_LOW_LEVEL) && (self->irq_type != GPIO_INTR_HIGH_LEVEL)) { + _pin_enable_irq(self); + } + + vTaskDelete(NULL); +} + +//-------------------------------------------- +STATIC void machine_pin_isr_handler(void *arg) +{ + // Disable gpio interrupt + gpio_set_intr_type(((machine_pin_obj_t *)arg)->id, GPIO_PIN_INTR_DISABLE); + machine_pin_obj_t *self = (machine_pin_obj_t *)arg; + + if (self->irq_debounce > 0) { + // Start the debounce task + #if CONFIG_MICROPY_USE_BOTH_CORES + xTaskCreate(debounce_task, "pin_task", 768, (void *)arg, CONFIG_MICROPY_TASK_PRIORITY, NULL); + #else + xTaskCreatePinnedToCore(debounce_task, "pin_task", 768, (void *)arg, CONFIG_MICROPY_TASK_PRIORITY, NULL, MainTaskCore); + #endif + } + else { + if (self->irq_handler) { + // schedule the callback function + self->irq_retvalue = gpio_get_level(self->id); + mp_sched_schedule(self->irq_handler, MP_OBJ_FROM_PTR(self), NULL); + } + + // Re-enable interrupt ONLY for edge types + if ((self->irq_type != GPIO_INTR_LOW_LEVEL) && (self->irq_type != GPIO_INTR_HIGH_LEVEL)) { + _pin_enable_irq(self); + } } - machine_pin_obj_t *self = pin_in; - return self->id; } +//---------------------------------------------------------------------------------------------- STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_pin_obj_t *self = self_in; - mp_printf(print, "Pin(%u)", self->id); -} -// pin.init(mode, pull=None, *, value) -STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_pull, ARG_value }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = mp_const_none}}, - { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, - { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - }; + char smode[32]; + if (self->mode == GPIO_MODE_DISABLE) sprintf(smode, "DISABLED"); + else if (self->mode == GPIO_MODE_INPUT) sprintf(smode, "IN"); + else if (self->mode == GPIO_MODE_OUTPUT) sprintf(smode, "OUT"); + else if (self->mode == GPIO_MODE_OUTPUT_OD) sprintf(smode, "OUT_OD"); + else if (self->mode == GPIO_MODE_INPUT_OUTPUT_OD) sprintf(smode, "INOUT_OD"); + else if (self->mode == GPIO_MODE_INPUT_OUTPUT) sprintf(smode, "INOUT"); + else sprintf(smode, "Unknown"); + + if (self->pull == GPIO_PULLUP_ONLY) strcat(smode, ", PULL_UP"); + else if (self->pull == GPIO_PULLDOWN_ONLY) strcat(smode, ", PULL_DOWN"); + else if (self->pull == GPIO_PULLUP_PULLDOWN) strcat(smode, ", PULL_UPDOWN"); + else if (self->pull == GPIO_FLOATING) strcat(smode, ", PULL_FLOAT"); + else strcat(smode, ", Unknown"); + + mp_printf(print, "Pin(%u) mode=%s", self->id, smode); + if (self->irq_handler) { + uint32_t pin_irq_type = self->irq_type; + char sirq[32]; + if (pin_irq_type == GPIO_INTR_DISABLE) sprintf(sirq, "IRQ_DISABLED"); + else if (pin_irq_type == GPIO_INTR_POSEDGE) sprintf(sirq, "IRQ_RISING"); + else if (pin_irq_type == GPIO_INTR_NEGEDGE) sprintf(sirq, "IRQ_FALLING"); + else if (pin_irq_type == GPIO_INTR_ANYEDGE) { + uint32_t pin_irq_type_any = GPIO.pin[self->id].int_type; + char sirq_any[8]; + if (pin_irq_type_any == GPIO_INTR_LOW_LEVEL) sprintf(sirq_any, "LOLEVEL"); + else if (pin_irq_type_any == GPIO_INTR_HIGH_LEVEL) sprintf(sirq_any, "HILEVEL"); + else sprintf(sirq_any, "?"); + sprintf(sirq, "IRQ_ANYEDGE (%s)", sirq_any); + } + else if (pin_irq_type == GPIO_INTR_LOW_LEVEL) sprintf(sirq, "IRQ_LOLEVEL"); + else if (pin_irq_type == GPIO_INTR_HIGH_LEVEL) sprintf(sirq, "IRQ_HILEVEL"); + else sprintf(sirq, "Unknown"); + mp_printf(print, ", irq=%s, debounce=%u, actTime=%d", sirq, self->irq_debounce, self->irq_active_time); + } +} - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); +// constructor(id, ...) +//------------------------------------------------------------------------------------------------------- +mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_pin, ARG_mode, ARG_pull, ARG_value, ARG_handler, ARG_trigger, ARG_debounce, ARG_acttime }; + static const mp_arg_t mp_pin_allowed_args[] = { + { MP_QSTR_pin, MP_ARG_INT, {.u_int = 40}}, + { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_PIN_INTR_DISABLE} }, + { MP_QSTR_debounce, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_acttime, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(mp_pin_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(mp_pin_allowed_args), mp_pin_allowed_args, args); - // configure the pin for gpio - gpio_pad_select_gpio(self->id); + // get the wanted pin object + int wanted_pin = args[ARG_pin].u_int; - // set initial value (do this before configuring mode/pull) - if (args[ARG_value].u_obj != MP_OBJ_NULL) { - gpio_set_level(self->id, mp_obj_is_true(args[ARG_value].u_obj)); + if (!GPIO_IS_VALID_GPIO(wanted_pin)) { + mp_raise_ValueError("invalid pin"); } + if (mpy_use_spiram) { + if ((wanted_pin == 16) || (wanted_pin == 17)) { + mp_raise_ValueError("Pins 16&17 cannot be used if SPIRAM is used"); + } + } + + // Create Pin object + //machine_pin_obj_t *self = m_new_obj(machine_pin_obj_t); + machine_pin_obj_t *self = m_new_obj_with_finaliser(machine_pin_obj_t); + memset(self, 0, sizeof(machine_pin_obj_t)); + self->base.type = &machine_pin_type; + self->id = wanted_pin; + self->mode = GPIO_MODE_INPUT; + self->pull = GPIO_FLOATING; + + gpio_config_t pin_conf; + pin_conf.intr_type = GPIO_PIN_INTR_DISABLE; + pin_conf.mode = GPIO_MODE_INPUT; + pin_conf.pin_bit_mask = (1ULL<id >= 34 && (pin_io_mode & GPIO_MODE_DEF_OUTPUT)) { - mp_raise_ValueError("pin can only be input"); - } else { - gpio_set_direction(self->id, pin_io_mode); + int pin_io_mode = -1; + int in_pin_mode = mp_obj_get_int(args[ARG_mode].u_obj); + for (int i=0; iid)) { + mp_raise_ValueError("not a valid output pin"); + } + } + pin_conf.mode = pin_io_mode; + self->mode = pin_io_mode; } // configure pull @@ -173,37 +339,235 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ if (self->id >= 34) { mp_raise_ValueError("pins 34~39 do not have pull-up or pull-down circuitry"); } - gpio_set_pull_mode(self->id, mp_obj_get_int(args[ARG_pull].u_obj)); + int pin_pull = -1; + int in_pin_pull_mode = mp_obj_get_int(args[ARG_pull].u_obj); + for (int i=0; ipull = pin_pull; } - return mp_const_none; + // configure the pin for gpio + if (rtc_gpio_is_valid_gpio(self->id)) rtc_gpio_deinit(self->id); + gpio_pad_select_gpio(self->id); + + gpio_config(&pin_conf); + + // set initial value + if (args[ARG_value].u_obj != MP_OBJ_NULL) { + gpio_set_level(self->id, mp_obj_is_true(args[ARG_value].u_obj)); + } + + _pin_disable_irq(self); + if ((self->mode != GPIO_MODE_OUTPUT) && (self->mode != GPIO_MODE_OUTPUT_OD)) { + // Only input modes can have interrupts, configure it + if (args[ARG_handler].u_obj != mp_const_none) { + // Disable pin interrupts and remove isr handler + gpio_set_intr_type(self->id, GPIO_PIN_INTR_DISABLE); + gpio_isr_handler_remove(self->id); + + // Check arguments + if ((!MP_OBJ_IS_FUN(args[ARG_handler].u_obj)) && (!MP_OBJ_IS_METH(args[ARG_handler].u_obj))) { + mp_raise_ValueError("callback function expected"); + } + if ((args[ARG_trigger].u_int < GPIO_PIN_INTR_DISABLE) || (args[ARG_trigger].u_int >= GPIO_INTR_MAX)) { + mp_raise_ValueError("invalid trigger type"); + } + if ((args[ARG_debounce].u_int != 0) && ((args[ARG_debounce].u_int < 100) || (args[ARG_debounce].u_int > 500000))) { + mp_raise_ValueError("wrong debounce range (0 or 100 - 500000 us)"); + } + if ((args[ARG_acttime].u_int != 0) && ((args[ARG_acttime].u_int < 100) || (args[ARG_acttime].u_int > 500000))) { + mp_raise_ValueError("wrong active time range (0 or 100 - 500000 us)"); + } + self->irq_handler = NULL; + self->irq_type = (int8_t)args[ARG_trigger].u_int; + + self->irq_debounce = args[ARG_debounce].u_int; + self->irq_active_time = args[ARG_acttime].u_int; + if (self->irq_active_time > self->irq_debounce) self->irq_active_time = self->irq_debounce; + + self->irq_handler = args[ARG_handler].u_obj; + + // Add pin ISR handler + if (gpio_isr_handler_add(self->id, machine_pin_isr_handler, (void*)self) != ESP_OK) { + self->irq_handler = NULL; + self->irq_type = GPIO_PIN_INTR_DISABLE; + self->irq_debounce = 0; + gpio_set_intr_type(self->id, GPIO_PIN_INTR_DISABLE); + mp_raise_ValueError("error adding ISR handler"); + } + // Enable pin interrupt + _pin_enable_irq(self); + } + } + + return MP_OBJ_FROM_PTR(self); } -// constructor(id, ...) -mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); +// pin.init(mode, pull) +//--------------------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_pin_obj_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_pull, ARG_value, ARG_handler, ARG_trigger, ARG_debounce, ARG_acttime }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_INT, {.u_int = -1}}, + { MP_QSTR_pull, MP_ARG_INT, {.u_int = -1}}, + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_debounce, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_acttime, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + machine_pin_obj_t *self = pos_args[0]; - // get the wanted pin object - int wanted_pin = mp_obj_get_int(args[0]); - const machine_pin_obj_t *self = NULL; - if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) { - self = (machine_pin_obj_t*)&machine_pin_obj[wanted_pin]; + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (self->irq_handler) { + // Disable pin interrupt + gpio_set_intr_type(self->id, GPIO_PIN_INTR_DISABLE); } - if (self == NULL || self->base.type == NULL) { - mp_raise_ValueError("invalid pin"); + + // set initial value (do this before configuring mode/pull) + if (args[ARG_value].u_obj != MP_OBJ_NULL) { + gpio_set_level(self->id, mp_obj_is_true(args[ARG_value].u_obj)); } - if (n_args > 1 || n_kw > 0) { - // pin mode given, so configure this GPIO - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); + // configure mode + if (args[ARG_mode].u_int >= 0) { + int pin_io_mode = -1; + for (int i=0; iirq_handler) _pin_enable_irq(self); + mp_raise_ValueError("unsupported pin mode"); + } + if (self->mode != pin_io_mode) { + if (pin_io_mode & GPIO_MODE_DEF_OUTPUT) { + // output + if (!GPIO_IS_VALID_OUTPUT_GPIO(self->id)) { + if (self->irq_handler) _pin_enable_irq(self); + mp_raise_ValueError("not a valid output pin"); + } + } + if (gpio_set_direction(self->id, pin_io_mode) != ESP_OK) { + gpio_set_direction(self->id, self->mode); + } + else self->mode = pin_io_mode; + if ((pin_io_mode == GPIO_MODE_OUTPUT) || (pin_io_mode == GPIO_MODE_OUTPUT_OD)) { + // no interrupts for OUTPUT modes + _pin_disable_irq(self); + } + } } - return MP_OBJ_FROM_PTR(self); + // configure pull + if (args[ARG_pull].u_int >= 0) { + if (self->id >= 34) { + if (self->irq_handler) _pin_enable_irq(self);; + mp_raise_ValueError("pins 34~39 do not have pull-up or pull-down circuitry"); + } + int pin_pull = -1; + for (int i=0; iirq_handler) _pin_enable_irq(self);; + mp_raise_ValueError("unsupported pull mode"); + } + if (self->pull != pin_pull) { + if (gpio_set_pull_mode(self->id, pin_pull) != ESP_OK) { + gpio_set_pull_mode(self->id, self->pull); + } + else self->pull = pin_pull; + } + } + + if ((self->mode != GPIO_MODE_OUTPUT) && (self->mode != GPIO_MODE_OUTPUT_OD)) { + // Configure interrupt for input pin modes + if (args[ARG_handler].u_obj != MP_OBJ_NULL) { + if (args[ARG_handler].u_obj == mp_const_none) { + _pin_disable_irq(self); + } + else { + gpio_isr_handler_remove(self->id); + if ((!MP_OBJ_IS_FUN(args[ARG_handler].u_obj)) && (!MP_OBJ_IS_METH(args[ARG_handler].u_obj))) { + if (self->irq_handler) _pin_enable_irq(self); + mp_raise_ValueError("callback function expected"); + } + if (gpio_isr_handler_add(self->id, machine_pin_isr_handler, (void*)self) != ESP_OK) { + _pin_disable_irq(self); + mp_raise_ValueError("error adding ISR handler, IRQ disabled"); + } + self->irq_handler = args[ARG_handler].u_obj; + } + } + + if (self->irq_handler) { + // set debounce + if ((args[ARG_debounce].u_int == 0) || ((args[ARG_debounce].u_int >= 100) && (args[ARG_debounce].u_int <= 500000))) { + self->irq_debounce = args[ARG_debounce].u_int; + } + else if (args[ARG_debounce].u_int > 0) { + _pin_disable_irq(self); + mp_raise_ValueError("out of debounce range (100 - 500000 us)"); + } + + // set active time + if ((args[ARG_acttime].u_int == 0) || ((args[ARG_acttime].u_int >= 100) && (args[ARG_acttime].u_int <= 500000))) { + self->irq_active_time = args[ARG_acttime].u_int; + } + else if (args[ARG_acttime].u_int > 0) { + _pin_disable_irq(self); + mp_raise_ValueError("out of active time range (100 - 500000 us)"); + } + if (self->irq_active_time > self->irq_debounce) self->irq_active_time = self->irq_debounce; + + // set trigger type + if (args[ARG_trigger].u_int >= 0) { + if (self->irq_type != (int8_t)args[ARG_trigger].u_int) { + if ((args[ARG_trigger].u_int < GPIO_PIN_INTR_DISABLE) || (args[ARG_trigger].u_int >= GPIO_INTR_MAX)) { + _pin_disable_irq(self); + mp_raise_ValueError("invalid trigger type"); + } + self->irq_type = (int8_t)args[ARG_trigger].u_int; + // Enable interrupts + _pin_enable_irq(self); + } + } + + self->irq_retvalue = -1; + } + } + + if (self->irq_handler) _pin_enable_irq(self); + + return mp_const_none; } +MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); + // fast method for getting/setting pin value +//---------------------------------------------------------------------------------------------------- STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); machine_pin_obj_t *self = self_in; @@ -217,64 +581,66 @@ STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c } } -// pin.init(mode, pull) -STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init); - // pin.value([value]) +//---------------------------------------------------------------------- STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) { return machine_pin_call(args[0], n_args - 1, 0, args + 1); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value); -// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING) -STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_handler, ARG_trigger, ARG_hard }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE} }, - }; - machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - if (n_args > 1 || kw_args->used != 0) { - // configure irq - mp_obj_t handler = args[ARG_handler].u_obj; - uint32_t trigger = args[ARG_trigger].u_int; - if (handler == mp_const_none) { - handler = MP_OBJ_NULL; - trigger = 0; - } - gpio_isr_handler_remove(self->id); - MP_STATE_PORT(machine_pin_irq_handler)[self->id] = handler; - gpio_set_intr_type(self->id, trigger); - gpio_isr_handler_add(self->id, machine_pin_isr_handler, (void*)self); - } +//------------------------------------------------------- +STATIC mp_obj_t machine_pin_irq_value(mp_obj_t self_in) { + machine_pin_obj_t *self = self_in; + + return MP_OBJ_NEW_SMALL_INT(self->irq_retvalue); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_irq_value_obj, machine_pin_irq_value); + +//---------------------------------------------------- +STATIC mp_obj_t machine_pin_deinit(mp_obj_t self_in) { + machine_pin_obj_t *self = self_in; - // return the irq object - return MP_OBJ_FROM_PTR(&machine_pin_irq_object[self->id]); + if (self->irq_handler) { + gpio_set_intr_type(self->id, GPIO_PIN_INTR_DISABLE); + gpio_isr_handler_remove(self->id); + self->irq_handler = NULL; + self->irq_type = GPIO_PIN_INTR_DISABLE; + self->irq_debounce = 0; + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_deinit_obj, machine_pin_deinit); + +//================================================================ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { // instance methods - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, - { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_pin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_irqvalue), MP_ROM_PTR(&machine_pin_irq_value_obj) }, // class constants - { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, - { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, - { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, - { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) }, - { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN_ONLY) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUTPUT) }, + { MP_ROM_QSTR(MP_QSTR_OUT_OD), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) }, + { MP_ROM_QSTR(MP_QSTR_INOUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, + { MP_ROM_QSTR(MP_QSTR_INOUT_OD), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, + + { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_PULL_UPDOWN), MP_ROM_INT(GPIO_PULLUP_PULLDOWN) }, + { MP_ROM_QSTR(MP_QSTR_PULL_FLOAT), MP_ROM_INT(GPIO_FLOATING) }, + + { MP_ROM_QSTR(MP_QSTR_IRQ_DISABLE), MP_ROM_INT(GPIO_PIN_INTR_DISABLE) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_ANYEDGE), MP_ROM_INT(GPIO_PIN_INTR_ANYEDGE) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_LOLEVEL), MP_ROM_INT(GPIO_PIN_INTR_LOLEVEL) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_HILEVEL), MP_ROM_INT(GPIO_PIN_INTR_HILEVEL) }, }; +//-------------------------------------------------------------------------------------------- STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; machine_pin_obj_t *self = self_in; @@ -293,10 +659,12 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); +//----------------------------------- STATIC const mp_pin_p_t pin_pin_p = { .ioctl = pin_ioctl, }; +//====================================== const mp_obj_type_t machine_pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, @@ -306,82 +674,3 @@ const mp_obj_type_t machine_pin_type = { .protocol = &pin_pin_p, .locals_dict = (mp_obj_t)&machine_pin_locals_dict, }; - -/******************************************************************************/ -// Pin IRQ object - -STATIC const mp_obj_type_t machine_pin_irq_type; - -STATIC const machine_pin_irq_obj_t machine_pin_irq_object[] = { - {{&machine_pin_irq_type}, GPIO_NUM_0}, - {{&machine_pin_irq_type}, GPIO_NUM_1}, - {{&machine_pin_irq_type}, GPIO_NUM_2}, - {{&machine_pin_irq_type}, GPIO_NUM_3}, - {{&machine_pin_irq_type}, GPIO_NUM_4}, - {{&machine_pin_irq_type}, GPIO_NUM_5}, - {{&machine_pin_irq_type}, GPIO_NUM_6}, - {{&machine_pin_irq_type}, GPIO_NUM_7}, - {{&machine_pin_irq_type}, GPIO_NUM_8}, - {{&machine_pin_irq_type}, GPIO_NUM_9}, - {{&machine_pin_irq_type}, GPIO_NUM_10}, - {{&machine_pin_irq_type}, GPIO_NUM_11}, - {{&machine_pin_irq_type}, GPIO_NUM_12}, - {{&machine_pin_irq_type}, GPIO_NUM_13}, - {{&machine_pin_irq_type}, GPIO_NUM_14}, - {{&machine_pin_irq_type}, GPIO_NUM_15}, - {{&machine_pin_irq_type}, GPIO_NUM_16}, - {{&machine_pin_irq_type}, GPIO_NUM_17}, - {{&machine_pin_irq_type}, GPIO_NUM_18}, - {{&machine_pin_irq_type}, GPIO_NUM_19}, - {{NULL}, -1}, - {{&machine_pin_irq_type}, GPIO_NUM_21}, - {{&machine_pin_irq_type}, GPIO_NUM_22}, - {{&machine_pin_irq_type}, GPIO_NUM_23}, - {{NULL}, -1}, - {{&machine_pin_irq_type}, GPIO_NUM_25}, - {{&machine_pin_irq_type}, GPIO_NUM_26}, - {{&machine_pin_irq_type}, GPIO_NUM_27}, - {{NULL}, -1}, - {{NULL}, -1}, - {{NULL}, -1}, - {{NULL}, -1}, - {{&machine_pin_irq_type}, GPIO_NUM_32}, - {{&machine_pin_irq_type}, GPIO_NUM_33}, - {{&machine_pin_irq_type}, GPIO_NUM_34}, - {{&machine_pin_irq_type}, GPIO_NUM_35}, - {{&machine_pin_irq_type}, GPIO_NUM_36}, - {{&machine_pin_irq_type}, GPIO_NUM_37}, - {{&machine_pin_irq_type}, GPIO_NUM_38}, - {{&machine_pin_irq_type}, GPIO_NUM_39}, -}; - -STATIC mp_obj_t machine_pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - machine_pin_irq_obj_t *self = self_in; - mp_arg_check_num(n_args, n_kw, 0, 0, false); - machine_pin_isr_handler((void*)&machine_pin_obj[self->id]); - return mp_const_none; -} - -STATIC mp_obj_t machine_pin_irq_trigger(size_t n_args, const mp_obj_t *args) { - machine_pin_irq_obj_t *self = args[0]; - uint32_t orig_trig = GPIO.pin[self->id].int_type; - if (n_args == 2) { - // set trigger - gpio_set_intr_type(self->id, mp_obj_get_int(args[1])); - } - // return original trigger value - return MP_OBJ_NEW_SMALL_INT(orig_trig); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_irq_trigger_obj, 1, 2, machine_pin_irq_trigger); - -STATIC const mp_rom_map_elem_t machine_pin_irq_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&machine_pin_irq_trigger_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(machine_pin_irq_locals_dict, machine_pin_irq_locals_dict_table); - -STATIC const mp_obj_type_t machine_pin_irq_type = { - { &mp_type_type }, - .name = MP_QSTR_IRQ, - .call = machine_pin_irq_call, - .locals_dict = (mp_obj_dict_t*)&machine_pin_irq_locals_dict, -}; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c b/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c index 643eba06..78906b95 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c @@ -32,7 +32,7 @@ #include "py/nlr.h" #include "py/runtime.h" #include "modmachine.h" -#include "machine_pin.h" +#include "modmachine.h" #include "mphalport.h" // High speed mode @@ -41,13 +41,13 @@ // Forward dec'l extern const mp_obj_type_t machine_pwm_type; -typedef struct _esp32_pwm_obj_t { - mp_obj_base_t base; - gpio_num_t pin; - uint8_t active; - uint8_t channel; - uint8_t timer; -} esp32_pwm_obj_t; +// typedef struct _esp32_pwm_obj_t { +// mp_obj_base_t base; +// gpio_num_t pin; +// uint8_t active; +// uint8_t channel; +// uint8_t timer; +// } esp32_pwm_obj_t; STATIC esp32_pwm_obj_t *pwm_channels[LEDC_CHANNEL_MAX]; STATIC ledc_timer_config_t pwm_timers[LEDC_CHANNEL_MAX/2]; @@ -175,7 +175,7 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self, size_t n_args, const mp if (self->channel >= LEDC_CHANNEL_MAX) { // === New PWM assignment - if (timer < 0) timer = 0; + if (timer < 0) timer = 1; if (timer > 3) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "wrong timer requested: %d (0~3 allowed)", timer)); } diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_rfcomm.c b/MicroPython_BUILD/components/micropython/esp32/machine_rfcomm.c new file mode 100644 index 00000000..eae5010e --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/machine_rfcomm.c @@ -0,0 +1,1152 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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 "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_RFCOMM + +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_log.h" +#include "esp_bt.h" +#include "api/esp_bt_main.h" +#include "api/esp_gap_bt_api.h" +#include "api/esp_bt_device.h" +#include "api/esp_spp_api.h" + +#include "machine_uart.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "modmachine.h" + +#define SPP_TAG "RFCOMM" +#define RFCOMM_CB_TYPE_DATA 1 +#define RFCOMM_CB_TYPE_PATTERN 2 +#define RFCOMM_CB_TYPE_STATUS 3 +#define RFCOMM_MAX_CLIENTS 8 + +typedef struct _rfcomm_cb_obj_t { + int data_cb_size; + uint8_t pattern[16]; + uint8_t pattern_len; + uint32_t *data_cb; + uint32_t *pattern_cb; + uint8_t lineend[3]; +} rfcomm_cb_obj_t; + +typedef struct _rfcomm_client_t { + uint8_t client_btaddr[ESP_BD_ADDR_LEN]; + uint32_t handle; + uint32_t wr_handle; + uint16_t size; + uint16_t iget; + uint16_t iput; + rfcomm_cb_obj_t cb; + uint8_t *buf; +} rfcomm_client_t; + +typedef struct _machine_rfcomm_obj_t { + mp_obj_base_t base; + bool init; + int8_t channel; + int8_t connected; + esp_spp_sec_t sec_mask; + esp_spp_role_t role; + char server_name[32]; + char device_name[32]; + rfcomm_cb_obj_t cb; + uint16_t timeout; // timeout waiting for first char (in ms) + uint16_t buffer_size; + uint32_t *status_cb; +} machine_rfcomm_obj_t; + +static machine_rfcomm_obj_t *rfcomm_obj = NULL; +static QueueHandle_t rfcomm_mutex = NULL; +static bool bt_controller_is_init = false; +static rfcomm_client_t * clients[RFCOMM_MAX_CLIENTS] = {NULL}; + +static const char* const rfcomm_events[] = { + "SPP initialized", // 0 + "SDP discovery complete", // 1 + "SPP client connection open", // 2 + "SPP connection closed, client disconnected", // 3 + "SPP server started", // 4 + "SPP client initiated a connection", // 5 + "SPP connection received data", // 6 + "SPP connection congestion status changed", // 7 + "SPP write operation complete", // 8 + "SPP connection open, client connected", // 9 + "Data received, buffer overflow", // 10 + "SPP server start failed", // 11 +}; + +//----------------------------------------------------------------- +static int rfcomm_buf_get(uint8_t idx, uint8_t *dest, uint16_t len) +{ + if ((clients[idx] == NULL) || (clients[idx]->buf == NULL)) return -1; + if (clients[idx]->iget == clients[idx]->iput) return -1; // input buffer empty + + int res = 0; + for (int i=0; ibuf[clients[idx]->iget++]; + res++; + if (clients[idx]->iget == clients[idx]->iput) break; + } + // move the buffer and adjust the pointers + memmove(clients[idx], clients[idx]->buf+res, clients[idx]->iput - res); + clients[idx]->iget -= res; + clients[idx]->iput -= res; + + return res; +} + +//------------------------------------------------------------------- +static int rfcomm_buf_put(uint8_t idx, uint8_t *source, uint16_t len) +{ + if ((clients[idx] == NULL) || (clients[idx]->buf == NULL)) return 1; + int res = 0; + for (int i=0; iiput >= clients[idx]->size) return 1; // overflow + clients[idx]->buf[clients[idx]->iput++] = source[i]; + } + return res; +} + +//-------------------------------------------------------------------------------------------------------------- +static void _sched_callback(mp_obj_t function, int8_t client, int type, int iarglen, uint8_t *sarg, char *param) +{ + mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); + if (carg == NULL) return; + if (client >= 0) { + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_INT, client, NULL, NULL)) return; + } + else { + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_NONE, 0, NULL, NULL)) return; + } + if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_INT, type, NULL, NULL)) return; + if (sarg) { + if (iarglen == 0) { + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, strlen((char *)sarg), sarg, NULL)) return; + } + else { + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, iarglen, sarg, NULL)) return; + } + } + else { + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_INT, iarglen, NULL, NULL)) return; + } + if (param) { + if (!make_carg_entry(carg, 3, MP_SCHED_ENTRY_TYPE_STR, strlen(param), (uint8_t *)param, NULL)) return; + } + mp_sched_schedule(function, mp_const_none, carg); +} + +//---------------------------------------------------------------------- +static void _rfcomm_event_status(int8_t client, int nevent, char *param) +{ + if (rfcomm_obj->status_cb) { + _sched_callback(rfcomm_obj->status_cb, client, nevent, 0, (uint8_t *)rfcomm_events[nevent], param); + } + else { + if (param) { + if (client >= 0) { + ESP_LOGD(SPP_TAG, "[client_%d] %s (%s)", client, rfcomm_events[nevent], param); + } + else { + ESP_LOGD(SPP_TAG, "%s (%s)", rfcomm_events[nevent], param); + } + } + else { + if (client >= 0) { + ESP_LOGD(SPP_TAG, "[client_%d] %s", client, rfcomm_events[nevent]); + } + else { + ESP_LOGD(SPP_TAG, "%s", rfcomm_events[nevent]); + } + } + } +} + +//============================================================================ +static void rfcomm_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) +{ + if (rfcomm_obj == NULL) return; + int res; + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + switch (event) { + case ESP_SPP_INIT_EVT: + { + esp_bt_dev_set_device_name((const char *)rfcomm_obj->device_name); + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); + esp_spp_start_srv(rfcomm_obj->sec_mask, rfcomm_obj->role, rfcomm_obj->channel, (const char *)rfcomm_obj->server_name); + _rfcomm_event_status(-1, 0, NULL); + break; + } + + case ESP_SPP_DISCOVERY_COMP_EVT: + _rfcomm_event_status(-1, 1, NULL); + break; + + case ESP_SPP_OPEN_EVT: + _rfcomm_event_status(-1, 2, NULL); + break; + + case ESP_SPP_CLOSE_EVT: + { + int client = -1; + for (int i=0; ihandle == param->close.handle)) { + if (clients[i]->buf) free(clients[i]->buf); + free(clients[i]); + clients[i] = NULL; + client = i; + break; + } + } + if (rfcomm_obj->connected) rfcomm_obj->connected--; + _rfcomm_event_status(client, 3, NULL); + break; + } + + case ESP_SPP_START_EVT: + if (param->start.status != ESP_SPP_SUCCESS) { + _rfcomm_event_status(-1, 11, NULL); + rfcomm_obj->channel++; + if (rfcomm_obj->channel > 79) rfcomm_obj->channel = 1; + ESP_LOGW(SPP_TAG, "Fail reason: %d, retry on channel %d", param->start.status, rfcomm_obj->channel); + esp_spp_start_srv(rfcomm_obj->sec_mask, rfcomm_obj->role, rfcomm_obj->channel, (const char *)rfcomm_obj->server_name); + } + else { + _rfcomm_event_status(-1, 4, NULL); + } + break; + + case ESP_SPP_CL_INIT_EVT: + _rfcomm_event_status(-1, 5, NULL); + break; + + case ESP_SPP_DATA_IND_EVT: + { + // Data received + int cidx = -1; + for (int i=0; ihandle == param->data_ind.handle)) { + cidx = i; + break; + } + } + if (cidx >= 0) { + res = rfcomm_buf_put(cidx, param->data_ind.data, param->data_ind.len); + if (res) _rfcomm_event_status(cidx, 10, NULL); + else { + bool serviced = false; + if ((clients[cidx]->cb.data_cb) || (rfcomm_obj->cb.data_cb)) { + rfcomm_cb_obj_t *pcb = &rfcomm_obj->cb; + if (clients[cidx]->cb.data_cb) pcb = &clients[cidx]->cb; + if ((pcb->data_cb_size > 0) && (clients[cidx]->iput >= pcb->data_cb_size)) { + // ** callback on data length + uint8_t *dtmp = malloc(pcb->data_cb_size); + if (dtmp) { + rfcomm_buf_get(cidx, dtmp, pcb->data_cb_size); + _sched_callback(pcb->data_cb, cidx, RFCOMM_CB_TYPE_DATA, pcb->data_cb_size, dtmp, NULL); + free(dtmp); + } + serviced = true; + } + } + else if ((!serviced) && ((clients[cidx]->cb.pattern_cb) || (rfcomm_obj->cb.pattern_cb))) { + // ** callback on pattern received + rfcomm_cb_obj_t *pcb = &rfcomm_obj->cb; + if (clients[cidx]->cb.pattern_cb) pcb = &clients[cidx]->cb; + res = match_pattern(clients[cidx]->buf, clients[cidx]->iput, pcb->pattern, pcb->pattern_len); + if (res >= 0) { + // found, pull data, including pattern from buffer + uint8_t *dtmp = malloc(res + pcb->pattern_len); + if (dtmp) { + rfcomm_buf_get(cidx, dtmp, res + pcb->pattern_len); + _sched_callback(pcb->pattern_cb, cidx, RFCOMM_CB_TYPE_PATTERN, res, dtmp, NULL); + free(dtmp); + } + } + } + else { + ESP_LOGD(SPP_TAG, "[client %d] Data received: len=%d, in buffer=%d", cidx, param->data_ind.len, clients[cidx]->iput); + } + } + } + break; + } + + case ESP_SPP_CONG_EVT: + _rfcomm_event_status(-1, 7, NULL); + break; + + case ESP_SPP_WRITE_EVT: + _rfcomm_event_status(-1, 8, NULL); + break; + + case ESP_SPP_SRV_OPEN_EVT: + { + char btaddr[13] = {0}; + for (res = 0; res < 6; res++) { + sprintf(btaddr+(res*2), "%02X", param->srv_open.rem_bda[res]); + } + // Add the new client to clients list + int idx; + for (idx=0; idxsrv_open.handle); + ESP_LOGE(SPP_TAG, "Error allocating client's data for client %d [%s]", idx, btaddr); + break; + } + memset(clients[idx], 0, sizeof(rfcomm_client_t)); + // Allocate the client's buffer + clients[idx]->buf = malloc(rfcomm_obj->buffer_size); + if (clients[idx]->buf == NULL) { + free(clients[idx]); + clients[idx] = NULL; + esp_spp_disconnect(param->srv_open.handle); + ESP_LOGE(SPP_TAG, "Error allocating data buffer for client %d [%s]", idx, btaddr); + break; + } + clients[idx]->size = rfcomm_obj->buffer_size; + clients[idx]->handle = param->srv_open.handle; + clients[idx]->wr_handle = param->write.handle; + memcpy(clients[idx]->client_btaddr, param->srv_open.rem_bda, ESP_BD_ADDR_LEN); + memcpy(clients[idx]->cb.lineend, rfcomm_obj->cb.lineend, sizeof(rfcomm_obj->cb.lineend)); + + _rfcomm_event_status(idx, 9, btaddr); + rfcomm_obj->connected++; + break; + } + } + if (idx >= RFCOMM_MAX_CLIENTS) { + esp_spp_disconnect(param->srv_open.handle); + ESP_LOGW(SPP_TAG, "Maximal number of clients (%d) already connected", RFCOMM_MAX_CLIENTS); + } + break; + } + default: + break; + } + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); +} + + +//-------------------------------------------------------------------------------- +static char *_rfcomm_read(uint8_t client, int timeout, char *lnend, char *lnstart) +{ + char *rdstr = NULL; + int rdlen = -1; + int minlen = strlen(lnend); + if (lnstart) minlen += strlen(lnstart); + + if (timeout == 0) { + if (rfcomm_mutex) { + if (xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + return NULL; + } + } + // check for minimal length + if (clients[client]->iput < minlen) { + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + return NULL; + } + while (1) { + rdlen = match_pattern(clients[client]->buf, clients[client]->iput, (uint8_t *)lnend, strlen(lnend)); + if (rdlen >= 0) { + // found, pull data, including pattern from buffer + rdlen += 2; + rdstr = calloc(rdlen+1, 1); + if (rdstr) { + rfcomm_buf_get(client, (uint8_t *)rdstr, rdlen); + rdstr[rdlen] = 0; + if (lnstart) { + // Match beginning string + char *start_ptr = strstr(rdstr, lnstart); + if (start_ptr) { + if (start_ptr != rdstr) { + char *new_rdstr = strdup(start_ptr); + free(rdstr); + rdstr = new_rdstr; + } + break; + } + else { + free(rdstr); + rdstr = NULL; + rdlen = -1; + break; + } + } + else break; + } + else { + rdlen = -1; + break; + } + } + else break; + } + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + if (rdlen < 0) return NULL; + } + else { + // wait until lnend received or timeout + int wait = timeout; + int buflen = 0; + mp_hal_set_wdt_tmo(); + while (wait > 0) { + if (rfcomm_mutex) { + if (xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + vTaskDelay(10 / portTICK_PERIOD_MS); + wait -= 10; + mp_hal_reset_wdt(); + continue; + } + } + if (buflen < clients[client]->iput) { + // ** new data received, reset timeout + buflen = clients[client]->iput; + wait = timeout; + } + if (clients[client]->iput < minlen) { + // ** too few characters received + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + vTaskDelay(10 / portTICK_PERIOD_MS); + wait -= 10; + mp_hal_reset_wdt(); + continue; + } + + while (1) { + // * Check if lineend pattern is received + rdlen = match_pattern(clients[client]->buf, clients[client]->iput, (uint8_t *)lnend, strlen(lnend)); + if (rdlen >= 0) { + rdlen += 2; + // * found, pull data, including pattern from buffer + rdstr = calloc(rdlen+1, 1); + if (rdstr) { + rfcomm_buf_get(client, (uint8_t *)rdstr, rdlen); + rdstr[rdlen] = 0; + if (lnstart) { + // * Find beginning of the sentence + char *start_ptr = strstr(rdstr, lnstart); + if (start_ptr) { + // === received string ending with lnend and starting with lnstart + if (start_ptr != rdstr) { + char *new_rdstr = strdup(start_ptr); + free(rdstr); + rdstr = new_rdstr; + } + break; + } + else { + free(rdstr); + rdstr = NULL; + break; + } + } + else break; // === received string ending with lineend + } + else { + // error allocating buffer, finish + wait = 0; + break; + } + } + else break; + } + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + if (rdstr) break; + if (wait > 0) { + vTaskDelay(10 / portTICK_PERIOD_MS); + wait -= 10; + mp_hal_reset_wdt(); + } + } + } + return rdstr; +} + +//----------------------------------------------------------------------------------------------- +STATIC int _machine_rfcomm_read(mp_obj_t self_in, uint8_t client, void *buf_in, mp_uint_t size) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // make sure we want at least 1 char + if (size == 0) return 0; + + int bytes_read = 0; + if (self->timeout == 0) { + // just return the buffer content + if (rfcomm_mutex) { + if (xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + return 0; + } + } + bytes_read = rfcomm_buf_get(client, (uint8_t *)buf_in, size); + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + if (bytes_read < 0) bytes_read = 0; + } + else { + // wait until data received or timeout + mp_hal_set_wdt_tmo(); + int wait = self->timeout; + MP_THREAD_GIL_EXIT(); + while (wait > 0) { + if (rfcomm_mutex) { + if (xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + vTaskDelay(2 / portTICK_PERIOD_MS); + wait -= 2; + mp_hal_reset_wdt(); + continue; + } + } + if (clients[client]->iput < size) { + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + vTaskDelay(2 / portTICK_PERIOD_MS); + wait -= 2; + mp_hal_reset_wdt(); + continue; + } + bytes_read = rfcomm_buf_get(client, (uint8_t *)buf_in, size); + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + break; + } + MP_THREAD_GIL_ENTER(); + } + + return bytes_read; +} + + +/******************************************************************************/ +// MicroPython bindings for UART + + +//------------------------------------------------------------------- +static void _check_rfcomm(machine_rfcomm_obj_t *self, int chk_client) +{ + if ((!self->init) || (rfcomm_obj == NULL)) { + mp_raise_ValueError("RFCOMM not initialized"); + } + + if (chk_client >= -1) { + if (self->connected <= 0) { + mp_raise_ValueError("No client connected"); + } + if (chk_client >= 0) { + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + if (clients[chk_client] == NULL) { + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + mp_raise_ValueError("Client not connected"); + } + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + } + } +} + +//------------------------------------------------------------------------------------------------- +STATIC void machine_rfcomm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if ((!self->init) || (rfcomm_obj == NULL)) { + mp_printf(print, "RFCOMM(%s: Deinitialized )", self->device_name); + return; + } + + char tmps[16] = {'\0'}; + int lnend_idx = 0; + for (int i=0; i < strlen((char *)self->cb.lineend); i++) { + if (self->cb.lineend[i] == 0) break; + if ((self->cb.lineend[i] < 32) || (self->cb.lineend[i] > 126)) { + if (self->cb.lineend[i] == '\r') { + sprintf(tmps+lnend_idx, "\\r"); + lnend_idx += 2; + } + else if (self->cb.lineend[i] == '\n') { + sprintf(tmps+lnend_idx, "\\n"); + lnend_idx += 2; + } + else { + sprintf(tmps+lnend_idx, "\\x%2x", self->cb.lineend[i]); + lnend_idx += 4; + } + } + else { + sprintf(tmps+lnend_idx, "%c", self->cb.lineend[i]); + lnend_idx++; + } + } + + mp_printf(print, "RFCOMM(%s: channel=%d, timeout=%u, buf_size=%u, lineend=b'%s')", self->device_name, self->channel, self->timeout, self->buffer_size, tmps); + + if (self->connected) { + mp_printf(print, "\n Connected clients: %d (", self->connected); + int nclients = 0; + for (int client=0; client < RFCOMM_MAX_CLIENTS; client++) { + if (clients[client]) { + memset(tmps, 0, 16); + for (int i = 0; i<6; i++) { + sprintf(tmps+(i*2), "%02X", clients[client]->client_btaddr[i]); + } + if (nclients > 0) mp_printf(print, ", "); + nclients++; + mp_printf(print, "%s [id=%d]", tmps, client); + } + } + mp_printf(print, ")", tmps); + } + if (self->cb.data_cb) { + mp_printf(print, "\n data CB: True, on len: %d", self->cb.data_cb_size); + } + if (self->cb.pattern_cb) { + char pattern[80] = {'\0'}; + for (int i=0; icb.pattern_len; i++) { + if ((self->cb.pattern[i] >= 0x20) && (self->cb.pattern[i] < 0x7f)) pattern[strlen(pattern)] = self->cb.pattern[i]; + else sprintf(pattern+strlen(pattern), "\\x%02x", self->cb.pattern[i]); + } + mp_printf(print, "\n pattern CB: True, pattern: b'%s'", pattern); + } + if (self->status_cb) { + mp_printf(print, "\n status CB: True"); + } +} + +//---------------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_channel, ARG_device, ARG_server, ARG_timeout, ARG_buffer_size, ARG_lineend }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_device, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_server, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 512} }, + { MP_QSTR_lineend, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + if (rfcomm_obj) { + mp_raise_msg(&mp_type_OSError, "RFCOMM object already created, only one allowed"); + } + + if (rfcomm_mutex == NULL) { + rfcomm_mutex = xSemaphoreCreateMutex(); + } + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if ((args[ARG_channel].u_int < 0) || (args[ARG_channel].u_int < 0)) { + mp_raise_ValueError("invalid channel (0-79 allowed)"); + } + // Create UART instance, set defaults + machine_rfcomm_obj_t *self = m_new_obj(machine_rfcomm_obj_t); + self->base.type = &machine_rfcomm_type; + self->timeout = 0; + self->cb.pattern[0] = 0; + self->cb.pattern_len = 0; + self->cb.data_cb = NULL; + self->cb.pattern_cb = NULL; + self->status_cb = NULL; + self->cb.data_cb_size = 0; + self->role = ESP_SPP_ROLE_SLAVE; + self->sec_mask = ESP_SPP_SEC_NONE; + self->init = false; + self->channel = (uint8_t)args[ARG_channel].u_int; + + // Set names + if (args[ARG_device].u_obj != mp_const_none) { + const char *device = mp_obj_str_get_str(args[ARG_device].u_obj); + memset(self->device_name, 0, sizeof(self->device_name)); + snprintf(self->device_name, sizeof(self->device_name), "%s", device); + } + else { + sprintf(self->device_name, "MicroPython_RFCOMM"); + } + + if (args[ARG_server].u_obj != mp_const_none) { + const char *device = mp_obj_str_get_str(args[ARG_server].u_obj); + memset(self->server_name, 0, sizeof(self->server_name)); + snprintf(self->server_name, sizeof(self->server_name)-1, "%s", device); + } + else { + sprintf(self->server_name, "ESP32_SPP_Server"); + } + + // set timeout + if (args[ARG_timeout].u_int >= 0) self->timeout = args[ARG_timeout].u_int; + + // set line end + sprintf((char *)self->cb.lineend, "\r\n"); + mp_buffer_info_t lnend_buff; + mp_obj_type_t *lne_type = mp_obj_get_type(args[ARG_lineend].u_obj); + if (lne_type->buffer_p.get_buffer != NULL) { + int ret = lne_type->buffer_p.get_buffer(args[ARG_lineend].u_obj, &lnend_buff, MP_BUFFER_READ); + if (ret == 0) { + if ((lnend_buff.len > 0) && (lnend_buff.len < sizeof(self->cb.lineend))) { + memset(self->cb.lineend, 0, sizeof(self->cb.lineend)); + memcpy(self->cb.lineend, lnend_buff.buf, lnend_buff.len); + } + } + } + + // Set buffer size + int bufsize = args[ARG_buffer_size].u_int; + if (bufsize < 512) bufsize = 512; + if (bufsize > 8192) bufsize = 8192; + self->buffer_size = bufsize; + + self->init = true; + + rfcomm_obj = self; + + if (!bt_controller_is_init) { + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + if (esp_bt_controller_init(&bt_cfg) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "BT controller initialization failed"); + } + bt_controller_is_init = true; + } + if (esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "BT controller enable failed"); + } + if (esp_bluedroid_init() != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Bluedroid initialization failed"); + } + if (esp_bluedroid_enable() != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Bluedroid enable failed"); + } + if (esp_spp_register_callback(rfcomm_spp_cb) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "BT event callback registration failed"); + } + + if (esp_spp_init(ESP_SPP_MODE_CB) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "BT SPP initialization failed"); + } + + return MP_OBJ_FROM_PTR(self); +} + +//--------------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_client, ARG_timeout, ARG_buffer_size, ARG_lineend }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_client, MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_lineend, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _check_rfcomm(self, -2); + + // set timeout + if (args[ARG_timeout].u_int >= 0) self->timeout = args[ARG_timeout].u_int; + + // set line end + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + rfcomm_cb_obj_t *pcb = &self->cb; + if ((args[ARG_client].u_int >= 0) && (clients[args[ARG_client].u_int])) pcb = &clients[args[ARG_client].u_int]->cb; + + mp_buffer_info_t lnend_buff; + mp_obj_type_t *lne_type = mp_obj_get_type(args[ARG_lineend].u_obj); + if (lne_type->buffer_p.get_buffer != NULL) { + int ret = lne_type->buffer_p.get_buffer(args[ARG_lineend].u_obj, &lnend_buff, MP_BUFFER_READ); + if (ret == 0) { + if ((lnend_buff.len > 0) && (lnend_buff.len < sizeof(pcb->lineend))) { + memset(pcb->lineend, 0, sizeof(pcb->lineend)); + memcpy(pcb->lineend, lnend_buff.buf, lnend_buff.len); + } + } + } + + // Set buffer size + if ((args[ARG_buffer_size].u_int >= 512) && (args[ARG_buffer_size].u_int <= 8192)) { + if (args[ARG_buffer_size].u_int != self->buffer_size) { + self->buffer_size = args[ARG_buffer_size].u_int; + } + } + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_rfcomm_init_obj, 1, machine_rfcomm_init); + +//------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_deinit(mp_obj_t self_in) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->init) { + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + for (int i=0; ibuf) free(clients[i]->buf); + free(clients[i]); + clients[i] = NULL; + break; + } + } + rfcomm_obj = NULL; + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + esp_spp_deinit(); + esp_bluedroid_disable(); + esp_bluedroid_deinit(); + esp_bt_controller_disable(); + //esp_bt_controller_deinit(); + + self->init = false; + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rfcomm_deinit_obj, machine_rfcomm_deinit); + +//--------------------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_any(mp_obj_t self_in, mp_obj_t client) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + int idx = mp_obj_get_int(client); + + _check_rfcomm(self, idx); + + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + int res = clients[idx]->iput; + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + return MP_OBJ_NEW_SMALL_INT(res); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rfcomm_any_obj, machine_rfcomm_any); + +//------------------------------------------------------------------- +mp_obj_t machine_rfcomm_readln(size_t n_args, const mp_obj_t *args) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + int idx = mp_obj_get_int(args[1]); + _check_rfcomm(self, idx); + + int timeout = self->timeout; + if (n_args > 1) timeout = mp_obj_get_int(args[2]); + + const char *startstr = NULL; + if (n_args > 3) startstr = mp_obj_str_get_str(args[3]); + + MP_THREAD_GIL_EXIT(); + char *rdstr = _rfcomm_read(idx, timeout, (char *)clients[idx]->cb.lineend, (char *)startstr); + MP_THREAD_GIL_ENTER(); + + if (rdstr == NULL) return mp_const_none; + mp_obj_t res_str = mp_obj_new_str((const char *)rdstr, strlen(rdstr)); + if (rdstr != NULL) free(rdstr); + return res_str; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rfcomm_readln_obj, 2, 4, machine_rfcomm_readln); + +//------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_read(mp_obj_t self_in, mp_obj_t client, mp_obj_t len_in) +{ + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + int idx = mp_obj_get_int(client); + + _check_rfcomm(self, idx); + + vstr_t vstr; + int len = mp_obj_get_int(len_in); + vstr_init_len(&vstr, len); + + int res = _machine_rfcomm_read(self, idx, vstr.buf, len); + + if (res <= 0) return mp_const_empty_bytes; + + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_rfcomm_read_obj, machine_rfcomm_read); + +//------------------------------------------------------------------------------------------ +STATIC mp_obj_t machine_rfcomm_readinto(mp_obj_t self_in, mp_obj_t client, mp_obj_t buf_out) +{ + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + int idx = mp_obj_get_int(client); + + _check_rfcomm(self, idx); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_out, &bufinfo, MP_BUFFER_WRITE); + + int res = _machine_rfcomm_read(self, idx, bufinfo.buf, bufinfo.len); + + if (res <= 0) return MP_OBJ_NEW_SMALL_INT(0); + + return MP_OBJ_NEW_SMALL_INT(res); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_rfcomm_readinto_obj, machine_rfcomm_readinto); + +//---------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_write(mp_obj_t self_in, mp_obj_t client, mp_obj_t buf_in) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + int idx = mp_obj_get_int(client); + + _check_rfcomm(self, idx); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + + int res = -1; + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + res = esp_spp_write(clients[idx]->wr_handle, bufinfo.len, (uint8_t *)bufinfo.buf); + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + if (res != ESP_OK) return MP_OBJ_NEW_SMALL_INT(0); + return MP_OBJ_NEW_SMALL_INT(bufinfo.len); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_rfcomm_write_obj, machine_rfcomm_write); + +//---------------------------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_disconnect(mp_obj_t self_in, mp_obj_t client) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + int idx = mp_obj_get_int(client); + + _check_rfcomm(self, idx); + + int res = -1; + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + res = esp_spp_disconnect(clients[idx]->handle); + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + return (res == ESP_OK) ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rfcomm_disconnect_obj, machine_rfcomm_disconnect); + +//---------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_connected(mp_obj_t self_in) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + _check_rfcomm(self, -2); + + mp_obj_t tuple[2]; + + tuple[0] = mp_obj_new_int(self->connected); + + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + + if (self->connected) { + char btaddr[13] = {0}; + mp_obj_t clients_tuple[self->connected]; + mp_obj_t client_tuple[2]; + int client = 0; + for (int idx=0; idxclient_btaddr[i]); + } + client_tuple[0] = mp_obj_new_int(idx); + client_tuple[1] = mp_obj_new_str(btaddr, strlen(btaddr)); + clients_tuple[client++] = mp_obj_new_tuple(2, client_tuple); + } + } + tuple[1] = mp_obj_new_tuple(self->connected, clients_tuple); + } + else tuple[1] = mp_const_none; + + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rfcomm_connected_obj, machine_rfcomm_connected); + +//-------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_channel(mp_obj_t self_in) { + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(self_in); + + _check_rfcomm(self, -2); + + return MP_OBJ_NEW_SMALL_INT(self->channel); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_rfcomm_channel_obj, machine_rfcomm_channel); + +//------------------------------------------------------------------------------------------------- +STATIC mp_obj_t machine_rfcomm_callback(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_type, ARG_func, ARG_client, ARG_pattern, ARG_datalen }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_type, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_func, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_client, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -2 } }, + { MP_QSTR_pattern, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_data_len, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + }; + + machine_rfcomm_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + int client = args[ARG_client].u_int; + if ((client != -2) && ((client < 0) || (client >= RFCOMM_MAX_CLIENTS))) { + mp_raise_ValueError("invalid client id"); + } + _check_rfcomm(self, client); + + int datalen = -1; + mp_buffer_info_t pattern_buff; + int cbtype = args[ARG_type].u_int; + if ((cbtype != RFCOMM_CB_TYPE_DATA) && (cbtype != RFCOMM_CB_TYPE_PATTERN) && (cbtype != RFCOMM_CB_TYPE_STATUS)) { + mp_raise_ValueError("invalid callback type"); + } + + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + rfcomm_cb_obj_t *pcb = &self->cb; + if ((args[ARG_client].u_int >= 0) && (cbtype != RFCOMM_CB_TYPE_STATUS) && (clients[args[ARG_client].u_int])) pcb = &clients[args[ARG_client].u_int]->cb; + + if ((!MP_OBJ_IS_FUN(args[ARG_func].u_obj)) && (!MP_OBJ_IS_METH(args[ARG_func].u_obj))) { + // === CB function not given, disable callback === + switch(cbtype) { + case RFCOMM_CB_TYPE_DATA: + pcb->data_cb = NULL; + pcb->data_cb_size = 0; + break; + case RFCOMM_CB_TYPE_PATTERN: + pcb->pattern_cb = NULL; + pcb->pattern[0] = 0; + pcb->pattern_len = 0; + break; + case RFCOMM_CB_TYPE_STATUS: + self->status_cb = NULL; + break; + default: + break; + } + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + return mp_const_none; + } + + // Get and check callback parameters + switch(cbtype) { + case RFCOMM_CB_TYPE_DATA: + if ((args[ARG_datalen].u_int <= 0) || (args[ARG_datalen].u_int >= self->buffer_size)) { + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + mp_raise_ValueError("invalid data length"); + } + datalen = args[ARG_datalen].u_int; + break; + case RFCOMM_CB_TYPE_PATTERN: + { + bool has_pattern = false; + mp_obj_type_t *type = mp_obj_get_type(args[ARG_pattern].u_obj); + if (type->buffer_p.get_buffer != NULL) { + int ret = type->buffer_p.get_buffer(args[ARG_pattern].u_obj, &pattern_buff, MP_BUFFER_READ); + if (ret == 0) { + if ((pattern_buff.len > 0) && (pattern_buff.len <= sizeof(pcb->pattern))) has_pattern = true; + } + } + if (!has_pattern) { + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + mp_raise_ValueError("invalid pattern"); + } + } + break; + default: + break; + } + + // Set the callback + if (rfcomm_mutex) xSemaphoreTake(rfcomm_mutex, 200 / portTICK_PERIOD_MS); + switch(cbtype) { + case RFCOMM_CB_TYPE_DATA: + pcb->data_cb_size = datalen; + pcb->data_cb = args[ARG_func].u_obj; + break; + case RFCOMM_CB_TYPE_PATTERN: + memcpy(pcb->pattern, pattern_buff.buf, pattern_buff.len); + pcb->pattern_len = pattern_buff.len; + pcb->pattern_cb = args[ARG_func].u_obj; + break; + case RFCOMM_CB_TYPE_STATUS: + self->status_cb = args[ARG_func].u_obj; + break; + default: + break; + } + if (rfcomm_mutex) xSemaphoreGive(rfcomm_mutex); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_rfcomm_callback_obj, 2, machine_rfcomm_callback); + + +//=================================================================== +STATIC const mp_rom_map_elem_t machine_rfcomm_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rfcomm_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_rfcomm_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_rfcomm_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_rfcomm_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&machine_rfcomm_readln_obj) }, + { MP_ROM_QSTR(MP_QSTR_readln), MP_ROM_PTR(&machine_rfcomm_readln_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_rfcomm_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_rfcomm_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&machine_rfcomm_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&machine_rfcomm_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&machine_rfcomm_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&machine_rfcomm_channel_obj) }, + + // class constants + { MP_ROM_QSTR(MP_QSTR_CBTYPE_DATA), MP_ROM_INT(RFCOMM_CB_TYPE_DATA) }, + { MP_ROM_QSTR(MP_QSTR_CBTYPE_PATTERN), MP_ROM_INT(RFCOMM_CB_TYPE_PATTERN) }, + { MP_ROM_QSTR(MP_QSTR_CBTYPE_STATUS), MP_ROM_INT(RFCOMM_CB_TYPE_STATUS) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_rfcomm_locals_dict, machine_rfcomm_locals_dict_table); + + +//========================================= +const mp_obj_type_t machine_rfcomm_type = { + { &mp_type_type }, + .name = MP_QSTR_RFCOMM, + .print = machine_rfcomm_print, + .make_new = machine_rfcomm_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_rfcomm_locals_dict, +}; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c index 95ec4d2f..d0296d6b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c @@ -31,62 +31,35 @@ #include #include +#include "sdkconfig.h" #include "apps/sntp/sntp.h" +#include "driver/rtc_io.h" +#include "esp_log.h" +#include "rom/crc.h" #include "py/nlr.h" #include "py/obj.h" #include "py/objstr.h" #include "py/runtime.h" -#include "esp_system.h" #include "machine_rtc.h" -#include "soc/rtc.h" -#include "esp_clk.h" -#include "sdkconfig.h" -#include "esp_attr.h" -#include "esp_log.h" -#include "rom/ets_sys.h" -#include "rom/uart.h" -#include "rom/crc.h" -#include "soc/soc.h" -#include "soc/rtc.h" -#include "soc/rtc_cntl_reg.h" #include "mphalport.h" +#include "modmachine.h" +#include "mpsleep.h" + #define RTC_MEM_INT_SIZE 64 #define RTC_MEM_STR_SIZE 2048 -#define MACHINE_RTC_VALID_EXT_PINS \ -( \ - (1ll << 0) | \ - (1ll << 2) | \ - (1ll << 4) | \ - (1ll << 12) | \ - (1ll << 13) | \ - (1ll << 14) | \ - (1ll << 15) | \ - (1ll << 25) | \ - (1ll << 26) | \ - (1ll << 27) | \ - (1ll << 32) | \ - (1ll << 33) | \ - (1ll << 34) | \ - (1ll << 35) | \ - (1ll << 36) | \ - (1ll << 37) | \ - (1ll << 38) | \ - (1ll << 39) \ -) - -#define MACHINE_RTC_LAST_EXT_PIN 39 +extern int MainTaskCore; + +char mpy_time_zone[64] = {'\0'}; static int RTC_DATA_ATTR rtc_mem_int[RTC_MEM_INT_SIZE] = { 0 }; static char RTC_DATA_ATTR rtc_mem_str[RTC_MEM_STR_SIZE] = { 0 }; static uint16_t RTC_DATA_ATTR rtc_mem_int_crc; static uint16_t RTC_DATA_ATTR rtc_mem_str_crc; -machine_rtc_config_t machine_rtc_config = { 0, -1, 0, 0, 0 }; - static TaskHandle_t sntp_handle = NULL; xSemaphoreHandle sntp_mutex = NULL; @@ -105,14 +78,6 @@ static RTC_DATA_ATTR uint64_t seconds_at_boot; static mach_rtc_obj_t mach_rtc_obj; const mp_obj_type_t mach_rtc_type; -//------------------------------------------------------------ -static void mach_rtc_set_seconds_since_epoch(uint64_t nowus) { - struct timeval tv; - - // store the packet timestamp - gettimeofday(&tv, NULL); - seconds_at_boot = tv.tv_sec; -} //------------------------ static void rtc_init_mem() @@ -125,11 +90,15 @@ static void rtc_init_mem() //-------------------- void rtc_init0(void) { - mach_rtc_set_seconds_since_epoch(0); - rtc_init_mem(); + mpsleep_reset_cause_t rstc = mpsleep_get_reset_cause(); + if ((rstc != MPSLEEP_DEEPSLEEP_RESET) && (rstc != MPSLEEP_SOFT_RESET) && (rstc != MPSLEEP_SOFT_CPU_RESET)) { + seconds_at_boot = 0; + setTicks_base(0); + rtc_init_mem(); + } } -// Set system datetime +// Set system date time //------------------------------------------------------- STATIC mp_obj_t mach_rtc_datetime(const mp_obj_t *args) { struct tm tm_info; @@ -178,7 +147,7 @@ STATIC mp_obj_t mach_rtc_datetime(const mp_obj_t *args) { // Set new base for ticks counting setTicks_base((((uint64_t)now.tv_sec * 1000000) - ticks_us)); - mach_rtc_set_seconds_since_epoch(seconds); + seconds_at_boot = seconds; return mp_const_none; } @@ -300,6 +269,29 @@ void sntp_task (void *pvParameters) vTaskDelete(NULL); } +//-------------------------------------------- +void tz_fromto_NVS(char *gettzs, char *settzs) +{ + size_t len = 0; + char value[64] = {'\0'}; + if (gettzs) { + gettzs[0] = '\0'; + esp_err_t ret = nvs_get_str(mpy_nvs_handle, "MpyTimeZone", NULL, &len); + if ((ret == ESP_OK ) && (len > 0) && (len < 64)) { + esp_err_t ret = nvs_get_str(mpy_nvs_handle, "MpyTimeZone", value, &len); + if ((ret == ESP_OK ) && (len > 0) && (len < 64)) { + if (gettzs) strcpy(gettzs, value); + } + } + } + if (settzs) { + esp_err_t esp_err = nvs_set_str(mpy_nvs_handle, "MpyTimeZone", settzs); + if (ESP_OK == esp_err) { + nvs_commit(mpy_nvs_handle); + } + } +} + //--------------------------------------------------------------------------------------------- STATIC mp_obj_t mach_rtc_ntp_sync(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { @@ -323,23 +315,30 @@ STATIC mp_obj_t mach_rtc_ntp_sync(size_t n_args, const mp_obj_t *pos_args, mp_ma if ((strlen(srvn) > 3) && (strlen(srvn) < 64)) sprintf(srv_name, "%s", srvn); } - char tz[64]; - #ifdef MICROPY_TIMEZONE - // ===== Set time zone ====== - sprintf(tz, "%s", MICROPY_TIMEZONE); + if (strlen(mpy_time_zone) == 0) { + // Try to get tz from NVS + tz_fromto_NVS(mpy_time_zone, NULL); + if (strlen(mpy_time_zone) == 0) { + #ifdef MICROPY_TIMEZONE + // ===== Set default time zone ====== + snprintf(mpy_time_zone, sizeof(mpy_time_zone)-1, "%s", MICROPY_TIMEZONE); + #endif + } + } + if (args[2].u_obj != mp_const_none) { + // get TZ argument const char *tzs = mp_obj_str_get_str(args[2].u_obj); - if (strlen(tzs) < 64) { - sprintf(tz, "%s", tzs); + if ((strlen(tzs) > 2) && (strlen(tzs) < 64)) { + sprintf(mpy_time_zone, "%s", tzs); + tz_fromto_NVS(NULL, mpy_time_zone); + } + else { + mp_raise_ValueError("tz string length must be 3 - 63"); } } - setenv("TZ", tz, 0); + setenv("TZ", mpy_time_zone, 1); tzset(); - // ========================== - #else - tz[0] = '\0'; - #endif - if (sntp_mutex == NULL) { // Create sntp mutex @@ -361,7 +360,12 @@ STATIC mp_obj_t mach_rtc_ntp_sync(size_t n_args, const mp_obj_t *pos_args, mp_ma if (sntp_handle == NULL) { // Create and start sntp task - if (xTaskCreate(&sntp_task, "SNTP_TASK", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY+1, &sntp_handle) != pdPASS) { + #if CONFIG_MICROPY_USE_BOTH_CORES + int tres = xTaskCreate(&sntp_task, "SNTP_TASK", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &sntp_handle); + #else + int tres = xTaskCreatePinnedToCore(&sntp_task, "SNTP_TASK", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &sntp_handle, MainTaskCore); + #endif + if (tres != pdTRUE) { mp_raise_msg(&mp_type_OSError, "Error creating SNTP task"); } } @@ -406,27 +410,43 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mach_rtc_sntp_state_obj, mach_rtc_sntp_state); //---------------------------------------------------------------------------------------------------- STATIC mp_obj_t machine_rtc_wake_on_ext0(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum {ARG_pin, ARG_level}; + enum {ARG_pin, ARG_level, ARG_count}; const mp_arg_t allowed_args[] = { - { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = mp_obj_new_int(machine_rtc_config.ext0_pin)} }, - { MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext0_level} }, + { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = mp_obj_new_int(machine_rtc_config.ext0_pin)} }, + { MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext0_level} }, + { MP_QSTR_count, MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_pin].u_obj == mp_const_none) { machine_rtc_config.ext0_pin = -1; // "None" - } else { - gpio_num_t pin_id = machine_pin_get_id(args[ARG_pin].u_obj); + } + else { + int pin_id = machine_pin_get_gpio(args[ARG_pin].u_obj); if (pin_id != machine_rtc_config.ext0_pin) { - if (!((1ll << pin_id) & MACHINE_RTC_VALID_EXT_PINS)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); + if (!rtc_gpio_is_valid_gpio(pin_id)) { + mp_raise_ValueError("Invalid ext0 pin"); + } + rtc_gpio_init(pin_id); + rtc_gpio_set_direction(pin_id, RTC_GPIO_MODE_INPUT_ONLY); + if (args[ARG_level].u_bool) { + rtc_gpio_pulldown_en(pin_id); + rtc_gpio_pullup_dis(pin_id); } - machine_rtc_config.ext0_pin = pin_id; + else { + rtc_gpio_pulldown_dis(pin_id); + rtc_gpio_pullup_en(pin_id); + } + rtc_gpio_hold_en(pin_id); + machine_rtc_config.ext0_pin = (int8_t)pin_id; + machine_rtc_config.ext0_rtcpin = rtc_gpio_desc[pin_id].rtc_num; } } machine_rtc_config.ext0_level = args[ARG_level].u_bool; + machine_rtc_config.ext0_count = args[ARG_count].u_int; + machine_rtc_config.pulse_count = 0; return mp_const_none; } @@ -436,37 +456,65 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_rtc_wake_on_ext0_obj, 1, machine_rtc_w STATIC mp_obj_t machine_rtc_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_pins, ARG_level}; const mp_arg_t allowed_args[] = { - { MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext1_level} }, + { MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_level, MP_ARG_INT, {.u_int = machine_rtc_config.ext1_level} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - uint64_t ext1_pins = machine_rtc_config.ext1_pins; + uint8_t ext1_pins[EXT1_WAKEUP_MAX_PINS] = {-1}; + uint32_t ext1_rtcpins[EXT1_WAKEUP_MAX_PINS] = {0}; + for (int i=0; i 2)) { + mp_raise_ValueError("Invalid ext1 level !"); + } // Check that all pins are allowed if (args[ARG_pins].u_obj != mp_const_none) { mp_uint_t len = 0; mp_obj_t *elem; mp_obj_get_array(args[ARG_pins].u_obj, &len, &elem); - ext1_pins = 0; - - for (int i = 0; i < len; i++) { + int pins = (len > EXT1_WAKEUP_MAX_PINS) ? EXT1_WAKEUP_MAX_PINS : len; - gpio_num_t pin_id = machine_pin_get_id(elem[i]); - // mp_int_t pin = mp_obj_get_int(elem[i]); - uint64_t pin_bit = (1ll << pin_id); + for (int i = 0; i < pins; i++) { + int pin_id = machine_pin_get_gpio(elem[i]); - if (!(pin_bit & MACHINE_RTC_VALID_EXT_PINS)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin")); + if (!rtc_gpio_is_valid_gpio(pin_id)) { + mp_raise_ValueError("Invalid ext1 pin"); break; } - ext1_pins |= pin_bit; + rtc_gpio_init(pin_id); + rtc_gpio_set_direction(pin_id, RTC_GPIO_MODE_INPUT_ONLY); + if (args[ARG_level].u_bool) { + rtc_gpio_pulldown_en(pin_id); + rtc_gpio_pullup_dis(pin_id); + } + else { + rtc_gpio_pulldown_dis(pin_id); + rtc_gpio_pullup_en(pin_id); + } + rtc_gpio_hold_en(pin_id); + ext1_pins[i] = pin_id; + ext1_rtcpins[i] = rtc_gpio_desc[pin_id].rtc_num; + } + } + else { + for (int i=0; i= 0) { + sprintf(ext0, "Wake on EXT0: Pin=%d, Level=%s, Count=%d", + machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? "High" : "Low", machine_rtc_config.ext0_count); + } + int has_ext1_pins = 0; + for (int i=0; i= 0) has_ext1_pins++; + } + + if (has_ext1_pins) { + if (strlen(ext0) > 0) strcat(ext0, "; "); + sprintf(ext1, "Wake on EXT1: Pins ("); + char stemp[16]; + for (int i=0; i= 0) { + sprintf(stemp, "%d,", machine_rtc_config.ext1_pins[i]); + strcat(ext1, stemp); + } + } + if (ext1[strlen(ext1)-1] == ',') ext1[strlen(ext1)-1] = '\0'; + strcat(ext1, ")"); + + stemp[0] = '\0'; + if (machine_rtc_config.ext1_level == ESP_EXT1_WAKEUP_ANY_HIGH) sprintf(stemp, "Any High"); + else if (machine_rtc_config.ext1_level == ESP_EXT1_WAKEUP_ALL_LOW) sprintf(stemp, "All Low"); + else if (machine_rtc_config.ext1_level == EXT1_WAKEUP_ALL_HIGH) sprintf(stemp, "All High"); + if (strlen(stemp) > 0) { + strcat(ext1, ", Level: "); + strcat(ext1, stemp); + } + } + mp_printf(print, "RTC ("); + if (strlen(ext0) > 0) mp_printf(print, " %s", ext0); + if (strlen(ext1) > 0) mp_printf(print, "%s", ext1); + mp_printf(print, " )"); +} + //========================================================= STATIC const mp_map_elem_t mach_rtc_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_init), MP_ROM_PTR(&mach_rtc_init_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_now), MP_ROM_PTR(&mach_rtc_now_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ntp_sync), MP_ROM_PTR(&mach_rtc_ntp_sync_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ntp_state), MP_ROM_PTR(&mach_rtc_sntp_state_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_synced), MP_ROM_PTR(&mach_rtc_has_synced_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext0), MP_ROM_PTR(&machine_rtc_wake_on_ext0_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext1), MP_ROM_PTR(&machine_rtc_wake_on_ext1_obj) }, - - {MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&esp_rtcmem_write_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&esp_rtcmem_read_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_clear), MP_ROM_PTR(&esp_rtcmem_clear_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_write_string), MP_ROM_PTR(&esp_rtcmem_write_string_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_read_string), MP_ROM_PTR(&esp_rtcmem_read_string_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mach_rtc_init_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_now), (mp_obj_t)&mach_rtc_now_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ntp_sync), (mp_obj_t)&mach_rtc_ntp_sync_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ntp_state), (mp_obj_t)&mach_rtc_sntp_state_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_synced), (mp_obj_t)&mach_rtc_has_synced_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext0), (mp_obj_t)&machine_rtc_wake_on_ext0_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext1), (mp_obj_t)&machine_rtc_wake_on_ext1_obj }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&esp_rtcmem_write_obj}, + { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&esp_rtcmem_read_obj}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&esp_rtcmem_clear_obj}, + { MP_OBJ_NEW_QSTR(MP_QSTR_write_string), (mp_obj_t)&esp_rtcmem_write_string_obj}, + { MP_OBJ_NEW_QSTR(MP_QSTR_read_string), (mp_obj_t)&esp_rtcmem_read_string_obj}, + + // Constants + { MP_ROM_QSTR(MP_QSTR_EXT1_ANYHIGH), MP_ROM_INT(ESP_EXT1_WAKEUP_ANY_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_EXT1_ALLLOW), MP_ROM_INT(ESP_EXT1_WAKEUP_ALL_LOW) }, + { MP_ROM_QSTR(MP_QSTR_EXT1_ALLHIGH), MP_ROM_INT(EXT1_WAKEUP_ALL_HIGH) }, }; STATIC MP_DEFINE_CONST_DICT(mach_rtc_locals_dict, mach_rtc_locals_dict_table); @@ -567,6 +663,7 @@ STATIC MP_DEFINE_CONST_DICT(mach_rtc_locals_dict, mach_rtc_locals_dict_table); const mp_obj_type_t mach_rtc_type = { { &mp_type_type }, .name = MP_QSTR_RTC, + .print = machine_rtc_print, .make_new = mach_rtc_make_new, .locals_dict = (mp_obj_t)&mach_rtc_locals_dict, }; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h index 7692f97b..f1900c3f 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h +++ b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h @@ -29,19 +29,11 @@ #ifndef MACHRTC_H_ #define MACHRTC_H_ +extern char mpy_time_zone[64]; extern const mp_obj_type_t mach_rtc_type; - -typedef struct { - uint64_t ext1_pins; - int8_t ext0_pin; - bool wake_on_touch : 1; - bool ext0_level : 1; - bool ext1_level : 1; -} machine_rtc_config_t; - - extern xSemaphoreHandle sntp_mutex; void rtc_init0(void); +void tz_fromto_NVS(char *gettzs, char *settzs); #endif // MACHRTC_H_ diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_timer.c b/MicroPython_BUILD/components/micropython/esp32/machine_timer.c index 2f599d35..6e3a7849 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_timer.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_timer.c @@ -54,25 +54,9 @@ #define TIMER_FLAGS 0 -typedef struct _machine_timer_obj_t { - mp_obj_base_t base; - uint8_t id; - uint8_t state; - uint8_t type; - int8_t debug_pin; - mp_uint_t repeat; - mp_uint_t period; - uint64_t event_num; - uint64_t cb_num; - mp_obj_t callback; - intr_handle_t handle; - uint64_t counter; - uint64_t alarm; -} machine_timer_obj_t; - const mp_obj_type_t machine_timer_type; -static machine_timer_obj_t * timers_used[4] = {NULL}; +machine_timer_obj_t * mpy_timers_used[4] = {NULL}; static machine_timer_obj_t * ext_timers[TIMER_EXT_NUM] = {NULL}; @@ -161,14 +145,17 @@ STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, } if (tmr < 4) { // Base hardware timer - if (timers_used[tmr] != NULL) { + if ((tmr == ADC_TIMER_NUM) && (adc_timer_active)) { + mp_raise_ValueError("Timer used by ADC module."); + } + if (mpy_timers_used[tmr] != NULL) { mp_raise_ValueError("Timer already in use."); } - timers_used[tmr] = self; + mpy_timers_used[tmr] = self; } else { // Extended timer - if ((timers_used[0] == NULL) || (timers_used[0]->type != TIMER_TYPE_EXTBASE)) { + if ((mpy_timers_used[0] == NULL) || (mpy_timers_used[0]->type != TIMER_TYPE_EXTBASE)) { mp_raise_ValueError("Timer 0 not configured as extended timer."); } if (ext_timers[(tmr-4)] != NULL) { @@ -187,7 +174,7 @@ STATIC void machine_timer_disable(machine_timer_obj_t *self) if ((self->id < 4) && (self->handle)) { timer_pause((self->id >> 1) & 1, self->id & 1); if (self->type != TIMER_TYPE_CHRONO) esp_intr_free(self->handle); - timers_used[self->id] = NULL; + mpy_timers_used[self->id] = NULL; } else ext_timers[(self->id-4)] = NULL; self->callback = NULL; @@ -215,7 +202,10 @@ STATIC void machine_timer_isr(void *self_in) TIMERG0.hw_timer[self->id & 1].config.alarm_en = self->repeat; } - if (self->debug_pin >= 0) gpio_set_level(self->debug_pin, (self->event_num & 1)); + if (self->debug_pin >= 0) { + if (self->debug_pin_mode >= 0) gpio_set_level(self->debug_pin, (self->debug_pin_mode & 1)); + else gpio_set_level(self->debug_pin, (self->event_num & 1)); + } self->event_num++; if ((self->callback) && (mp_sched_schedule(self->callback, self, NULL))) self->cb_num++; @@ -302,7 +292,7 @@ STATIC void machine_timer_enable(machine_timer_obj_t *self) } check_esp_err(timer_start((self->id >> 1) & 1, self->id & 1)); } - timers_used[self->id] = self; + mpy_timers_used[self->id] = self; } //--------------------------------------------------------------------------------------------------------------------------------- @@ -313,6 +303,7 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_TYPE_PERIODIC} }, { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_dbgpin, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_dbgpinmode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, }; machine_timer_disable(self); @@ -355,6 +346,7 @@ STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n // set the debug gpio if used if ((args[3].u_int >= 0) && (args[3].u_int < 34)) { self->debug_pin = args[3].u_int; + self->debug_pin_mode = args[4].u_int; gpio_pad_select_gpio(self->debug_pin); gpio_set_direction(self->debug_pin, GPIO_MODE_OUTPUT); gpio_set_level(self->debug_pin, 0); @@ -476,7 +468,7 @@ STATIC mp_obj_t machine_timer_resume(mp_obj_t self_in) } } else { - if ((timers_used[0] != NULL) && (timers_used[0]->state == TIMER_RUNNING)) self->state = TIMER_RUNNING; + if ((mpy_timers_used[0] != NULL) && (mpy_timers_used[0]->state == TIMER_RUNNING)) self->state = TIMER_RUNNING; else self->state = TIMER_PAUSED; } return mp_const_none; @@ -664,7 +656,7 @@ STATIC const mp_map_elem_t machine_timer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&machine_timer_init_obj }, { MP_ROM_QSTR(MP_QSTR_value), (mp_obj_t)&machine_timer_value_obj }, { MP_ROM_QSTR(MP_QSTR_events), (mp_obj_t)&machine_timer_events_obj }, - { MP_ROM_QSTR(MP_QSTR_reshot), (mp_obj_t)&machine_timer_shot_obj }, + { MP_ROM_QSTR(MP_QSTR_reshoot), (mp_obj_t)&machine_timer_shot_obj }, { MP_ROM_QSTR(MP_QSTR_start), (mp_obj_t)&machine_timer_start_obj }, { MP_ROM_QSTR(MP_QSTR_stop), (mp_obj_t)&machine_timer_pause_obj }, { MP_ROM_QSTR(MP_QSTR_pause), (mp_obj_t)&machine_timer_pause_obj }, diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_touchpad.c b/MicroPython_BUILD/components/micropython/esp32/machine_touchpad.c index 96de1a2a..d1edd150 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_touchpad.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_touchpad.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2017 Nick Moore + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,6 +36,8 @@ #include "py/runtime.h" #include "py/mphal.h" #include "modmachine.h" +#include "modmachine.h" + typedef struct _mtp_obj_t { mp_obj_base_t base; @@ -42,7 +45,7 @@ typedef struct _mtp_obj_t { touch_pad_t touchpad_id; } mtp_obj_t; -STATIC const mtp_obj_t touchpad_obj[] = { +STATIC mtp_obj_t touchpad_obj[] = { {{&machine_touchpad_type}, GPIO_NUM_4, TOUCH_PAD_NUM0}, {{&machine_touchpad_type}, GPIO_NUM_0, TOUCH_PAD_NUM1}, {{&machine_touchpad_type}, GPIO_NUM_2, TOUCH_PAD_NUM2}, @@ -55,55 +58,86 @@ STATIC const mtp_obj_t touchpad_obj[] = { {{&machine_touchpad_type}, GPIO_NUM_32, TOUCH_PAD_NUM9}, }; -STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, - const mp_obj_t *args) { +static int initialized = 0; +static uint16_t threshold[10] = {0}; + +//------------------------------------------------------------------------------------ +STATIC void mtp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + mtp_obj_t *self = self_in; + mp_printf(print, "Touchpad (Pin=%u, TP=%d, Threshold=%u)", self->gpio_id, self->touchpad_id, threshold[self->touchpad_id]); +} + +//------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) +{ mp_arg_check_num(n_args, n_kw, 1, 1, true); - gpio_num_t pin_id = machine_pin_get_id(args[0]); + gpio_num_t pin_id = machine_pin_get_gpio(args[0]); const mtp_obj_t *self = NULL; + for (int i = 0; i < MP_ARRAY_SIZE(touchpad_obj); i++) { - if (pin_id == touchpad_obj[i].gpio_id) { self = &touchpad_obj[i]; break; } + if (pin_id == touchpad_obj[i].gpio_id) { + self = &touchpad_obj[i]; + break; + } } if (!self) mp_raise_ValueError("invalid pin for touchpad"); - static int initialized = 0; if (!initialized) { touch_pad_init(); initialized = 1; } + threshold[self->touchpad_id] = 0; esp_err_t err = touch_pad_config(self->touchpad_id, 0); - if (err == ESP_OK) return MP_OBJ_FROM_PTR(self); - mp_raise_ValueError("Touch pad error"); + if (err != ESP_OK) { + mp_raise_ValueError("Touch pad config error"); + } + return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t mtp_config(mp_obj_t self_in, mp_obj_t value_in) { +//------------------------------------------------------------- +STATIC mp_obj_t mtp_config(mp_obj_t self_in, mp_obj_t value_in) +{ mtp_obj_t *self = self_in; uint16_t value = mp_obj_get_int(value_in); + esp_err_t err = touch_pad_config(self->touchpad_id, value); - if (err == ESP_OK) return mp_const_none; - mp_raise_ValueError("Touch pad error"); + if (err != ESP_OK) { + mp_raise_ValueError("Touch pad config error"); + } + threshold[self->touchpad_id] = value; + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(mtp_config_obj, mtp_config); -STATIC mp_obj_t mtp_read(mp_obj_t self_in) { +//---------------------------------------- +STATIC mp_obj_t mtp_read(mp_obj_t self_in) +{ mtp_obj_t *self = self_in; uint16_t value; + esp_err_t err = touch_pad_read(self->touchpad_id, &value); - if (err == ESP_OK) return MP_OBJ_NEW_SMALL_INT(value); - mp_raise_ValueError("Touch pad error"); + if (err != ESP_OK) { + mp_raise_ValueError("Touch pad read error"); + } + return MP_OBJ_NEW_SMALL_INT(value); } MP_DEFINE_CONST_FUN_OBJ_1(mtp_read_obj, mtp_read); + +//======================================================== STATIC const mp_rom_map_elem_t mtp_locals_dict_table[] = { // instance methods - { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&mtp_config_obj) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mtp_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&mtp_config_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mtp_read_obj) }, }; - STATIC MP_DEFINE_CONST_DICT(mtp_locals_dict, mtp_locals_dict_table); +//------------------------------------------- const mp_obj_type_t machine_touchpad_type = { { &mp_type_type }, + .print = mtp_print, .name = MP_QSTR_TouchPad, .make_new = mtp_make_new, .locals_dict = (mp_obj_t)&mtp_locals_dict, diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_uart.c b/MicroPython_BUILD/components/micropython/esp32/machine_uart.c index 000225f5..445f69e2 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_uart.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_uart.c @@ -32,52 +32,21 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" -#include "driver/uart.h" - -#include "py/runtime.h" +#include "machine_uart.h" #include "py/stream.h" #include "py/mperrno.h" #include "py/mphal.h" #include "modmachine.h" +#include "sdkconfig.h" + + +extern int MainTaskCore; -#define UART_CB_TYPE_DATA 1 -#define UART_CB_TYPE_PATTERN 2 -#define UART_CB_TYPE_ERROR 3 -#define UART_BUFF_SIZE 256 - -typedef struct _machine_uart_obj_t { - mp_obj_base_t base; - uart_port_t uart_num; - int8_t bits; - int8_t parity; - int8_t stop; - int8_t tx; - int8_t rx; - int8_t rts; - int8_t cts; - int data_cb_size; - uint8_t pattern[16]; - uint8_t pattern_len; - uint16_t timeout; // timeout waiting for first char (in ms) - uint16_t buffer_size; - uint32_t *data_cb; - uint32_t *pattern_cb; - uint32_t *error_cb; - uint8_t end_task; - uint8_t lineend[3]; -} machine_uart_obj_t; - -typedef struct _uart_ringbuf_t { - uint8_t *buf; - uint16_t size; - uint16_t iget; - uint16_t iput; -} uart_ringbuf_t; - -STATIC const char *_parity_name[] = {"None", "1", "0"}; +static const char *_parity_name[] = {"None", "None", "Even", "Odd"}; +static const char *_stopbits_name[] = {"?", "1", "1.5", "2"}; static QueueHandle_t UART_QUEUE[2] = {NULL}; static QueueHandle_t uart_mutex = NULL; -TaskHandle_t task_id[2] = {NULL}; +static TaskHandle_t task_id[2] = {NULL}; static uart_ringbuf_t uart_buffer[2]; static uart_ringbuf_t *uart_buf[2] = {NULL}; @@ -85,15 +54,16 @@ static uart_ringbuf_t *uart_buf[2] = {NULL}; //----------------------------------------------------------- static void uart_ringbuf_alloc(uint8_t uart_num, uint16_t sz) { - uart_buffer[uart_num].buf = m_new(uint8_t, sz); + uart_buffer[uart_num].buf = malloc(sz); uart_buffer[uart_num].size = sz; uart_buffer[uart_num].iget = 0; uart_buffer[uart_num].iput = 0; uart_buf[uart_num] = &uart_buffer[uart_num]; } -//----------------------------------------------------------------------- -static int uart_buf_get(uart_ringbuf_t *r, uint8_t *dest, uint16_t len) { +//-------------------------------------------------------------- +int uart_buf_get(uart_ringbuf_t *r, uint8_t *dest, uint16_t len) +{ if (r->iget == r->iput) return -1; // input buffer empty int res = 0; @@ -103,15 +73,16 @@ static int uart_buf_get(uart_ringbuf_t *r, uint8_t *dest, uint16_t len) { if (r->iget == r->iput) break; } // move the buffer and adjust the pointers - memmove(r->buf, r->buf+res, res); + memmove(r->buf, r->buf+res, r->iput - res); r->iget -= res; r->iput -= res; return res; } -//------------------------------------------------------------------------- -static int uart_buf_put(uart_ringbuf_t *r, uint8_t *source, uint16_t len) { +//---------------------------------------------------------------- +int uart_buf_put(uart_ringbuf_t *r, uint8_t *source, uint16_t len) +{ int res = 0; for (int i=0; iiput >= r->size) return 1; // overflow @@ -120,15 +91,16 @@ static int uart_buf_put(uart_ringbuf_t *r, uint8_t *source, uint16_t len) { return res; } -//--------------------------------------------------------------------------------------- -int pattern_match(uint8_t *text, int text_length, uint8_t *pattern, int pattern_length) { +//------------------------------------------------------------------------------------- +int match_pattern(uint8_t *text, int text_length, uint8_t *pattern, int pattern_length) +{ int c, d, e, position = -1; if (pattern_length > text_length) return -1; for (c = 0; c <= (text_length - pattern_length); c++) { position = e = c; - + // check pattern for (d = 0; d < pattern_length; d++) { if (pattern[d] == text[e]) e++; else break; @@ -147,10 +119,10 @@ static void _sched_callback(mp_obj_t function, int uart, int type, int iarglen, if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_INT, uart, NULL, NULL)) return; if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_INT, type, NULL, NULL)) return; if (sarg) { - if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_INT, iarglen, NULL, NULL)) return; + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, iarglen, sarg, NULL)) return; } else { - if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, iarglen, sarg, NULL)) return; + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_INT, iarglen, NULL, NULL)) return; } mp_sched_schedule(function, mp_const_none, carg); } @@ -197,7 +169,7 @@ static void uart_event_task(void *pvParameters) } else if (self->pattern_cb) { // ** callback on pattern received - res = pattern_match(uart_buf[self->uart_num]->buf, uart_buf[self->uart_num]->iput, self->pattern, self->pattern_len); + res = match_pattern(uart_buf[self->uart_num]->buf, uart_buf[self->uart_num]->iput, self->pattern, self->pattern_len); if (res >= 0) { // found, pull data, including pattern from buffer uart_buf_get(uart_buf[self->uart_num], dtmp, res+self->pattern_len); @@ -262,6 +234,143 @@ static void uart_event_task(void *pvParameters) vTaskDelete(NULL); } +//----------------------------------------------------------------------------- +char *_uart_read(uart_port_t uart_num, int timeout, char *lnend, char *lnstart) +{ + char *rdstr = NULL; + int rdlen = -1; + int minlen = strlen(lnend); + if (lnstart) minlen += strlen(lnstart); + + if (timeout == 0) { + if (uart_mutex) { + if (xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + return NULL; + } + } + // check for minimal length + if (uart_buf[uart_num]->iput < minlen) { + if (uart_mutex) xSemaphoreGive(uart_mutex); + return NULL; + } + while (1) { + rdlen = match_pattern(uart_buf[uart_num]->buf, uart_buf[uart_num]->iput, (uint8_t *)lnend, strlen(lnend)); + if (rdlen >= 0) { + // found, pull data, including pattern from buffer + rdlen += 2; + rdstr = calloc(rdlen+1, 1); + if (rdstr) { + uart_buf_get(uart_buf[uart_num], (uint8_t *)rdstr, rdlen); + rdstr[rdlen] = 0; + if (lnstart) { + // Match beginning string + char *start_ptr = strstr(rdstr, lnstart); + if (start_ptr) { + if (start_ptr != rdstr) { + char *new_rdstr = strdup(start_ptr); + free(rdstr); + rdstr = new_rdstr; + } + break; + } + else { + free(rdstr); + rdstr = NULL; + rdlen = -1; + break; + } + } + else break; + } + else { + rdlen = -1; + break; + } + } + else break; + } + if (uart_mutex) xSemaphoreGive(uart_mutex); + if (rdlen < 0) return NULL; + } + else { + // wait until lnend received or timeout + int wait = timeout; + int buflen = 0; + mp_hal_set_wdt_tmo(); + while (wait > 0) { + if (uart_mutex) { + if (xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + vTaskDelay(10 / portTICK_PERIOD_MS); + wait -= 10; + mp_hal_reset_wdt(); + continue; + } + } + if (buflen < uart_buf[uart_num]->iput) { + // ** new data received, reset timeout + buflen = uart_buf[uart_num]->iput; + wait = timeout; + } + if (uart_buf[uart_num]->iput < minlen) { + // ** too few characters received + if (uart_mutex) xSemaphoreGive(uart_mutex); + vTaskDelay(10 / portTICK_PERIOD_MS); + wait -= 10; + mp_hal_reset_wdt(); + continue; + } + + while (1) { + // * Check if lineend pattern is received + rdlen = match_pattern(uart_buf[uart_num]->buf, uart_buf[uart_num]->iput, (uint8_t *)lnend, strlen(lnend)); + if (rdlen >= 0) { + rdlen += 2; + // * found, pull data, including pattern from buffer + rdstr = calloc(rdlen+1, 1); + if (rdstr) { + uart_buf_get(uart_buf[uart_num], (uint8_t *)rdstr, rdlen); + rdstr[rdlen] = 0; + if (lnstart) { + // * Find beginning of the sentence + char *start_ptr = strstr(rdstr, lnstart); + if (start_ptr) { + // === received string ending with lnend and starting with lnstart + if (start_ptr != rdstr) { + char *new_rdstr = strdup(start_ptr); + free(rdstr); + rdstr = new_rdstr; + } + break; + } + else { + free(rdstr); + rdstr = NULL; + break; + } + } + else break; // === received string ending with lineend + } + else { + // error allocating buffer, finish + wait = 0; + break; + } + } + else break; + } + if (uart_mutex) xSemaphoreGive(uart_mutex); + + if (rdstr) break; + if (wait > 0) { + vTaskDelay(10 / portTICK_PERIOD_MS); + wait -= 10; + mp_hal_reset_wdt(); + } + } + } + return rdstr; +} + /******************************************************************************/ // MicroPython bindings for UART @@ -279,24 +388,77 @@ static const mp_arg_t allowed_args[] = { { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_buffer_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 512} }, { MP_QSTR_lineend, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_inverted, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = -1} }, }; -enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_timeout, ARG_buffer_size, ARG_lineend }; +enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_timeout, ARG_buffer_size, ARG_lineend, ARG_inverted }; //----------------------------------------------------------------------------------------------- STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (task_id[self->uart_num] == NULL) { + mp_printf(print, "UART(%u: Deinitialized )", self->uart_num+1); + return; + } + uint32_t baudrate; uart_get_baudrate(self->uart_num+1, &baudrate); + char lnend[16] = {'\0'}; + int lnend_idx = 0; + for (int i=0; i < strlen((char *)self->lineend); i++) { + if (self->lineend[i] == 0) break; + if ((self->lineend[i] < 32) || (self->lineend[i] > 126)) { + if (self->lineend[i] == '\r') { + sprintf(lnend+lnend_idx, "\\r"); + lnend_idx += 2; + } + else if (self->lineend[i] == '\n') { + sprintf(lnend+lnend_idx, "\\n"); + lnend_idx += 2; + } + else { + sprintf(lnend+lnend_idx, "\\x%2x", self->lineend[i]); + lnend_idx += 4; + } + } + else { + sprintf(lnend+lnend_idx, "%c", self->lineend[i]); + lnend_idx++; + } + } + char inverted[24] = {'\0'}; + if (self->inverted & (uint32_t)UART_INVERSE_RXD) { + if (inverted[0] != '\0') strcat(inverted, ", "); + strcat(inverted, "RX"); + } + if (self->inverted & (uint32_t)UART_INVERSE_TXD) { + if (inverted[0] != '\0') strcat(inverted, ", "); + strcat(inverted, "TX"); + } + if (self->inverted & (uint32_t)UART_INVERSE_CTS) { + if (inverted[0] != '\0') strcat(inverted, ", "); + strcat(inverted, "CTS"); + } + if (self->inverted & (uint32_t)UART_INVERSE_RTS) { + if (inverted[0] != '\0') strcat(inverted, ", "); + strcat(inverted, "RTS"); + } - mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, rts=%d, cts=%d, timeout=%u, buf_size=%u)", - self->uart_num+1, baudrate, self->bits, _parity_name[self->parity], - self->stop, self->tx, self->rx, self->rts, self->cts, self->timeout, self->buffer_size); + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%s, tx=%d, rx=%d, rts=%d, cts=%d, inverted: [%s]\n", + self->uart_num+1, baudrate, self->bits, _parity_name[self->parity], _stopbits_name[self->stop], + self->tx, self->rx, self->rts, self->cts, inverted); + mp_printf(print, " timeout=%u, buf_size=%u, lineend=b'%s')", self->timeout, self->buffer_size, lnend); if (self->data_cb) { mp_printf(print, "\n data CB: True, on len: %d", self->data_cb_size); } if (self->pattern_cb) { - mp_printf(print, "\n pattern CB: True, pattern: [%s]", self->pattern); + char pattern[80] = {'\0'}; + for (int i=0; ipattern_len; i++) { + if ((self->pattern[i] >= 0x20) && (self->pattern[i] < 0x7f)) pattern[strlen(pattern)] = self->pattern[i]; + else sprintf(pattern+strlen(pattern), "\\x%02x", self->pattern[i]); + } + mp_printf(print, "\n pattern CB: True, pattern: b'%s'", pattern); } if (self->error_cb) { mp_printf(print, "\n error CB: True"); @@ -314,18 +476,16 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co // wait for all data to be transmitted before changing settings uart_wait_tx_done(self->uart_num+1, pdMS_TO_TICKS(1000)); - // set baudrate + // set baudrate if needed uint32_t baudrate = 115200; if (args[ARG_baudrate].u_int > 0) { uart_set_baudrate(self->uart_num+1, args[ARG_baudrate].u_int); uart_get_baudrate(self->uart_num+1, &baudrate); } - // set data bits - if ((args[ARG_bits].u_int >= 0) && (args[ARG_bits].u_int != self->bits)) { + // set data bits if needed + if ((args[ARG_bits].u_int > 0) && (args[ARG_bits].u_int != self->bits)) { switch (args[ARG_bits].u_int) { - case 0: - break; case 5: uart_set_word_length(self->uart_num+1, UART_DATA_5_BITS); self->bits = 5; @@ -348,32 +508,31 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co } } - // set parity + // set parity if needed if (args[ARG_parity].u_obj != MP_OBJ_NULL) { if (args[ARG_parity].u_obj == mp_const_none) { if (self->parity != UART_PARITY_DISABLE) { uart_set_parity(self->uart_num+1, UART_PARITY_DISABLE); self->parity = UART_PARITY_DISABLE; - } + } } else { + // 0 -> odd; 1-> even parity mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj); - if ((parity & 1) && (self->parity != UART_PARITY_ODD)) { - uart_set_parity(self->uart_num+1, UART_PARITY_ODD); - self->parity = UART_PARITY_ODD; - } - else if (self->parity != UART_PARITY_EVEN){ + if ((parity & 1) && (self->parity != UART_PARITY_EVEN)) { uart_set_parity(self->uart_num+1, UART_PARITY_EVEN); self->parity = UART_PARITY_EVEN; } + else if (self->parity != UART_PARITY_ODD){ + uart_set_parity(self->uart_num+1, UART_PARITY_ODD); + self->parity = UART_PARITY_ODD; + } } } - // set stop bits - if ((args[ARG_stop].u_int >= 0) && (args[ARG_stop].u_int != self->stop)) { + // set stop bits if needed + if ((args[ARG_stop].u_int > 0) && (args[ARG_stop].u_int != self->stop)) { switch (args[ARG_stop].u_int) { - case 0: - break; case 1: uart_set_stop_bits(self->uart_num+1, UART_STOP_BITS_1); self->stop = UART_STOP_BITS_1; @@ -392,6 +551,12 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co } } + // set inverted pins + if ((args[ARG_inverted].u_int > -1) && (args[ARG_inverted].u_int != self->inverted)) { + self->inverted = args[ARG_inverted].u_int & (UART_INVERSE_RXD | UART_INVERSE_TXD | UART_INVERSE_RTS | UART_INVERSE_CTS); + uart_set_line_inverse(self->uart_num+1, self->inverted); + } + // set pins if (((self->tx == -2) && (args[ARG_tx].u_int == UART_PIN_NO_CHANGE)) || ((self->rx == -2) && (args[ARG_rx].u_int == UART_PIN_NO_CHANGE))) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Tx&Rx pins must be set: u=machine.UART(uart_num, tx=pin, rx=pin)")); @@ -407,18 +572,32 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co if (args[ARG_tx].u_int != UART_PIN_NO_CHANGE) self->tx = args[ARG_tx].u_int; if (args[ARG_rx].u_int != UART_PIN_NO_CHANGE) self->rx = args[ARG_rx].u_int; - if (args[ARG_rts].u_int != UART_PIN_NO_CHANGE) self->rts = args[ARG_rts].u_int; - if (args[ARG_cts].u_int != UART_PIN_NO_CHANGE) self->cts = args[ARG_cts].u_int; + if ((self->rts != args[ARG_rts].u_int) || (self->cts != args[ARG_cts].u_int)) { + if (args[ARG_rts].u_int != UART_PIN_NO_CHANGE) self->rts = args[ARG_rts].u_int; + if (args[ARG_cts].u_int != UART_PIN_NO_CHANGE) self->cts = args[ARG_cts].u_int; + // set flow control + int fwc = 0; + if (self->rts >= 0) fwc |= UART_HW_FLOWCTRL_RTS; + if (self->cts >= 0) fwc |= UART_HW_FLOWCTRL_CTS; + // Only when UART_HW_FLOWCTRL_RTS is set, will the rx_thresh value be set. + uart_set_hw_flow_ctrl(self->uart_num+1, fwc, UART_FIFO_LEN / 4 * 3); + } } // set timeout if (args[ARG_timeout].u_int >= 0) self->timeout = args[ARG_timeout].u_int; // set line end - if (MP_OBJ_IS_STR(args[ARG_lineend].u_obj)) { - size_t lnendlen; - const char *lnend = mp_obj_str_get_data(args[ARG_lineend].u_obj, &lnendlen); - if ((lnend) && (lnendlen > 0) && (lnendlen > 0)) sprintf((char *)self->lineend, "%s", lnend); + mp_buffer_info_t lnend_buff; + mp_obj_type_t *type = mp_obj_get_type(args[ARG_lineend].u_obj); + if (type->buffer_p.get_buffer != NULL) { + int ret = type->buffer_p.get_buffer(args[ARG_lineend].u_obj, &lnend_buff, MP_BUFFER_READ); + if (ret == 0) { + if ((lnend_buff.len > 0) && (lnend_buff.len < sizeof(self->lineend))) { + memset(self->lineend, 0, sizeof(self->lineend)); + memcpy(self->lineend, lnend_buff.buf, lnend_buff.len); + } + } } } @@ -438,14 +617,15 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) is disabled (dedicated to REPL)", uart_num)); } - // Defaults + // Set defaults parameters uart_config_t uartcfg = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, - .rx_flow_ctrl_thresh = 0 + .rx_flow_ctrl_thresh = 0, + .use_ref_tick = true }; if (uart_mutex == NULL) { @@ -456,11 +636,12 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, machine_uart_obj_t *self = m_new_obj(machine_uart_obj_t); self->base.type = &machine_uart_type; self->uart_num = uart_num-1; - self->bits = UART_DATA_8_BITS; - self->parity = UART_PARITY_DISABLE; + self->bits = 8; + self->parity = 0; self->stop = UART_STOP_BITS_1; self->rts = UART_PIN_NO_CHANGE; self->cts = UART_PIN_NO_CHANGE; + self->inverted = UART_INVERSE_DISABLE; self->timeout = 0; self->pattern[0] = 0; self->pattern_len = 0; @@ -493,12 +674,14 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, mp_arg_val_t kargs[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args-1, args+1, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, kargs); + // Set buffer size int bufsize = kargs[ARG_buffer_size].u_int; if (bufsize < 512) bufsize = 512; if (bufsize > 8192) bufsize = 8192; self->buffer_size = bufsize; if (uart_buf[self->uart_num] == NULL) { + // First time, create ring buffer uart_ringbuf_alloc(self->uart_num, bufsize); if (uart_buf[self->uart_num] == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) Error allocating ring buffer", uart_num)); @@ -508,12 +691,11 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, // Remove any existing configuration uart_driver_delete(uart_num); - // init the peripheral - // Setup + // Initialize the peripheral with default parameters uart_param_config(uart_num, &uartcfg); // RX ring buffer size is set to UART_BUFF_SIZE (256), TX buffer is disabled. - esp_err_t res = uart_driver_install(uart_num, UART_BUFF_SIZE, 0, 10, &UART_QUEUE[self->uart_num], 0); + esp_err_t res = uart_driver_install(uart_num, UART_BUFF_SIZE, 0, 20, &UART_QUEUE[self->uart_num], 0); if (res != ESP_OK) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) Error installing driver", uart_num)); } @@ -527,11 +709,23 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, uart_disable_pattern_det_intr(uart_num); //Create a task to handle UART event from ISR - if (task_id[self->uart_num] == NULL) xTaskCreate(uart_event_task, "uart_event_task", 1024, (void *)self, 12, &task_id[self->uart_num]); + #if CONFIG_MICROPY_USE_BOTH_CORES + if (task_id[self->uart_num] == NULL) xTaskCreate(uart_event_task, "uart_event_task", 1024, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &task_id[self->uart_num]); + #else + if (task_id[self->uart_num] == NULL) xTaskCreatePinnedToCore(uart_event_task, "uart_event_task", 1024, (void *)self, CONFIG_MICROPY_TASK_PRIORITY, &task_id[self->uart_num], MainTaskCore); + #endif return MP_OBJ_FROM_PTR(self); } +//----------------------------------------------- +static void _check_uart(machine_uart_obj_t *self) +{ + if (task_id[self->uart_num] == NULL) { + mp_raise_ValueError("UART not initialized"); + } +} + //----------------------------------------------------------------------------------------- STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); @@ -539,12 +733,44 @@ STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t } MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init); +//----------------------------------------------------- +STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (task_id[self->uart_num] != NULL) { + // stop the uart task + if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); + self->end_task = 1; + if (uart_mutex) xSemaphoreGive(uart_mutex); + // wait until ended + int tmo = 50; + while ((tmo) && (task_id[self->uart_num] != NULL)) { + vTaskDelay(100 / portTICK_PERIOD_MS); + tmo--; + } + if (tmo) { + mp_raise_ValueError("Cannot stop UART task!"); + } + // delete uart driver + uart_driver_delete(self->uart_num); + // free the uart buffer + if (uart_buf[self->uart_num] == NULL) { + if (uart_buf[self->uart_num]->buf) free(uart_buf[self->uart_num]->buf); + } + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit); + //-------------------------------------------------- STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); - int res = uart_buf[self->uart_num]->iput; + _check_uart(self); + + if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); + int res = uart_buf[self->uart_num]->iput; if (uart_mutex) xSemaphoreGive(uart_mutex); return MP_OBJ_NEW_SMALL_INT(res); @@ -555,81 +781,40 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any); STATIC mp_obj_t machine_uart_flush(mp_obj_t self_in) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); - uart_flush_input(self->uart_num+1); - uart_buf[self->uart_num]->iput = 0; - uart_buf[self->uart_num]->iget = 0; + _check_uart(self); + + if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); + uart_flush_input(self->uart_num+1); + uart_buf[self->uart_num]->iput = 0; + uart_buf[self->uart_num]->iget = 0; if (uart_mutex) xSemaphoreGive(uart_mutex); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_flush_obj, machine_uart_flush); -//------------------------------------------------------------------------ -STATIC mp_obj_t machine_uart_readln(size_t n_args, const mp_obj_t *args) { +//----------------------------------------------------------------- +mp_obj_t machine_uart_readln(size_t n_args, const mp_obj_t *args) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(args[0]); - vstr_t vstr; - int res = -1; - int lnendlen = strlen((char *)self->lineend); - int timeout = self->timeout; - if (n_args == 2) timeout = mp_obj_get_int(args[1]); + _check_uart(self); - if (timeout == 0) { - if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); - // just return the buffer content if line end was found - if (uart_buf[self->uart_num]->iput < lnendlen) { - if (uart_mutex) xSemaphoreGive(uart_mutex); - return mp_const_none; - } - res = pattern_match(uart_buf[self->uart_num]->buf, uart_buf[self->uart_num]->iput, self->lineend, lnendlen); - if (res >= 0) { - // found, pull data, including pattern from buffer - vstr_init_len(&vstr, res+lnendlen); - uart_buf_get(uart_buf[self->uart_num], (uint8_t *)vstr.buf, res+lnendlen); - } - if (uart_mutex) xSemaphoreGive(uart_mutex); - if (res < 0) return mp_const_none; - } - else { - // wait until line end received or timeout - int wait = timeout; - int buflen = 0; - mp_hal_set_wdt_tmo(); - MP_THREAD_GIL_EXIT(); - while (wait > 0) { - if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); - if (buflen < uart_buf[self->uart_num]->iput) { - buflen = uart_buf[self->uart_num]->iput; - wait = timeout; // new data received, reset timeout - } - if (uart_buf[self->uart_num]->iput < lnendlen) { - if (uart_mutex) xSemaphoreGive(uart_mutex); - vTaskDelay(10 / portTICK_PERIOD_MS); - wait -= 10; - mp_hal_reset_wdt(); - continue; - } - res = pattern_match(uart_buf[self->uart_num]->buf, uart_buf[self->uart_num]->iput, self->lineend, lnendlen); - if (res >= 0) { - // found, pull data, including pattern from buffer - vstr_init_len(&vstr, res+lnendlen); - uart_buf_get(uart_buf[self->uart_num], (uint8_t *)vstr.buf, res+lnendlen); - if (uart_mutex) xSemaphoreGive(uart_mutex); - break; - } - if (uart_mutex) xSemaphoreGive(uart_mutex); - vTaskDelay(10 / portTICK_PERIOD_MS); - wait -= 10; - mp_hal_reset_wdt(); - } - MP_THREAD_GIL_ENTER(); - if (res < 0) return mp_const_none; - } + int timeout = self->timeout; + if (n_args > 1) timeout = mp_obj_get_int(args[1]); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + const char *startstr = NULL; + if (n_args > 2) startstr = mp_obj_str_get_str(args[2]); + + MP_THREAD_GIL_EXIT(); + char *rdstr = _uart_read(self->uart_num, timeout, (char *)self->lineend, (char *)startstr); + MP_THREAD_GIL_ENTER(); + + if (rdstr == NULL) return mp_const_none; + mp_obj_t res_str = mp_obj_new_str((const char *)rdstr, strlen(rdstr)); + if (rdstr != NULL) free(rdstr); + return res_str; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_uart_readln_obj, 1, 2, machine_uart_readln); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_uart_readln_obj, 1, 3, machine_uart_readln); //----------------------------------------------------------------------------------------------- @@ -647,8 +832,14 @@ STATIC mp_obj_t machine_uart_callback(size_t n_args, const mp_obj_t *pos_args, m mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + _check_uart(self); + + int datalen = -1; + mp_buffer_info_t pattern_buff; int cbtype = args[ARG_type].u_int; + if ((!MP_OBJ_IS_FUN(args[ARG_func].u_obj)) && (!MP_OBJ_IS_METH(args[ARG_func].u_obj))) { + // CB function not given, disable callback if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); switch(cbtype) { case UART_CB_TYPE_DATA: @@ -670,29 +861,43 @@ STATIC mp_obj_t machine_uart_callback(size_t n_args, const mp_obj_t *pos_args, m return mp_const_none; } + // Get callback parameters + switch(cbtype) { + case UART_CB_TYPE_DATA: + if ((args[ARG_datalen].u_int <= 0) || (args[ARG_datalen].u_int >= self->buffer_size)) { + mp_raise_ValueError("invalid data length"); + } + datalen = args[ARG_datalen].u_int; + break; + case UART_CB_TYPE_PATTERN: + { + bool has_pattern = false; + mp_obj_type_t *type = mp_obj_get_type(args[ARG_pattern].u_obj); + if (type->buffer_p.get_buffer != NULL) { + int ret = type->buffer_p.get_buffer(args[ARG_pattern].u_obj, &pattern_buff, MP_BUFFER_READ); + if (ret == 0) { + if ((pattern_buff.len > 0) && (pattern_buff.len <= sizeof(self->pattern))) has_pattern = true; + } + } + if (!has_pattern) { + mp_raise_ValueError("invalid pattern"); + } + } + break; + default: + break; + } - int datalen = -1; - size_t patternlen = 0; - const char * pattern = NULL; - - if (MP_OBJ_IS_STR(args[ARG_pattern].u_obj)) { - pattern = mp_obj_str_get_data(args[ARG_pattern].u_obj, &patternlen); - if (patternlen > sizeof(self->pattern)) patternlen = sizeof(self->pattern); - } - - if ((args[ARG_datalen].u_int >= 0) && (args[ARG_datalen].u_int < self->buffer_size)) datalen = args[ARG_datalen].u_int; - + // Set the callback if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); switch(cbtype) { case UART_CB_TYPE_DATA: - if (datalen >= 0) self->data_cb_size = datalen; + self->data_cb_size = datalen; self->data_cb = args[ARG_func].u_obj; break; case UART_CB_TYPE_PATTERN: - if (pattern) { - memcpy(self->pattern, pattern, patternlen); - self->pattern_len = patternlen; - } + memcpy(self->pattern, pattern_buff.buf, pattern_buff.len); + self->pattern_len = pattern_buff.len; self->pattern_cb = args[ARG_func].u_obj; break; case UART_CB_TYPE_ERROR: @@ -707,16 +912,47 @@ STATIC mp_obj_t machine_uart_callback(size_t n_args, const mp_obj_t *pos_args, m } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_callback_obj, 2, machine_uart_callback); +//--------------------------------------------------------------------------- +STATIC mp_obj_t machine_uart_write_break(size_t n_args, const mp_obj_t *args) +{ + machine_uart_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + _check_uart(self); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + + // break signal length + // unit: one BIT time at current_baudrate + int nbreak = nbreak = mp_obj_get_int_truncated(args[2]); + if ((nbreak < 1) || (nbreak > 255)) { + mp_raise_ValueError("values 1 - 255 are allowed"); + } + + int len = bufinfo.len; + if (n_args == 4) { + len = mp_obj_get_int_truncated(args[3]); + if ((len < 0) || (len > bufinfo.len)) len = bufinfo.len;; + } + + int bytes_written = uart_write_bytes_with_break(self->uart_num+1, (const char*)bufinfo.buf, len, nbreak); + + return MP_OBJ_NEW_SMALL_INT(bytes_written); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_uart_write_break_obj, 3, 4, machine_uart_write_break); + //================================================================= STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_break), MP_ROM_PTR(&machine_uart_write_break_obj) }, { MP_ROM_QSTR(MP_QSTR_readln), MP_ROM_PTR(&machine_uart_readln_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&machine_uart_flush_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&machine_uart_callback_obj) }, @@ -725,22 +961,38 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_CBTYPE_DATA), MP_ROM_INT(UART_CB_TYPE_DATA) }, { MP_ROM_QSTR(MP_QSTR_CBTYPE_PATTERN), MP_ROM_INT(UART_CB_TYPE_PATTERN) }, { MP_ROM_QSTR(MP_QSTR_CBTYPE_ERROR), MP_ROM_INT(UART_CB_TYPE_ERROR) }, + + { MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERSE_RXD >> 1) }, + { MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERSE_TXD >> 1) }, + { MP_ROM_QSTR(MP_QSTR_INV_CTS), MP_ROM_INT(UART_INVERSE_CTS >> 1) }, + { MP_ROM_QSTR(MP_QSTR_INV_RTS), MP_ROM_INT(UART_INVERSE_RTS >> 1) }, + { MP_ROM_QSTR(MP_QSTR_INV_NONE), MP_ROM_INT(0) }, }; STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table); + +// === Stream UART functions === + //------------------------------------------------------------------------------------------------ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - // make sure we want at least 1 char - if (size == 0) { - return 0; + if (task_id[self->uart_num] == NULL) { + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; } + // make sure we want at least 1 char + if (size == 0) return 0; + int bytes_read = 0; if (self->timeout == 0) { // just return the buffer content - if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); + if (uart_mutex) { + if (xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + return 0; + } + } bytes_read = uart_buf_get(uart_buf[self->uart_num], (uint8_t *)buf_in, size); if (uart_mutex) xSemaphoreGive(uart_mutex); if (bytes_read < 0) bytes_read = 0; @@ -751,7 +1003,14 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz int wait = self->timeout; MP_THREAD_GIL_EXIT(); while (wait > 0) { - if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); + if (uart_mutex) { + if (xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS) != pdTRUE) { + vTaskDelay(2 / portTICK_PERIOD_MS); + wait -= 2; + mp_hal_reset_wdt(); + continue; + } + } if (uart_buf[self->uart_num]->iput < size) { if (uart_mutex) xSemaphoreGive(uart_mutex); vTaskDelay(2 / portTICK_PERIOD_MS); @@ -778,6 +1037,11 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (task_id[self->uart_num] == NULL) { + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } + int bytes_written = uart_write_bytes(self->uart_num+1, buf_in, size); if (bytes_written < 0) { @@ -792,6 +1056,12 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin //----------------------------------------------------------------------------------------------------- STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { machine_uart_obj_t *self = self_in; + + if (task_id[self->uart_num] == NULL) { + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } + mp_uint_t ret; if (request == MP_STREAM_POLL) { mp_uint_t flags = arg; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_uart.h b/MicroPython_BUILD/components/micropython/esp32/machine_uart.h new file mode 100644 index 00000000..504b8123 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/machine_uart.h @@ -0,0 +1,48 @@ +#ifndef INC_MACHINE_UART_H +#define INC_MACHINE_UART_H + +#include "driver/uart.h" +#include "py/runtime.h" + +#define UART_CB_TYPE_DATA 1 +#define UART_CB_TYPE_PATTERN 2 +#define UART_CB_TYPE_ERROR 3 +#define UART_BUFF_SIZE 256 + +typedef struct _machine_uart_obj_t { + mp_obj_base_t base; + uart_port_t uart_num; + int8_t bits; + int8_t parity; + int8_t stop; + int8_t tx; + int8_t rx; + int8_t rts; + int8_t cts; + int data_cb_size; + uint8_t pattern[16]; + uint8_t pattern_len; + uint16_t timeout; // timeout waiting for first char (in ms) + uint16_t buffer_size; + uint32_t *data_cb; + uint32_t *pattern_cb; + uint32_t *error_cb; + uint32_t inverted; + uint8_t end_task; + uint8_t lineend[3]; +} machine_uart_obj_t; + +typedef struct _uart_ringbuf_t { + uint8_t *buf; + uint16_t size; + uint16_t iget; + uint16_t iput; +} uart_ringbuf_t; + + +char *_uart_read(uart_port_t uart_num, int timeout, char *lnend, char *lnstart); +int match_pattern(uint8_t *text, int text_length, uint8_t *pattern, int pattern_length); +int uart_buf_get(uart_ringbuf_t *r, uint8_t *dest, uint16_t len); +int uart_buf_put(uart_ringbuf_t *r, uint8_t *source, uint16_t len); + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/main.c b/MicroPython_BUILD/components/micropython/esp32/main.c index 6ef4c5bd..2e86f5e3 100644 --- a/MicroPython_BUILD/components/micropython/esp32/main.c +++ b/MicroPython_BUILD/components/micropython/esp32/main.c @@ -26,6 +26,7 @@ #include #include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -38,6 +39,7 @@ #include "esp_log.h" #include "driver/periph_ctrl.h" #include "esp_ota_ops.h" +#include "esp_pm.h" #include "py/stackctrl.h" #include "py/nlr.h" @@ -58,73 +60,79 @@ #ifdef CONFIG_MICROPY_USE_FTPSERVER #include "libs/ftp.h" #endif -#ifdef CONFIG_MICROPY_USE_MQTT -#include "mqtt.h" -#endif +#include "driver/uart.h" +#include "rom/uart.h" #include "sdkconfig.h" -// ========================================= -// MicroPython runs as a task under FreeRTOS -// ========================================= +// ================================================ +// MicroPython runs as a STATIC task under FreeRTOS +// ================================================ #define NVS_NAMESPACE "MPY_NVM" -#define MP_TASK_PRIORITY CONFIG_MICROPY_TASK_PRIORITY -#define MP_TASK_STACK_SIZE (CONFIG_MICROPY_STACK_SIZE * 1024) -#define MP_TASK_HEAP_SIZE (CONFIG_MICROPY_HEAP_SIZE * 1024) -#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) +#define MP_TASK_STACK_LEN 4096 -STATIC TaskHandle_t MainTaskHandle = NULL; +#if CONFIG_SPIRAM_IGNORE_NOTFOUND +extern bool s_spiram_okay; +#endif -STATIC StaticTask_t DRAM_ATTR mp_task_tcb; -STATIC StackType_t DRAM_ATTR mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); +static StaticTask_t DRAM_ATTR mp_task_tcb; +static StackType_t *mp_task_stack; +static StackType_t *mp_task_stack_end; +static int mp_task_stack_len = 4096; +static uint8_t *mp_task_heap = NULL; -STATIC uint8_t *mp_task_heap; +//STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); int MainTaskCore = 0; -//=============================== -void mp_task(void *pvParameter) { +//============================= +void mp_task(void *pvParameter) +{ volatile uint32_t sp = (uint32_t)get_sp(); + //mp_task_stack_len -= ((uint32_t)mp_task_stack_end - sp); #ifdef CONFIG_MICROPY_USE_TASK_WDT - // Enable watchdog for MicroPython main task + // Enable watchdog for MicroPython main task + #ifdef CONFIG_MICROPY_TASK_WDT_PANIC + esp_task_wdt_init(CONFIG_TASK_WDT_TIMEOUT_S, true); + #else esp_task_wdt_init(CONFIG_TASK_WDT_TIMEOUT_S, false); - esp_task_wdt_add(MainTaskHandle); - esp_task_wdt_reset(); + #endif + esp_task_wdt_add(MainTaskHandle); + esp_task_wdt_reset(); #endif uart_init(); - // Check and open NVS name space - if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &mpy_nvs_handle) != ESP_OK) { - mpy_nvs_handle = 0; - printf("Error while opening MicroPython NVS name space\n"); - } + #if (CONFIG_BOOT_SET_LED >= 0) && defined(CONFIG_BOOT_RESET_LED) + // Deactivate boot led + gpio_pad_select_gpio(CONFIG_BOOT_SET_LED); + GPIO_OUTPUT_SET(CONFIG_BOOT_SET_LED, CONFIG_BOOT_LED_ON ^ 1); + #endif - // Get and print reset & wakeup reasons + // Get and print reset & wakeup reasons mpsleep_init0(); - if (mpsleep_get_reset_cause() != MPSLEEP_DEEPSLEEP_RESET) rtc_init0(); - - mp_thread_preinit(&mp_task_stack[0], MP_TASK_STACK_LEN); + rtc_init0(); -soft_reset: - // Thread init - mp_thread_init(); + // === Main MicroPython thread init === + mp_thread_preinit(mp_task_stack, mp_task_stack_len); // Initialize the stack pointer for the main thread mp_stack_set_top((void *)sp); - mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024); + mp_stack_set_limit(mp_task_stack_len - 1024); - // initialize the mp heap - gc_init(mp_task_heap, mp_task_heap + MP_TASK_HEAP_SIZE); + // Initialize the MicroPython heap + gc_init(mp_task_heap, mp_task_heap + mpy_heap_size); + // Initialize MicroPython environment mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_m5flow)); mp_obj_list_init(mp_sys_argv, 0); readline_init0(); @@ -132,8 +140,11 @@ void mp_task(void *pvParameter) { // Initialize peripherals machine_pins_init(); + ESP_LOGI("MicroPython", "[=== MicroPython FreeRTOS task started (sp=%08x) ===]\n", sp); + // === Mount internal flash file system === int res = mount_vfs(VFS_NATIVE_TYPE_SPIFLASH, VFS_NATIVE_INTERNAL_MP); + if (res == 0) { // run boot-up script 'boot.py' pyexec_file("boot.py"); @@ -147,142 +158,332 @@ void mp_task(void *pvParameter) { } } } - else printf("Error mounting Flash file system\n"); + else ESP_LOGE("MicroPython", "Error mounting Flash file system"); - // === Print some info === - char sbuff[24] = { 0 }; gc_info_t info; gc_info(&info); - // set gc.threshold to 80% of usable heap - MP_STATE_MEM(gc_alloc_threshold) = ((info.total / 10) * 8) / MICROPY_BYTES_PER_GC_BLOCK; - - #if CONFIG_FREERTOS_UNICORE - printf("\nFreeRTOS running only on FIRST CORE.\n"); - #else - #if CONFIG_SPIRAM_SUPPORT - printf("\nFreeRTOS running on BOTH CORES, MicroPython task running on both cores.\n"); - #else - printf("\nFreeRTOS running on BOTH CORES, MicroPython task started on App Core.\n"); - #endif + #ifdef CONFIG_MICROPY_GC_SET_THRESHOLD + MP_STATE_MEM(gc_alloc_threshold) = ((info.total * 100) / CONFIG_MICROPY_GC_THRESHOLD_VALUE) / MICROPY_BYTES_PER_GC_BLOCK; #endif - // Print partition info - const esp_partition_t *running_partition = esp_ota_get_running_partition(); - if (running_partition != NULL) { - if (running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) sprintf(sbuff, "Factory "); - else if (running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) sprintf(sbuff, "OTA_0 "); - else if (running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_1) sprintf(sbuff, "OTA_1 "); - else sbuff[0] = '\0'; - printf("Running from %s%spartition starting at 0x%X, [%s].\n", - ((running_partition->encrypted) ? "encrypted " : ""), sbuff, running_partition->address, running_partition->label); - } - - mpsleep_get_reset_desc(sbuff); - if (mpsleep_get_wake_reason() != MPSLEEP_NONE_WAKE) printf(" "); - printf("\n Reset reason: %s\n", sbuff); - if (mpsleep_get_wake_reason() != MPSLEEP_NONE_WAKE) { - mpsleep_get_wake_desc(sbuff); - printf("Wakeup source: %s\n", sbuff); - } - - printf(" uPY stack: %d bytes\n", MP_TASK_STACK_LEN-1024); - - #if CONFIG_SPIRAM_SUPPORT - // ## USING SPI RAM FOR HEAP ## - #if CONFIG_SPIRAM_USE_CAPS_ALLOC - printf(" uPY heap: %u/%u/%u bytes (in SPIRAM using heap_caps_malloc)\n\n", info.total, info.used, info.free); - #elif SPIRAM_USE_MEMMAP - printf(" uPY heap: %u/%u/%u bytes (in SPIRAM using MEMMAP)\n\n", info.total, info.used, info.free); - #else - printf(" uPY heap: %u/%u/%u bytes (in SPIRAM using malloc)\n\n", info.total, info.used, info.free); - #endif - #else - // ## USING DRAM FOR HEAP ## - printf(" uPY heap: %u/%u/%u bytes\n\n", info.total, info.used, info.free); - #endif + // === Print some info === + if ((CONFIG_LOG_DEFAULT_LEVEL >= ESP_LOG_INFO) && (CONFIG_MICRO_PY_LOG_LEVEL > ESP_LOG_INFO)) { + char sbuff[24] = { 0 }; + + #if CONFIG_FREERTOS_UNICORE + printf("\nFreeRTOS and MicroPython running only on FIRST CORE.\n"); + #else + #if CONFIG_MICROPY_USE_BOTH_CORES + printf("\nFreeRTOS running on BOTH CORES, MicroPython task running on both cores.\n"); + #else + printf("\nFreeRTOS running on BOTH CORES, MicroPython task started on App Core (1).\n"); + #endif + #endif + + #ifdef CONFIG_MICROPY_USE_OTA + // Print partition info + const esp_partition_t *running_partition = esp_ota_get_running_partition(); + if (running_partition != NULL) { + if (running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_FACTORY) sprintf(sbuff, "Factory "); + else if (running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) sprintf(sbuff, "OTA_0 "); + else if (running_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_1) sprintf(sbuff, "OTA_1 "); + else sbuff[0] = '\0'; + printf("Running from %s%spartition starting at 0x%X, [%s].\n", + ((running_partition->encrypted) ? "encrypted " : ""), sbuff, running_partition->address, running_partition->label); + } + #endif + + mpsleep_get_reset_desc(sbuff); + if (mpsleep_get_wake_reason() != MPSLEEP_NONE_WAKE) printf(" "); + printf("\n Reset reason: %s\n", sbuff); + if (mpsleep_get_wake_reason() != MPSLEEP_NONE_WAKE) { + mpsleep_get_wake_desc(sbuff); + printf("Wakeup source: %s\n", sbuff); + } - // === Main loop ================================== - for (;;) { - if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { - if (pyexec_raw_repl() != 0) { - break; - } + printf(" uPY stack: %d bytes\n", mp_task_stack_len - 1024); + + if (mpy_use_spiram) { + // ## USING SPI RAM FOR HEAP ## + #if CONFIG_SPIRAM_USE_CAPS_ALLOC + printf(" uPY heap: %u/%u/%u bytes (in SPIRAM using heap_caps_malloc)\n\n", info.total, info.used, info.free); + #elif CONFIG_SPIRAM_USE_MEMMAP + printf(" uPY heap: %u/%u/%u bytes (in SPIRAM using MEMMAP)\n\n", info.total, info.used, info.free); + #else + printf(" uPY heap: %u/%u/%u bytes (in SPIRAM using malloc)\n\n", info.total, info.used, info.free); + #endif } else { - if (pyexec_friendly_repl() != 0) { - break; - } + // ## USING DRAM FOR HEAP ## + printf(" uPY heap: %u/%u/%u bytes\n\n", info.total, info.used, info.free); } } + + // === Main loop ================================== + MP_THREAD_GIL_EXIT(); + + // === Start REPL in main task ==================== + ReplTaskHandle = MainTaskHandle; + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } + else { + if (pyexec_friendly_repl() != 0) { + break; + } + } + } // ================================================ + //ToDo: Remember the REPL mode (is it needed ?) !! prepareSleepReset(0, "ESP32: soft reboot\r\n"); - - goto soft_reset; + esp_restart(); // no return !! } //============================ -void micropython_entry(void) { - nvs_flash_init(); - - // === Set esp32 log levels while running MicroPython === - esp_log_level_set("*", CONFIG_MICRO_PY_LOG_LEVEL); - esp_log_level_set("wifi", 1); - esp_log_level_set("rmt", 1); - #ifdef CONFIG_MICROPY_USE_OTA - esp_log_level_set("OTA_UPDATE", 4); +void micropython_entry(void) +{ + ESP_LOGD("MicroPython","Entry"); + vTaskDelay(1000); + // Configure UART for power management usage + uart_config_t uartcfg = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 0, + .use_ref_tick = true + }; + uart_param_config(UART_NUM_0, &uartcfg); + uart_set_baudrate(UART_NUM_0, CONFIG_CONSOLE_UART_BAUDRATE); + + // === Check SPIRAM support ================= + MPY_DEFAULT_STACK_SIZE = CONFIG_MICROPY_STACK_SIZE * 1024; + MPY_DEFAULT_HEAP_SIZE = CONFIG_MICROPY_HEAP_SIZE * 1024; + #if CONFIG_SPIRAM_SUPPORT + #if CONFIG_SPIRAM_IGNORE_NOTFOUND + if (s_spiram_okay) mpy_use_spiram = true; + else { + mpy_use_spiram = false; + MPY_DEFAULT_STACK_SIZE = 16 * 1024; + MPY_DEFAULT_HEAP_SIZE = 72 * 1024; + ESP_LOGW("MicroPython","SPIRAM support enabled but SPIRAM not detected"); + } + #else + mpy_use_spiram = true; + #endif + #else + mpy_use_spiram = false; #endif + ESP_LOGD("MicroPython","SPIRAM: %s", mpy_use_spiram ? "Enabled" : "Disabled"); + // ========================================== + + // Initialize some global variables depending on SPIRAM support + if (mpy_use_spiram) { + MPY_MAX_STACK_SIZE = 64*1024; + MPY_MIN_HEAP_SIZE = 128*1024; + MPY_MAX_HEAP_SIZE = 3584*1024; + hdr_maxlen = 1024; + body_maxlen = 4096; + ssh2_hdr_maxlen = 1024; + ssh2_body_maxlen = 4096; + } + else { + MPY_MAX_STACK_SIZE = 32*1024; + MPY_MIN_HEAP_SIZE = 48*1024; + #if defined(CONFIG_MICROPY_USE_CURL) && defined(CONFIG_MICROPY_USE_CURL_TLS) + MPY_MAX_HEAP_SIZE = 74*1024; + MPY_DEFAULT_HEAP_SIZE = 72 * 1024; + #else + MPY_MAX_HEAP_SIZE = 96*1024; + #endif + hdr_maxlen = 512; + body_maxlen = 1024; + ssh2_hdr_maxlen = 512; + ssh2_body_maxlen = 1024; + } - #ifdef CONFIG_MICROPY_USE_MQTT - esp_log_level_set(MQTT_TAG, CONFIG_MQTT_LOG_LEVEL); - #endif - #ifdef CONFIG_MICROPY_USE_FTPSERVER - esp_log_level_set(FTP_TAG, CONFIG_FTPSERVER_LOG_LEVEL); + /* + // ---- esp-idf PM bug! ---------------------------------------------------------------------------------------- + #if defined(CONFIG_PM_ENABLE) && !defined(CONFIG_PM_DFS_INIT_AUTO) && defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_240) + esp_pm_config_esp32_t pm_config; + pm_config.max_cpu_freq = RTC_CPU_FREQ_160M; + pm_config.min_cpu_freq = RTC_CPU_FREQ_XTAL; + pm_config.light_sleep_enable = false; + esp_pm_configure(&pm_config); + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M); + uart_set_baudrate(UART_NUM_0, CONFIG_CONSOLE_UART_BAUDRATE); + pm_config.max_cpu_freq = RTC_CPU_FREQ_240M; + esp_pm_configure(&pm_config); + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); + uart_set_baudrate(UART_NUM_0, CONFIG_CONSOLE_UART_BAUDRATE); #endif + // ------------------------------------------------------------------------------------------------------------- + */ + + nvs_flash_init(); + + // ================================ + // === Check and allocate stack === + ESP_LOGD("MicroPython","Configure stack"); + mp_task_stack_len = MPY_DEFAULT_STACK_SIZE; - // ==== Allocate heap memory ==== - #if CONFIG_SPIRAM_SUPPORT + // Open NVS name space + if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &mpy_nvs_handle) != ESP_OK) { + mpy_nvs_handle = 0; + ESP_LOGE("MicroPython","Error while opening MicroPython NVS name space"); + } + if (mpy_nvs_handle != 0) { + // Get stack size from NVS + if (ESP_ERR_NVS_NOT_FOUND != nvs_get_i32(mpy_nvs_handle, "MPY_StackSize", &mp_task_stack_len)) { + if ((mp_task_stack_len < MPY_MIN_STACK_SIZE) || (mp_task_stack_len > MPY_MAX_STACK_SIZE)) { + mp_task_stack_len = MPY_DEFAULT_STACK_SIZE; + ESP_LOGW("MicroPython","Wrong Stack size set in NVS: %d (set to configured: %d)", mp_task_stack_len, MPY_DEFAULT_STACK_SIZE); + } + else { + ESP_LOGI("MicroPython","Stack size set from NVS: %d (configured: %d)", mp_task_stack_len, MPY_DEFAULT_STACK_SIZE); + } + } + // restore time zone + tz_fromto_NVS(mpy_time_zone, NULL); + if (strlen(mpy_time_zone) > 0) { + setenv("TZ", mpy_time_zone, 1); + tzset(); + } + } + mp_task_stack_len &= 0x7FFFFFF8; + mp_task_stack_len = mp_task_stack_len / sizeof(StackType_t); + + if (mpy_use_spiram) mp_task_stack = heap_caps_malloc((mp_task_stack_len * sizeof(StackType_t))+8, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + else mp_task_stack = malloc((mp_task_stack_len * sizeof(StackType_t))+8); + if (mp_task_stack == NULL) { + ESP_LOGE("MicroPython", "Error allocating stack, HALTED."); + return; + } + mp_task_stack_end = mp_task_stack + ((mp_task_stack_len * sizeof(StackType_t)) + 8); + ESP_LOGD("MicroPython", "MPy stack: %p - %p (%d)", mp_task_stack, mp_task_stack_end, mp_task_stack_len+8); + + // ========================================== + // ==== Allocate MicroPython HEAP memory ==== + ESP_LOGD("MicroPython","Configure heap"); + mpy_heap_size = MPY_DEFAULT_HEAP_SIZE; + if (mpy_nvs_handle != 0) { + // Get heap size from NVS + if (ESP_ERR_NVS_NOT_FOUND != nvs_get_i32(mpy_nvs_handle, "MPY_HeapSize", &mpy_heap_size)) { + if ((mpy_heap_size < MPY_MIN_HEAP_SIZE) || (mpy_heap_size > MPY_MAX_HEAP_SIZE)) { + mpy_heap_size = MPY_DEFAULT_HEAP_SIZE; + ESP_LOGW("MicroPython", "Wrong Heap size set in NVS: %d (set to configured: %d)", mpy_heap_size, MPY_DEFAULT_HEAP_SIZE); + } + else { + ESP_LOGI("MicroPython", "Heap size set from NVS: %d (configured: %d)", mpy_heap_size, MPY_DEFAULT_HEAP_SIZE); + } + } + } + mpy_heap_size &= 0x7FFFFFF0; + + if (mpy_use_spiram) { // ## USING SPI RAM FOR HEAP ## #if CONFIG_SPIRAM_USE_CAPS_ALLOC - mp_task_heap = heap_caps_malloc(MP_TASK_HEAP_SIZE, MALLOC_CAP_SPIRAM); - #elif SPIRAM_USE_MEMMAP + mp_task_heap = heap_caps_malloc(mpy_heap_size+16, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + #elif CONFIG_SPIRAM_USE_MEMMAP mp_task_heap = (uint8_t *)0x3f800000; + #elif CONFIG_SPIRAM_USE_MALLOC + mp_task_heap = malloc(mpy_heap_size+16); + //mp_task_heap = heap_caps_malloc(mpy_heap_size+16, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); #else - mp_task_heap = malloc(MP_TASK_HEAP_SIZE); + ESP_LOGE("MicroPython", "Unknown SPIRAM configuration, HALTED."); + return; #endif - #else + } + else { // ## USING DRAM FOR HEAP ## - mp_task_heap = malloc(MP_TASK_HEAP_SIZE); - #endif + mp_task_heap = malloc(mpy_heap_size+16); + //mp_task_heap = heap_caps_malloc(mpy_heap_size+16, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + } if (mp_task_heap == NULL) { - printf("Error allocating heap, Halted.\n"); + ESP_LOGE("MicroPython", "Error allocating heap, HALTED."); return; } + ESP_LOGD("MicroPython", "MPy heap: %p - %p (%d)", mp_task_heap, mp_task_heap+mpy_heap_size+64, mpy_heap_size); // Workaround for possible bug in i2c driver !? + //ToDo: Is it still needed? periph_module_disable(PERIPH_I2C0_MODULE); periph_module_enable(PERIPH_I2C0_MODULE); - // ==== Create and start main MicroPython task ==== + // === Set esp32 log levels while running MicroPython === + if (CONFIG_MICRO_PY_LOG_LEVEL < CONFIG_LOG_DEFAULT_LEVEL) esp_log_level_set("*", CONFIG_MICRO_PY_LOG_LEVEL); + if ((CONFIG_LOG_DEFAULT_LEVEL > ESP_LOG_WARN) && (CONFIG_MICRO_PY_LOG_LEVEL > ESP_LOG_WARN)){ + esp_log_level_set("wifi", ESP_LOG_WARN); + esp_log_level_set("rmt", ESP_LOG_WARN); + esp_log_level_set("tcpip_adapter", ESP_LOG_WARN); + esp_log_level_set("event", ESP_LOG_WARN); + esp_log_level_set("nvs", ESP_LOG_WARN); + esp_log_level_set("phy_init", ESP_LOG_WARN); + esp_log_level_set("wl_flash", ESP_LOG_WARN); + esp_log_level_set("RTC_MODULE", ESP_LOG_WARN); + #ifdef CONFIG_MICROPY_USE_ETHERNET + esp_log_level_set("phy_common", ESP_LOG_WARN); + #endif + #ifdef CONFIG_MICROPY_USE_RFCOMM + esp_log_level_set("BTDM_INIT", ESP_LOG_WARN); + #endif + #ifdef CONFIG_MICROPY_USE_REQUESTS + //esp_log_level_set("HTTP_CLIENT", ESP_LOG_WARN); + //esp_log_level_set("TRANS_TCP", ESP_LOG_WARN); + //esp_log_level_set("TRANS_SSL", ESP_LOG_WARN); + #endif + } + #ifdef CONFIG_MICROPY_USE_OTA + if (CONFIG_LOG_DEFAULT_LEVEL >= ESP_LOG_DEBUG) esp_log_level_set("OTA_UPDATE", ESP_LOG_DEBUG); + else esp_log_level_set("OTA_UPDATE", CONFIG_LOG_DEFAULT_LEVEL); + #endif + + #ifdef CONFIG_MICROPY_USE_MQTT + esp_log_level_set("MQTT_CLIENT", CONFIG_MQTT_LOG_LEVEL); + #endif + #ifdef CONFIG_MICROPY_USE_FTPSERVER + esp_log_level_set(FTP_TAG, CONFIG_FTPSERVER_LOG_LEVEL); + #endif + esp_log_level_set("MicroPython", CONFIG_LOG_DEFAULT_LEVEL); + + // ================================================ + // ==== Create and start main MicroPython task ==== + // ================================================ #if CONFIG_FREERTOS_UNICORE MainTaskCore = 0; - MainTaskHandle = xTaskCreateStaticPinnedToCore(&mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_task_stack[0], &mp_task_tcb, 0); + MainTaskHandle = xTaskCreateStaticPinnedToCore(&mp_task, "mp_task", mp_task_stack_len, NULL, CONFIG_MICROPY_TASK_PRIORITY, mp_task_stack, &mp_task_tcb, 0); #else MainTaskCore = 1; #if CONFIG_MICROPY_USE_BOTH_CORES - MainTaskHandle = xTaskCreateStatic(&mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_task_stack[0], &mp_task_tcb); + MainTaskHandle = xTaskCreateStatic(&mp_task, "mp_task", mp_task_stack_len, NULL, CONFIG_MICROPY_TASK_PRIORITY, mp_task_stack, &mp_task_tcb); #else - MainTaskHandle = xTaskCreateStaticPinnedToCore(&mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_task_stack[0], &mp_task_tcb, 1); + MainTaskHandle = xTaskCreateStaticPinnedToCore(&mp_task, "mp_task", mp_task_stack_len, NULL, CONFIG_MICROPY_TASK_PRIORITY, mp_task_stack, &mp_task_tcb, 1); #endif #endif + + if (!MainTaskHandle) { + ESP_LOGE("MicroPython", "Error creating MicroPython task, HALTED."); + } + + ESP_LOGD("MicroPython", "Main task exit, stack used: %d", CONFIG_MAIN_TASK_STACK_SIZE - uxTaskGetStackHighWaterMark(NULL)); + /* + while (1) { + vTaskDelay(60000 / portTICK_PERIOD_MS); + } + */ } //----------------------------- void nlr_jump_fail(void *val) { - printf("RESET: NLR jump failed, val=%p\n", val); - prepareSleepReset(1, NULL); + //printf("RESET: NLR jump failed, val=%p\n", val); + //prepareSleepReset(1, NULL); esp_restart(); } diff --git a/MicroPython_BUILD/components/micropython/esp32/modcurl.c b/MicroPython_BUILD/components/micropython/esp32/modcurl.c index 907ef902..13298bdb 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modcurl.c +++ b/MicroPython_BUILD/components/micropython/esp32/modcurl.c @@ -41,13 +41,12 @@ #include "py/obj.h" #include "py/runtime.h" - +#include "modmachine.h" +#include "modnetwork.h" #include "libs/espcurl.h" +#include "libs/curl_mail.h" #include "extmod/vfs_native.h" -#ifdef CONFIG_MICROPY_USE_MAIL -#include "quickmail.h" -#endif //---------------------------------- static int check_file(char *fname) { @@ -145,7 +144,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(curl_Options_obj, 0, curl_Options); //---------------------------------------------------------------------------------- STATIC mp_obj_t curl_GET(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - checkConnection(); + network_checkConnection(); enum { ARG_url, ARG_file }; const mp_arg_t allowed_args[] = { { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, @@ -199,10 +198,82 @@ STATIC mp_obj_t curl_GET(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(curl_GET_obj, 1, curl_GET); +//--------------------------------------------------------------------------------------- +STATIC mp_obj_t curl_GET_MAIL(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + network_checkConnection(); + enum { ARG_opts, ARG_user, ARG_pass, ARG_server, ARG_port, ARG_file, ARG_req }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_opts, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_user, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_password, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_server, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = GMAIL_IMAP_PORT } }, + { MP_QSTR_file, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_req, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *cust_req = NULL; + char *opts = (char *)mp_obj_str_get_str(args[ARG_opts].u_obj); + char *user = (char *)mp_obj_str_get_str(args[ARG_user].u_obj); + char *pass = (char *)mp_obj_str_get_str(args[ARG_pass].u_obj); + char mail_server[128] = {'\0'}; + int res; + int hdr_len = hdr_maxlen; + int body_len = body_maxlen; + vstr_t header; + vstr_t body; + char *fname = NULL; + char fullname[128] = {'\0'}; + + uint32_t mail_port = args[ARG_port].u_int; + if (MP_OBJ_IS_STR(args[ARG_req].u_obj)) { + (char *)mp_obj_str_get_str(args[ARG_req].u_obj); + } + + if (MP_OBJ_IS_STR(args[ARG_server].u_obj)) sprintf(mail_server, "%s", (char *)mp_obj_str_get_str(args[ARG_server].u_obj)); + else sprintf(mail_server, GMAIL_IMAP); + + if (MP_OBJ_IS_STR(args[ARG_file].u_obj)) { + // GET to file + fname = (char *)mp_obj_str_get_str(args[ARG_file].u_obj); + if (strcmp(fname, "simulate") != 0) { + res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + fname = fullname; + } + body_len = MIN_BODY_BUF_LEN; + } + + vstr_init_len(&header, hdr_len); + vstr_init_len(&body, body_len); + header.buf[0] = '\0'; + body.buf[0] = '\0'; + + MP_THREAD_GIL_EXIT(); + res = Curl_IMAP_GET(opts, fname, header.buf, body.buf, header.len, body.len, mail_server, mail_port, user, pass, cust_req); + MP_THREAD_GIL_ENTER(); + + mp_obj_t tuple[3]; + tuple[0] = mp_obj_new_int(res); + header.len = strlen(header.buf); + body.len = strlen(body.buf); + tuple[1] = mp_obj_new_str_from_vstr(&mp_type_str, &header); + tuple[2] = mp_obj_new_str_from_vstr(&mp_type_str, &body); + + return mp_obj_new_tuple(3, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(curl_GET_MAIL_obj, 1, curl_GET_MAIL); + //----------------------------------------------------------------------------------- STATIC mp_obj_t curl_POST(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - checkConnection(); + network_checkConnection(); enum { ARG_url, ARG_params }; const mp_arg_t allowed_args[] = { { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, @@ -225,50 +296,61 @@ STATIC mp_obj_t curl_POST(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ if (formpost) curl_formfree(formpost); formpost=NULL; lastptr=NULL; + int nparam = 0; // get POST parameters if (MP_OBJ_IS_TYPE(args[ARG_params].u_obj, &mp_type_dict)) { - mp_obj_dict_t *params = MP_OBJ_TO_PTR(args[ARG_params].u_obj); - mp_map_t *map = ¶ms->map; - mp_map_elem_t *table = map->table; - int nparam = map->used; - if (nparam > 0) { - nparam = 0; - for (int i=0; iused; i++) { - const char *key = mp_obj_str_get_str(table[i].key); - if (MP_OBJ_IS_STR(table[i].value)) { - const char *value = mp_obj_str_get_str(table[i].value); - uint8_t fadded = 0; - if (strlen(value) < 128) { - res = physicalPath(value, fullname); - if ((res == 0) && (strlen(fullname) > 0)) { - if (check_file(fullname)) { - curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_FILE, fullname, CURLFORM_END); - nparam++; - fadded = 1; - } - } - } - if (fadded == 0) { - curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_COPYCONTENTS, value, CURLFORM_END); - nparam++; - } - } - else if (MP_OBJ_IS_INT(table[i].value)) { - int ival = mp_obj_get_int(table[i].value); - char sval[64]; - sprintf(sval,"%d", ival); - curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_COPYCONTENTS, sval, CURLFORM_END); - nparam++; - } - else if (MP_OBJ_IS_TYPE(table[i].value, &mp_type_float)) { - double fval = mp_obj_get_float(table[i].value); - char sval[64]; - sprintf(sval,"%f", fval); - curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_COPYCONTENTS, sval, CURLFORM_END); - nparam++; - } - } + const char *key; + const char *value; + mp_obj_dict_t *dict = MP_OBJ_TO_PTR(args[ARG_params].u_obj); + size_t max = dict->map.alloc; + mp_map_t *map = &dict->map; + mp_map_elem_t *next; + size_t cur = 0; + while (1) { + next = NULL; + for (size_t i = cur; i < max; i++) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + cur = i + 1; + next = &(map->table[i]); + break; + } + } + if (next == NULL) break; + + key = mp_obj_str_get_str(next->key); + if (MP_OBJ_IS_STR(next->value)) { + value = mp_obj_str_get_str(next->value); + uint8_t fadded = 0; + if (strlen(value) < 128) { + res = physicalPath(value, fullname); + if ((res == 0) && (strlen(fullname) > 0)) { + if (check_file(fullname)) { + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_FILE, fullname, CURLFORM_END); + nparam++; + fadded = 1; + } + } + } + if (fadded == 0) { + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_COPYCONTENTS, value, CURLFORM_END); + nparam++; + } + } + else if (MP_OBJ_IS_INT(next->value)) { + int ival = mp_obj_get_int(next->value); + char sval[64]; + sprintf(sval,"%d", ival); + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_COPYCONTENTS, sval, CURLFORM_END); + nparam++; + } + else if (MP_OBJ_IS_TYPE(next->value, &mp_type_float)) { + double fval = mp_obj_get_float(next->value); + char sval[64]; + sprintf(sval,"%f", fval); + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key, CURLFORM_COPYCONTENTS, sval, CURLFORM_END); + nparam++; + } } if (nparam == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Expected at least one POST parameter")); @@ -300,13 +382,11 @@ STATIC mp_obj_t curl_POST(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(curl_POST_obj, 1, curl_POST); -#ifdef CONFIG_MICROPY_USE_MAIL - //--------------------------------------------------------------------------------------- STATIC mp_obj_t curl_sendmail(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - checkConnection(); - enum { ARG_user, ARG_pass, ARG_to, ARG_subject, ARG_msg, ARG_cc, ARG_attach, ARG_server, ARG_port, ARG_prot }; + network_checkConnection(); + enum { ARG_user, ARG_pass, ARG_to, ARG_subject, ARG_msg, ARG_cc, ARG_bcc, ARG_attach, ARG_server, ARG_port, ARG_prot }; const mp_arg_t allowed_args[] = { { MP_QSTR_user, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_password, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, @@ -314,10 +394,11 @@ STATIC mp_obj_t curl_sendmail(size_t n_args, const mp_obj_t *pos_args, mp_map_t { MP_QSTR_subject, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_msg, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_cc, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_bcc, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_attach, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_server, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = GMAIL_PORT } }, - { MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = QUICKMAIL_PROT_SMTPS } }, + { MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = CURLMAIL_PROTOCOL_SMTPS } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -332,7 +413,7 @@ STATIC mp_obj_t curl_sendmail(size_t n_args, const mp_obj_t *pos_args, mp_map_t uint32_t mail_port = args[ARG_port].u_int; uint8_t mail_protocol = args[ARG_prot].u_int; - if ((mail_protocol != QUICKMAIL_PROT_SMTP) && (mail_protocol != QUICKMAIL_PROT_SMTPS)) { + if ((mail_protocol != CURLMAIL_PROTOCOL_SMTP) && (mail_protocol != CURLMAIL_PROTOCOL_SMTPS)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported SMTP protocol")); } if (MP_OBJ_IS_STR(args[ARG_server].u_obj)) { @@ -340,61 +421,86 @@ STATIC mp_obj_t curl_sendmail(size_t n_args, const mp_obj_t *pos_args, mp_map_t } else sprintf(mail_server, GMAIL_SMTP); - // Create quickmail object - quickmail mailobj = quickmail_create(user, subj); + // Create curlmail object + curl_mail mailobj = curlmail_create(user, subj); if (mailobj == NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error creating mail object")); } - // Set recipients + // Add recipients if (MP_OBJ_IS_STR(args[ARG_to].u_obj)) { to = (char *)mp_obj_str_get_str(args[ARG_to].u_obj); - quickmail_add_to(mailobj, to); - } + curlmail_add_to(mailobj, to); + } else if (MP_OBJ_IS_TYPE(args[ARG_to].u_obj, &mp_type_tuple)) { mp_obj_t *items; uint len; mp_obj_tuple_get(args[ARG_to].u_obj, &len, &items); + if (len == 0) { + curlmail_destroy(mailobj); + curl_global_cleanup(); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Recipient(s) expected")); + } for (int i = 0; i < len; i++) { to = (char *)mp_obj_str_get_str(items[i]); - quickmail_add_to(mailobj, to); + curlmail_add_to(mailobj, to); } } else { - quickmail_destroy(mailobj); - quickmail_cleanup(); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "At least one recipient expected")); + curlmail_destroy(mailobj); + curl_global_cleanup(); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Recipient(s) expected")); } - // Set CC recipients + // Add CC recipients if (MP_OBJ_IS_STR(args[ARG_cc].u_obj)) { to = (char *)mp_obj_str_get_str(args[ARG_cc].u_obj); - quickmail_add_cc(mailobj, to); - } + curlmail_add_cc(mailobj, to); + } else if (MP_OBJ_IS_TYPE(args[ARG_cc].u_obj, &mp_type_tuple)) { mp_obj_t *items; uint len; mp_obj_tuple_get(args[ARG_cc].u_obj, &len, &items); for (int i = 0; i < len; i++) { to = (char *)mp_obj_str_get_str(items[i]); - quickmail_add_cc(mailobj, to); + curlmail_add_cc(mailobj, to); } } - // Set attachments + // Add BCC recipients + if (MP_OBJ_IS_STR(args[ARG_bcc].u_obj)) { + to = (char *)mp_obj_str_get_str(args[ARG_bcc].u_obj); + curlmail_add_bcc(mailobj, to); + } + else if (MP_OBJ_IS_TYPE(args[ARG_bcc].u_obj, &mp_type_tuple)) { + mp_obj_t *items; + uint len; + mp_obj_tuple_get(args[ARG_bcc].u_obj, &len, &items); + for (int i = 0; i < len; i++) { + to = (char *)mp_obj_str_get_str(items[i]); + curlmail_add_bcc(mailobj, to); + } + } + + // Add attachments if (MP_OBJ_IS_STR(args[ARG_attach].u_obj)) { char *fname = (char *)mp_obj_str_get_str(args[ARG_attach].u_obj); char fullname[128] = {'\0'}; int res = physicalPath(fname, fullname); if ((res == 0) && (strlen(fullname) > 0)) { int exists = check_file(fullname); - if (exists) quickmail_add_attachment_file(mailobj, fullname, NULL); + if (exists) curlmail_add_attachment_file(mailobj, fullname, NULL); } - } + } else if (MP_OBJ_IS_TYPE(args[ARG_attach].u_obj, &mp_type_tuple)) { mp_obj_t *items; uint len; mp_obj_tuple_get(args[ARG_attach].u_obj, &len, &items); + if (len > CURLMAIL_MAX_ATTACHMENTS) { + curlmail_destroy(mailobj); + curl_global_cleanup(); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Maximum number of attachments exceeded")); + } char *fname = NULL; char fullname[128] = {'\0'}; for (int i = 0; i < len; i++) { @@ -402,47 +508,40 @@ STATIC mp_obj_t curl_sendmail(size_t n_args, const mp_obj_t *pos_args, mp_map_t int res = physicalPath(fname, fullname); if ((res == 0) && (strlen(fullname) > 0)) { int exists = check_file(fullname); - if (exists) quickmail_add_attachment_file(mailobj, fullname, NULL); + if (exists) curlmail_add_attachment_file(mailobj, fullname, NULL); } } } - quickmail_set_body(mailobj, msg); - - quickmail_progress = curl_progress; - quickmail_verbose = curl_verbose; - - // set some options - quickmail_add_header(mailobj, "Importance: Low"); - quickmail_add_header(mailobj, "X-Priority: 5"); - quickmail_add_header(mailobj, "X-MSMail-Priority: Low"); + curlmail_set_body(mailobj, msg); - if (curl_verbose) quickmail_set_debug_log(mailobj, stderr); - else quickmail_set_debug_log(mailobj, NULL); + // set headers + curlmail_add_header(mailobj, "Importance: Low"); + curlmail_add_header(mailobj, "X-Priority: 5"); + curlmail_add_header(mailobj, "X-MSMail-Priority: Low"); const char* errmsg = NULL; - errmsg = quickmail_protocol_send(mailobj, mail_server, mail_port, mail_protocol, user, pass); + errmsg = curlmail_protocol_send(mailobj, mail_server, mail_port, mail_protocol, user, pass); // Cleanup - quickmail_destroy(mailobj); - quickmail_cleanup(); + curlmail_destroy(mailobj); + curl_global_cleanup(); if (errmsg) { - if (quickmail_verbose) mp_printf(&mp_plat_print, "ERROR: %s\n", errmsg); + if (curl_verbose) mp_printf(&mp_plat_print, "ERROR: %s\n", errmsg); return mp_const_false; } return mp_const_true; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(curl_sendmail_obj, 1, curl_sendmail); -#endif // CONFIG_MICROPY_USE_MAIL #ifdef CONFIG_MICROPY_USE_CURLFTP //------------------------------------------------------------------------------------------------------- STATIC mp_obj_t curl_FTP_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, uint8_t type) { - checkConnection(); + network_checkConnection(); enum { ARG_url, ARG_user, ARG_pass, ARG_file }; const mp_arg_t allowed_args[] = { { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, @@ -496,7 +595,7 @@ STATIC mp_obj_t curl_FTP_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_ body.buf[0] = '\0'; MP_THREAD_GIL_EXIT(); - res = Curl_FTP(type&1, url, userpass, fname, header.buf, body.buf, header.len, body.len); + res = Curl_FTP(type&1, (char *)url, userpass, fname, header.buf, body.buf, header.len, body.len); MP_THREAD_GIL_ENTER(); mp_obj_t tuple[3]; @@ -541,10 +640,8 @@ STATIC const mp_rom_map_elem_t curl_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_options), MP_ROM_PTR(&curl_Options_obj) }, { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&curl_GET_obj) }, { MP_ROM_QSTR(MP_QSTR_post), MP_ROM_PTR(&curl_POST_obj) }, - - #ifdef CONFIG_MICROPY_USE_MAIL { MP_ROM_QSTR(MP_QSTR_sendmail), MP_ROM_PTR(&curl_sendmail_obj) }, - #endif + { MP_ROM_QSTR(MP_QSTR_getmail), MP_ROM_PTR(&curl_GET_MAIL_obj) }, #ifdef CONFIG_MICROPY_USE_CURLFTP { MP_ROM_QSTR(MP_QSTR_ftp_get), MP_ROM_PTR(&curl_FTP_GET_obj) }, @@ -553,10 +650,8 @@ STATIC const mp_rom_map_elem_t curl_module_globals_table[] = { #endif // Constants - #ifdef CONFIG_MICROPY_USE_MAIL - { MP_ROM_QSTR(MP_QSTR_SMTP), MP_ROM_INT(QUICKMAIL_PROT_SMTP) }, - { MP_ROM_QSTR(MP_QSTR_SMTPS), MP_ROM_INT(QUICKMAIL_PROT_SMTPS) }, - #endif + { MP_ROM_QSTR(MP_QSTR_SMTP), MP_ROM_INT(CURLMAIL_PROTOCOL_SMTP) }, + { MP_ROM_QSTR(MP_QSTR_SMTPS), MP_ROM_INT(CURLMAIL_PROTOCOL_SMTPS) }, }; STATIC MP_DEFINE_CONST_DICT(curl_module_globals, curl_module_globals_table); diff --git a/MicroPython_BUILD/components/micropython/esp32/moddisplay.c b/MicroPython_BUILD/components/micropython/esp32/moddisplay.c index 75dbb79d..1707642a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/moddisplay.c +++ b/MicroPython_BUILD/components/micropython/esp32/moddisplay.c @@ -24,1564 +24,35 @@ * THE SOFTWARE. */ -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "rom/ets_sys.h" -#include "esp_system.h" -#include "esp_task_wdt.h" -#include - -#include "py/obj.h" -#include "py/objint.h" -#include "py/runtime.h" - -#include "driver/gpio.h" -#include "tft/tftspi.h" -#include "tft/tft.h" -#include "extmod/vfs_native.h" -#include "machine_hw_spi.h" -#include "modmachine.h" +#include "sdkconfig.h" +#ifdef CONFIG_MICROPY_USE_DISPLAY -typedef struct _display_tft_obj_t { - mp_obj_base_t base; - machine_hw_spi_obj_t *spi; - display_config_t dconfig; - exspi_device_handle_t disp_spi_dev; - exspi_device_handle_t ts_spi_dev; - exspi_device_handle_t *disp_spi; - exspi_device_handle_t *ts_spi; - uint32_t tp_calx; - uint32_t tp_caly; -} display_tft_obj_t; +#include -const mp_obj_type_t display_tft_type; +#include "py/obj.h" uint8_t disp_used_spi_host = 0; -static const char* const display_types[] = { - "ILI9341", - "ILI9488", - "ST7789V", - "ST7735", - "ST7735R", - "ST7735B", - "M5STACK", - "Unknown", -}; - -static const char* const touch_types[] = { - "None", - "xpt2046", - "stmpe610", - "Unknown", -}; - -// constructor(id, ...) -//----------------------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - - display_tft_obj_t *self = m_new_obj(display_tft_obj_t); //(display_tft_obj_t*)&display_tft_obj; - self->base.type = &display_tft_type; - self->spi = NULL; - self->disp_spi_dev.handle = NULL; - self->disp_spi_dev.cs = -1; - self->disp_spi_dev.dc = -1; - self->disp_spi_dev.selected = 0; - self->ts_spi_dev.handle = NULL; - self->ts_spi_dev.cs = -1; - self->ts_spi_dev.dc = -1; - self->ts_spi_dev.selected = 0; - self->disp_spi = &self->disp_spi_dev; - self->ts_spi = &self->ts_spi_dev; - - //return (mp_obj_t)&display_tft_obj; - return MP_OBJ_FROM_PTR(self); -} - -//----------------------------------------------------------------------------------------------- -STATIC void display_tft_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) -{ - display_tft_obj_t *self = self_in; - if (self->disp_spi->handle) { - mp_printf(print, "TFT (%dx%d, Type=%s, Ready: %s, Color mode: %d-bit, Clk=%u Hz, RdClk=%u Hz, Touch: %s)\n", - self->dconfig.width, self->dconfig.height, display_types[self->dconfig.type], ((self->disp_spi->handle) ? "yes" : "no"), self->dconfig.color_bits, self->dconfig.speed, self->dconfig.rdspeed, ((self->ts_spi->handle) ? "yes" : "no")); - mp_printf(print, "Pins (miso=%d, mosi=%d, clk=%d, cs=%d, dc=%d, reset=%d, backlight=%d)", self->dconfig.miso, self->dconfig.mosi, self->dconfig.sck, self->dconfig.cs, self->dconfig.dc, self->dconfig.rst, self->dconfig.bckl); - if (self->ts_spi->handle) { - mp_printf(print, "\nTouch (Enabled, type: %s, cs=%d)", touch_types[self->dconfig.touch], self->dconfig.tcs); - } - } - else { - mp_printf(print, "TFT (Not initialized)"); - } -} - -/* - * tftspi.c low level driver uses some global variables - * Here we set those variables so that multiple displays can be used - */ -//------------------------------------------------- -static int setupDevice(display_tft_obj_t *disp_dev) -{ - if (disp_dev->disp_spi->handle == NULL) return 1; - - if (disp_spi != disp_dev->disp_spi) { - disp_spi = disp_dev->disp_spi; - ts_spi = disp_dev->ts_spi; - TFT_display_setvars(&disp_dev->dconfig); - - tp_calx = disp_dev->tp_calx; - tp_caly = disp_dev->tp_caly; - spi_device_select(disp_spi, 1); - spi_device_deselect(disp_spi); - } - - return 0; -} - -//-------------------------------------- -STATIC color_t intToColor(uint32_t cint) -{ - color_t cl = {0,0,0}; - cl.r = (cint >> 16) & 0xFF; - cl.g = (cint >> 8) & 0xFF; - cl.b = cint & 0xFF; - return cl; -} - -//------------------------------------------------------ -STATIC void spi_deinit_internal(display_tft_obj_t *self) -{ - if (self->disp_spi->handle) { - esp_err_t ret; - // Deinitialize display spi device(s) - if (self->ts_spi->handle) { - ret = remove_extspi_device(self->ts_spi); - if (ret != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "Error removing touch device"); - } - } - ret = remove_extspi_device(self->disp_spi); - if (ret != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "Error removing display device"); - } - - gpio_pad_select_gpio(self->dconfig.miso); - gpio_pad_select_gpio(self->dconfig.mosi); - gpio_pad_select_gpio(self->dconfig.sck); - } -} - - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_type, ARG_host, ARG_width, ARG_height, ARG_speed, ARG_miso, ARG_mosi, ARG_clk, ARG_cs, - ARG_dc, ARG_tcs, ARG_rst, ARG_bckl, ARG_bcklon, ARG_hastouch, ARG_invrot, ARG_bgr, ARG_cbits, ARG_rot, ARG_splash }; - const mp_arg_t allowed_args[] = { - { MP_QSTR_type, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = DISP_TYPE_ST7789V } }, - { MP_QSTR_spihost, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = HSPI_HOST } }, - { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = DEFAULT_TFT_DISPLAY_WIDTH } }, - { MP_QSTR_height, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = DEFAULT_TFT_DISPLAY_HEIGHT } }, - { MP_QSTR_speed, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 10000000 } }, - { MP_QSTR_miso, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_mosi, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_clk, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_cs, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_dc, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_tcs, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_rst_pin, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_backl_pin, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_backl_on, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_hastouch, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = TOUCH_TYPE_NONE } }, - { MP_QSTR_invrot, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_bgr, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, - { MP_QSTR_color_bits, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 24 } }, - { MP_QSTR_rot, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_splash, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = true } }, - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - display_tft_obj_t *self = pos_args[0]; - esp_err_t ret; - - // === deinitialize display spi device if it was initialized === - if (self->disp_spi->handle) spi_deinit_internal(self); - - // === Get arguments === - if ((args[ARG_host].u_int != HSPI_HOST) && (args[ARG_host].u_int != VSPI_HOST)) { - mp_raise_ValueError("SPI host must be either HSPI(1) or VSPI(2)"); - } - if ((SPIbus_configs[VSPI_HOST] == NULL) && (args[ARG_host].u_int == VSPI_HOST)) { - mp_raise_ValueError("SPI host must be HSPI(1), VSPI(2) used by SPIRAM"); - } - - if ((args[ARG_type].u_int < 0) || (args[ARG_type].u_int >= DISP_TYPE_MAX)) { - mp_raise_ValueError("Unsupported display type"); - } - - if ((args[ARG_cbits].u_int != 16) && (args[ARG_cbits].u_int != 24)) { - mp_raise_ValueError("Unsupported color bits"); - } - - self->dconfig.color_bits = args[ARG_cbits].u_int; - - self->dconfig.type = args[ARG_type].u_int; - - if ((args[ARG_hastouch].u_int == TOUCH_TYPE_XPT2046) || (args[ARG_hastouch].u_int == TOUCH_TYPE_STMPE610)) { - if (args[ARG_tcs].u_int < 0) { - mp_raise_ValueError("Touch selected but no touch cs given"); - } - self->dconfig.touch = args[ARG_hastouch].u_int; - if (args[ARG_hastouch].u_int == TOUCH_TYPE_XPT2046) { - self->tp_calx = TP_CALX_XPT2046; - self->tp_caly = TP_CALY_XPT2046; - } - else { - self->tp_calx = TP_CALX_STMPE610; - self->tp_caly = TP_CALY_STMPE610; - } - self->dconfig.tcs = args[ARG_tcs].u_int; - } - else self->dconfig.touch = TOUCH_TYPE_NONE; - - self->dconfig.host = args[ARG_host].u_int; - self->dconfig.gamma = 0; - self->dconfig.width = args[ARG_width].u_int; // smaller dimension - self->dconfig.height = args[ARG_height].u_int; // larger dimension - self->dconfig.rdspeed = 8000000; - if (args[ARG_invrot].u_int >= 0) self->dconfig.invrot = args[ARG_invrot].u_int; - else { - if ((self->dconfig.type == DISP_TYPE_ST7789V) || - (self->dconfig.type == DISP_TYPE_ST7735) || - (self->dconfig.type == DISP_TYPE_ST7735R) || - (self->dconfig.type == DISP_TYPE_ST7735B)) self->dconfig.invrot = 1; - else if (self->dconfig.type == DISP_TYPE_M5STACK) self->dconfig.invrot = 3; - else self->dconfig.invrot = 0; - } - - if (args[ARG_bgr].u_bool) self->dconfig.bgr = 8; - else self->dconfig.bgr = 0; - - self->dconfig.rst = args[ARG_rst].u_int; - self->dconfig.bckl = args[ARG_bckl].u_int; - self->dconfig.bckl_on = args[ARG_bcklon].u_int & 1; - - self->dconfig.miso = args[ARG_miso].u_int; - self->dconfig.mosi = args[ARG_mosi].u_int; - self->dconfig.sck = args[ARG_clk].u_int; - - self->dconfig.cs = args[ARG_cs].u_int; - self->dconfig.dc = args[ARG_dc].u_int; - - disp_spi = self->disp_spi; - ts_spi = self->ts_spi; - - int orient = args[ARG_rot].u_int; - if (orient < 0) { - if (self->dconfig.type == DISP_TYPE_M5STACK) orient = LANDSCAPE; - else orient = PORTRAIT; - } - else orient &= 3; - - // ================================ - // ==== Initialize the Display ==== - ret = TFT_display_init(&self->dconfig); - if (ret != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "Error initializing display"); - } - - disp_used_spi_host = args[ARG_host].u_int; - - if (self->dconfig.type == DISP_TYPE_GENERIC) return mp_const_none; - - // ==== Set SPI clock used for display operations ==== - self->dconfig.speed = spi_set_speed(self->disp_spi, args[ARG_speed].u_int); - - max_rdclock = find_rd_speed(); - self->dconfig.rdspeed = max_rdclock; - - font_rotate = 0; - text_wrap = 0; - font_transparent = 0; - font_forceFixed = 0; - gray_scale = 0; - TFT_setRotation(orient); - self->dconfig.width = _width; - self->dconfig.height = _height; - TFT_setGammaCurve(0); - TFT_setFont(DEFAULT_FONT, NULL); - TFT_resetclipwin(); - if (args[ARG_splash].u_bool) { - int fhight = TFT_getfontheight(); - _fg = intToColor(iTFT_RED); - TFT_print("MicroPython", CENTER, (_height/2) - fhight - (fhight/2)); - _fg = intToColor(iTFT_GREEN); - TFT_print("MicroPython", CENTER, (_height/2) - (fhight/2)); - _fg = intToColor(iTFT_BLUE); - TFT_print("MicroPython", CENTER, (_height/2) + (fhight/2)); - _fg = intToColor(iTFT_GREEN); - } - - bcklOn(&self->dconfig); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_init_obj, 0, display_tft_init); - -//-------------------------------------------------- -STATIC mp_obj_t display_tft_deinit(mp_obj_t self_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self) == 0) { - spi_deinit_internal(self); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_deinit_obj, display_tft_deinit); - -//------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_drawPixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - if (args[2].u_int >= 0) { - color = intToColor(args[2].u_int); - } - TFT_drawPixel(x, y, color, 1); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawPixel_obj, 2, display_tft_drawPixel); - -//------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_readPixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - - color_t color = TFT_readPixel(x, y); - mp_int_t icolor = (int)((color.r << 16) | (color.g << 8) | color.b); - - return mp_obj_new_int(icolor); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_readPixel_obj, 2, display_tft_readPixel); - -//------------------------------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_drawLine(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x0 = args[0].u_int; - mp_int_t y0 = args[1].u_int; - mp_int_t x1 = args[2].u_int; - mp_int_t y1 = args[3].u_int; - if (args[4].u_int >= 0) { - color = intToColor(args[4].u_int); - } - TFT_drawLine(x0, y0, x1, y1, color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawLine_obj, 4, display_tft_drawLine); - -//------------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_drawLineByAngle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_start, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_length, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_angle, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - mp_int_t start = args[2].u_int; - mp_int_t len = args[3].u_int; - mp_int_t angle = args[4].u_int; - if (args[5].u_int >= 0) { - color = intToColor(args[5].u_int); - } - TFT_drawLineByAngle(x, y, start, len, angle, color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawLineByAngle_obj, 5, display_tft_drawLineByAngle); - -//---------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_drawTriangle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_x2, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y2, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x0 = args[0].u_int; - mp_int_t y0 = args[1].u_int; - mp_int_t x1 = args[2].u_int; - mp_int_t y1 = args[3].u_int; - mp_int_t x2 = args[4].u_int; - mp_int_t y2 = args[5].u_int; - if (args[6].u_int >= 0) { - color = intToColor(args[6].u_int); - } - if (args[7].u_int >= 0) { - TFT_fillTriangle(x0, y0, x1, y1, x2, y2, intToColor(args[7].u_int)); - } - TFT_drawTriangle(x0, y0, x1, y1, x2, y2, color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawTriangle_obj, 6, display_tft_drawTriangle); - -//-------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_drawCircle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - mp_int_t radius = args[2].u_int; - if (args[3].u_int >= 0) { - color = intToColor(args[3].u_int); - } - if (args[4].u_int >= 0) { - TFT_fillCircle(x, y, radius, intToColor(args[4].u_int)); - if (args[3].u_int != args[4].u_int) TFT_drawCircle(x, y, radius, color); - } - else TFT_drawCircle(x, y, radius, color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawCircle_obj, 3, display_tft_drawCircle); - -//--------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_drawEllipse(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_ry, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_opt, MP_ARG_INT, { .u_int = 15 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - mp_int_t rx = args[2].u_int; - mp_int_t ry = args[3].u_int; - mp_int_t opt = args[4].u_int & 0x0F; - if (args[5].u_int >= 0) { - color = intToColor(args[5].u_int); - } - if (args[6].u_int >= 0) { - TFT_fillEllipse(x, y, rx, ry, intToColor(args[6].u_int), opt); - } - TFT_drawEllipse(x, y, rx, ry, color, opt); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawEllipse_obj, 4, display_tft_drawEllipse); - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_drawArc(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_thick, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_start, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_end, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 15 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - color_t fill_color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - mp_int_t r = args[2].u_int; - mp_int_t th = args[3].u_int; - mp_int_t start = args[4].u_int; - mp_int_t end = args[5].u_int; - if (args[6].u_int >= 0) { - color = intToColor(args[6].u_int); - } - if (args[7].u_int >= 0) { - fill_color = intToColor(args[7].u_int); - } - TFT_drawArc(x, y, r, th, start, end, color, fill_color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawArc_obj, 6, display_tft_drawArc); - -//------------------------------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_drawPoly(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_sides, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_thick, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 1 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_rotate, MP_ARG_INT, { .u_int = 0 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - color_t fill_color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - mp_int_t r = args[2].u_int; - mp_int_t sides = args[3].u_int; - mp_int_t th = args[4].u_int; - if (args[5].u_int >= 0) { - color = intToColor(args[5].u_int); - } - if (args[6].u_int >= 0) { - fill_color = intToColor(args[6].u_int); - } - TFT_drawPolygon(x, y, sides, r, color, fill_color, args[7].u_int, th); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawPoly_obj, 5, display_tft_drawPoly); - -//------------------------------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_drawRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - mp_int_t w = args[2].u_int; - mp_int_t h = args[3].u_int; - if (args[4].u_int >= 0) { - color = intToColor(args[4].u_int); - } - if (args[5].u_int >= 0) { - TFT_fillRect(x, y, w, h, intToColor(args[5].u_int)); - } - TFT_drawRect(x, y, w, h, color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawRect_obj, 4, display_tft_drawRect); - -//----------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_drawRoundRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _fg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - mp_int_t w = args[2].u_int; - mp_int_t h = args[3].u_int; - mp_int_t r = args[4].u_int; - if (args[5].u_int >= 0) { - color = intToColor(args[5].u_int); - } - if (args[6].u_int >= 0) { - TFT_fillRoundRect(x, y, w, h, r, intToColor(args[6].u_int)); - } - TFT_drawRoundRect(x, y, w, h, r, color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawRoundRect_obj, 5, display_tft_drawRoundRect); - -//-------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_fillScreen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _bg; - if (args[0].u_int >= 0) { - color = intToColor(args[0].u_int); - } - TFT_fillScreen(color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillScreen_obj, 0, display_tft_fillScreen); - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_fillWin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t color = _bg; - if (args[0].u_int >= 0) { - color = intToColor(args[0].u_int); - } - TFT_fillWindow(color); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillWin_obj, 0, display_tft_fillWin); - -//-------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_7segAttrib(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_dist, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_outline, MP_ARG_REQUIRED | MP_ARG_BOOL, { .u_bool = false } }, - { MP_QSTR_color, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - set_7seg_font_atrib(args[0].u_int, args[1].u_int, (int)args[2].u_bool, intToColor(args[3].u_int)); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_7segAttrib_obj, 4, display_tft_7segAttrib); - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_setFont(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_font, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_rotate, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_transparent, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fixedwidth, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_dist, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 8 } }, - { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 2 } }, - { MP_QSTR_outline, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, - { MP_QSTR_color, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - const char *font_file = NULL; - char fullname[128] = {'\0'}; - mp_int_t font = DEFAULT_FONT; - - if (MP_OBJ_IS_STR(args[0].u_obj)) { - font_file = mp_obj_str_get_str(args[0].u_obj); - - if (physicalPath(font_file, fullname) == 0) { - font = USER_FONT; - font_file = fullname; - } - } - else { - font = mp_obj_get_int(args[0].u_obj); - } - TFT_setFont(font, font_file); - - if (args[1].u_int >= 0) font_rotate = args[1].u_int; - if (args[2].u_int >= 0) font_transparent = args[2].u_int & 1; - if (args[3].u_int >= 0) font_forceFixed = args[3].u_int & 1; - - if (font == FONT_7SEG) { - set_7seg_font_atrib(args[4].u_int, args[5].u_int, (int)args[6].u_bool, intToColor(args[7].u_int)); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setFont_obj, 1, display_tft_setFont); - -//------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_getFontSize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - int width, height; - TFT_getfontsize(&width, &height); - - mp_obj_t tuple[2]; - - tuple[0] = mp_obj_new_int(width); - tuple[1] = mp_obj_new_int(height); - - return mp_obj_new_tuple(2, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getFontSize_obj, 0, display_tft_getFontSize); - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_setRot(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_rot, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = PORTRAIT } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_int_t rot = args[0].u_int; - if ((rot < 0) || (rot > 3)) rot = 0; - - TFT_setRotation(rot); - self->dconfig.width = _width; - self->dconfig.height = _height; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setRot_obj, 1, display_tft_setRot); - -//--------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_rotate, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_transparent, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_fixedwidth, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_bgcolor, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t old_fg = _fg; - color_t old_bg = _bg; - int old_rot = font_rotate; - int old_transp = font_transparent; - int old_fixed = font_forceFixed; - int old_wrap = text_wrap; - - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - char *st = (char *)mp_obj_str_get_str(args[2].u_obj); - - if (args[3].u_int >= 0) _fg = intToColor(args[3].u_int); - if (args[4].u_int >= 0) font_rotate = args[4].u_int; - if (args[5].u_int >= 0) font_transparent = args[5].u_int & 1; - if (args[6].u_int >= 0) font_forceFixed = args[6].u_int & 1; - if (args[7].u_int >= 0) text_wrap = args[7].u_int & 1; - if (args[8].u_int >= 0) _bg = intToColor(args[8].u_int); - - TFT_print(st, x, y); - - _fg = old_fg; - _bg = old_bg; - font_rotate = old_rot; - font_transparent = old_transp; - font_forceFixed = old_fixed; - text_wrap = old_wrap; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_print_obj, 3, display_tft_print); - -//--------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_stringWidth(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - char *st = (char *)mp_obj_str_get_str(args[0].u_obj); - - mp_int_t w = TFT_getStringWidth(st); - - return mp_obj_new_int(w); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_stringWidth_obj, 1, display_tft_stringWidth); - -//------------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_clearStringRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - color_t old_bg = _bg; - mp_int_t x = args[0].u_int; - mp_int_t y = args[1].u_int; - char *st = (char *)mp_obj_str_get_str(args[2].u_obj); - - if (args[3].u_int >= 0) _bg = intToColor(args[3].u_int); - - TFT_clearStringRect(x, y, st); - - _bg = old_bg; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_clearStringRect_obj, 3, display_tft_clearStringRect); - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_Image(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_scale, MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_type, MP_ARG_INT, { .u_int = -1 } }, - { MP_QSTR_debug, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - char *fname = NULL; - char fullname[128] = {'\0'}; - int img_type = args[4].u_int; - - fname = (char *)mp_obj_str_get_str(args[2].u_obj); - - int res = physicalPath(fname, fullname); - if ((res != 0) || (strlen(fullname) == 0)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); - } - - if (img_type < 0) { - // try to determine image type - char upr_fname[128]; - strcpy(upr_fname, fname); - for (int i=0; i < strlen(upr_fname); i++) { - upr_fname[i] = toupper((unsigned char) upr_fname[i]); - } - if (strstr(upr_fname, ".JPG") != NULL) img_type = IMAGE_TYPE_JPG; - else if (strstr(upr_fname, ".BMP") != NULL) img_type = IMAGE_TYPE_BMP; - else { - FILE *fhndl = fopen(fullname, "r"); - if (fhndl != NULL) { - uint8_t buf[16]; - if (fread(buf, 1, 11, fhndl) == 11) { - buf[10] = 0; - if (strstr((char *)(buf+6), "JFIF") != NULL) img_type = IMAGE_TYPE_JPG; - else if ((buf[0] = 0x42) && (buf[1] = 0x4d)) img_type = IMAGE_TYPE_BMP; - } - fclose(fhndl); - } - } - if (img_type < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Cannot determine image type")); - } - } - - image_debug = (uint8_t)args[5].u_bool; - if (img_type == IMAGE_TYPE_BMP) { - TFT_bmp_image(args[0].u_int, args[1].u_int, args[3].u_int, fullname, NULL, 0); - } - else if (img_type == IMAGE_TYPE_JPG) { - TFT_jpg_image(args[0].u_int, args[1].u_int, args[3].u_int, fullname, NULL, 0); - } - else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported image type")); - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_Image_obj, 3, display_tft_Image); - -//------------------------------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_getTouch(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_raw, MP_ARG_BOOL, { .u_bool = false } }, - { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - if (setupDevice(self)) return mp_const_none; - if (self->ts_spi->handle == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch not configured")); - } - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - int x = 0; - int y = 0; - uint8_t raw = 0; - if (args[0].u_bool) raw = 1; - int wait = args[1].u_int; - if ((wait < 5) || (wait > 60000)) wait = 0; - - int res = TFT_read_touch(&x, &y, raw); - if (wait) { - #ifdef CONFIG_MICROPY_USE_TASK_WDT - esp_task_wdt_reset(); - #endif - struct timeval tv; - gettimeofday(&tv, NULL); - uint32_t tstart = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); - uint32_t tend = tstart; - uint32_t nres = tstart; - - // wait until not touched - while ((tend-tstart) < wait) { - res = TFT_read_touch(&x, &y, raw); - if (res == 0) break; - vTaskDelay(2); - gettimeofday(&tv, NULL); - tend = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); - #ifdef CONFIG_MICROPY_USE_TASK_WDT - if ((tend-nres) > (CONFIG_TASK_WDT_TIMEOUT_S*500)) { - esp_task_wdt_reset(); - nres = tend; - } - #endif - } - // wait until touched - while ((tend-tstart) < wait) { - res = TFT_read_touch(&x, &y, raw); - if (res) break; - vTaskDelay(2); - gettimeofday(&tv, NULL); - tend = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); - #ifdef CONFIG_MICROPY_USE_TASK_WDT - if ((tend-nres) > (CONFIG_TASK_WDT_TIMEOUT_S*500)) { - esp_task_wdt_reset(); - nres = tend; - } - #endif - } - } - - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_bool(res); - tuple[1] = mp_obj_new_int(x); - tuple[2] = mp_obj_new_int(y); - - return mp_obj_new_tuple(3, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getTouch_obj, 0, display_tft_getTouch); - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_compileFont(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_debug, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, - }; - //display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - //if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - char *fname = NULL; - char fullname[128] = {'\0'}; - uint8_t debug = (uint8_t)args[1].u_bool; - - fname = (char *)mp_obj_str_get_str(args[0].u_obj); - - int res = physicalPath(fname, fullname); - if ((res != 0) || (strlen(fullname) == 0)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); - } - - res = compile_font_file(fullname, debug); - if (res) return mp_const_false; - return mp_const_true; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_compileFont_obj, 1, display_tft_compileFont); - -//----------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_HSBtoRGB(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_hue, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_saturation, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_brightness, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_float_t hue = mp_obj_get_float(args[0].u_obj); - mp_float_t sat = mp_obj_get_float(args[1].u_obj); - mp_float_t bri = mp_obj_get_float(args[2].u_obj); - - color_t color = HSBtoRGB(hue, sat, bri); - mp_int_t icolor = (int)((color.r << 16) | (color.g << 8) | color.b); - - return mp_obj_new_int(icolor); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_HSBtoRGB_obj, 3, display_tft_HSBtoRGB); - -//-------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_setclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_int_t x0 = args[0].u_int; - mp_int_t y0 = args[1].u_int; - mp_int_t x1 = args[2].u_int; - mp_int_t y1 = args[3].u_int; - - TFT_setclipwin(x0, y0, x1, y1); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setclipwin_obj, 4, display_tft_setclipwin); - -//---------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_resetclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - TFT_resetclipwin(); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_resetclipwin_obj, 0, display_tft_resetclipwin); - -//--------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_saveclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - TFT_saveClipWin(); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_saveclipwin_obj, 0, display_tft_saveclipwin); - -//------------------------------------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_restoreclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - TFT_restoreClipWin(); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_restoreclipwin_obj, 0, display_tft_restoreclipwin); - -//------------------------------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_getSize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_obj_t tuple[2]; - tuple[0] = mp_obj_new_int(_width); - tuple[1] = mp_obj_new_int(_height); - - return mp_obj_new_tuple(2, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getSize_obj, 0, display_tft_getSize); - -//-------------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_getWinSize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - - mp_obj_t tuple[2]; - tuple[0] = mp_obj_new_int(dispWin.x2 - dispWin.x1 + 1); - tuple[1] = mp_obj_new_int(dispWin.y2 - dispWin.y1 + 1); - - return mp_obj_new_tuple(2, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getWinSize_obj, 0, display_tft_getWinSize); - -//------------------------------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_setCalib(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - - const mp_arg_t allowed_args[] = { - { MP_QSTR_calx, MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_caly, MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_from_nvs, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, - }; - display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (setupDevice(self)) return mp_const_none; - if (self->ts_spi->handle == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch not configured")); - } - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - if (self->dconfig.touch == TOUCH_TYPE_NONE) { - return mp_const_none; - } - - if (args[2].u_bool) { - if (mpy_nvs_handle == 0) { - mp_raise_msg(&mp_type_OSError, "NVS not available!"); - } - int calx = 0, caly = 0; - bool f = true; - if (ESP_ERR_NVS_NOT_FOUND == nvs_get_i32(mpy_nvs_handle, "tpcalibX", &calx)) f = false; - if (f) { - if (ESP_ERR_NVS_NOT_FOUND == nvs_get_i32(mpy_nvs_handle, "tpcalibY", &caly)) f = false; - } - if (!f) { - mp_raise_msg(&mp_type_OSError, "Calibration values not found in NVS"); - } - self->tp_calx = calx; - self->tp_caly = caly; - return mp_const_none; - } - - if (args[0].u_int == 0) { - if (self->dconfig.touch == TOUCH_TYPE_XPT2046) self->tp_calx = TP_CALX_XPT2046; - else self->tp_calx = TP_CALX_STMPE610; - } - else self->tp_calx = args[0].u_int; - - if (args[1].u_int == 0) { - if (self->dconfig.touch == TOUCH_TYPE_XPT2046) self->tp_caly = TP_CALY_XPT2046; - else self->tp_caly = TP_CALY_STMPE610; - } - else self->tp_caly = args[1].u_int; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setCalib_obj, 0, display_tft_setCalib); - -//---------------------------------------------------- -STATIC mp_obj_t display_tft_getCalib(mp_obj_t self_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - if (self->ts_spi->handle == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch not configured")); - } - mp_obj_t tuple[2]; - - tuple[0] = mp_obj_new_int(self->tp_calx); - tuple[1] = mp_obj_new_int(self->tp_caly); - - return mp_obj_new_tuple(2, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_getCalib_obj, display_tft_getCalib); - - -//------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_backlight(mp_obj_t self_in, mp_obj_t onoff_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - int onoff = mp_obj_get_int(onoff_in); - if (onoff) bcklOn(&self->dconfig); - else bcklOff(&self->dconfig); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_backlight_obj, display_tft_backlight); - -//------------------------------------------------------ -STATIC mp_obj_t display_tft_touch_type(mp_obj_t self_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - return mp_obj_new_int(self->dconfig.touch); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_touch_type_obj, display_tft_touch_type); - - -// ==== Low level functions ====================================== - -//------------------------------------------------------------------------ -STATIC mp_obj_t display_tft_set_speed(mp_obj_t self_in, mp_obj_t speed_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - int speed = mp_obj_get_int(speed_in); - - // Set SPI clock used for display operations - self->dconfig.speed = spi_set_speed(self->disp_spi, speed); - - max_rdclock = find_rd_speed(); - self->dconfig.rdspeed = max_rdclock; - - mp_obj_t tuple[2]; - - tuple[0] = mp_obj_new_int(self->dconfig.speed); - tuple[1] = mp_obj_new_int(self->dconfig.rdspeed); - - return mp_obj_new_tuple(2, tuple); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_set_speed_obj, display_tft_set_speed); - -//-------------------------------------------------- -STATIC mp_obj_t display_tft_select(mp_obj_t self_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - disp_select(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_select_obj, display_tft_select); - -//---------------------------------------------------- -STATIC mp_obj_t display_tft_deselect(mp_obj_t self_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - disp_deselect(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_deselect_obj, display_tft_deselect); - -//-------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_cmd_read(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t len_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - uint8_t cmd = (uint8_t)mp_obj_get_int(cmd_in); - uint8_t len = (uint8_t)mp_obj_get_int(len_in); - if ((len < 1) || (len > 4)) len = 1; - - uint32_t res = read_cmd(cmd, len); - - return mp_obj_new_int_from_uint(res); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(display_tft_cmd_read_obj, display_tft_cmd_read); - -//------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_send_command(mp_obj_t self_in, mp_obj_t cmd_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - uint8_t cmd = (uint8_t)mp_obj_get_int(cmd_in); - - disp_select(); - disp_spi_transfer_cmd(cmd); - wait_trans_finish(0); - disp_deselect(); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_send_command_obj, display_tft_send_command); - -//-------------------------------------------------------------------------------------------- -STATIC mp_obj_t display_tft_send_cmd_data(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t data_in) -{ - display_tft_obj_t *self = self_in; - if (setupDevice(self)) return mp_const_none; - - uint8_t cmd = (uint8_t)mp_obj_get_int(cmd_in); - mp_buffer_info_t data; - mp_get_buffer_raise(data_in, &data, MP_BUFFER_READ); - - disp_select(); - disp_spi_transfer_cmd_data(cmd, data.buf, data.len); - wait_trans_finish(0); - disp_deselect(); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(display_tft_send_cmd_data_obj, display_tft_send_cmd_data); - - - -//================================================================ -STATIC const mp_rom_map_elem_t display_tft_locals_dict_table[] = { - // instance methods - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&display_tft_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&display_tft_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&display_tft_drawPixel_obj) }, - { MP_ROM_QSTR(MP_QSTR_readPixel), MP_ROM_PTR(&display_tft_readPixel_obj) }, - { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&display_tft_drawLine_obj) }, - { MP_ROM_QSTR(MP_QSTR_lineByAngle), MP_ROM_PTR(&display_tft_drawLineByAngle_obj) }, - { MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&display_tft_drawTriangle_obj) }, - { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&display_tft_drawCircle_obj) }, - { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&display_tft_drawEllipse_obj) }, - { MP_ROM_QSTR(MP_QSTR_arc), MP_ROM_PTR(&display_tft_drawArc_obj) }, - { MP_ROM_QSTR(MP_QSTR_polygon), MP_ROM_PTR(&display_tft_drawPoly_obj) }, - { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&display_tft_drawRect_obj) }, - { MP_ROM_QSTR(MP_QSTR_roundrect), MP_ROM_PTR(&display_tft_drawRoundRect_obj) }, - { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&display_tft_fillScreen_obj) }, - { MP_ROM_QSTR(MP_QSTR_clearwin), MP_ROM_PTR(&display_tft_fillWin_obj) }, - { MP_ROM_QSTR(MP_QSTR_font), MP_ROM_PTR(&display_tft_setFont_obj) }, - { MP_ROM_QSTR(MP_QSTR_fontSize), MP_ROM_PTR(&display_tft_getFontSize_obj) }, - { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&display_tft_print_obj) }, - { MP_ROM_QSTR(MP_QSTR_orient), MP_ROM_PTR(&display_tft_setRot_obj) }, - { MP_ROM_QSTR(MP_QSTR_textWidth), MP_ROM_PTR(&display_tft_stringWidth_obj) }, - { MP_ROM_QSTR(MP_QSTR_textClear), MP_ROM_PTR(&display_tft_clearStringRect_obj) }, - { MP_ROM_QSTR(MP_QSTR_attrib7seg), MP_ROM_PTR(&display_tft_7segAttrib_obj) }, - { MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&display_tft_Image_obj) }, - { MP_ROM_QSTR(MP_QSTR_gettouch), MP_ROM_PTR(&display_tft_getTouch_obj) }, - { MP_ROM_QSTR(MP_QSTR_compileFont), MP_ROM_PTR(&display_tft_compileFont_obj) }, - { MP_ROM_QSTR(MP_QSTR_hsb2rgb), MP_ROM_PTR(&display_tft_HSBtoRGB_obj) }, - { MP_ROM_QSTR(MP_QSTR_setwin), MP_ROM_PTR(&display_tft_setclipwin_obj) }, - { MP_ROM_QSTR(MP_QSTR_resetwin), MP_ROM_PTR(&display_tft_resetclipwin_obj) }, - { MP_ROM_QSTR(MP_QSTR_savewin), MP_ROM_PTR(&display_tft_saveclipwin_obj) }, - { MP_ROM_QSTR(MP_QSTR_restorewin), MP_ROM_PTR(&display_tft_restoreclipwin_obj) }, - { MP_ROM_QSTR(MP_QSTR_screensize), MP_ROM_PTR(&display_tft_getSize_obj) }, - { MP_ROM_QSTR(MP_QSTR_winsize), MP_ROM_PTR(&display_tft_getWinSize_obj) }, - { MP_ROM_QSTR(MP_QSTR_setCalib), MP_ROM_PTR(&display_tft_setCalib_obj) }, - { MP_ROM_QSTR(MP_QSTR_getCalib), MP_ROM_PTR(&display_tft_getCalib_obj) }, - { MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&display_tft_backlight_obj) }, - { MP_ROM_QSTR(MP_QSTR_getTouchType), MP_ROM_PTR(&display_tft_touch_type_obj) }, - - { MP_ROM_QSTR(MP_QSTR_tft_setspeed), MP_ROM_PTR(&display_tft_set_speed_obj) }, - { MP_ROM_QSTR(MP_QSTR_tft_select), MP_ROM_PTR(&display_tft_select_obj) }, - { MP_ROM_QSTR(MP_QSTR_tft_deselect), MP_ROM_PTR(&display_tft_deselect_obj) }, - { MP_ROM_QSTR(MP_QSTR_tft_writecmd), MP_ROM_PTR(&display_tft_send_command_obj) }, - { MP_ROM_QSTR(MP_QSTR_tft_writecmddata), MP_ROM_PTR(&display_tft_send_cmd_data_obj) }, - { MP_ROM_QSTR(MP_QSTR_tft_readcmd), MP_ROM_PTR(&display_tft_cmd_read_obj) }, - - // class constants - { MP_ROM_QSTR(MP_QSTR_ST7789), MP_ROM_INT(DISP_TYPE_ST7789V) }, - { MP_ROM_QSTR(MP_QSTR_ILI9341), MP_ROM_INT(DISP_TYPE_ILI9341) }, - { MP_ROM_QSTR(MP_QSTR_ILI9488), MP_ROM_INT(DISP_TYPE_ILI9488) }, - { MP_ROM_QSTR(MP_QSTR_ST7735), MP_ROM_INT(DISP_TYPE_ST7735) }, - { MP_ROM_QSTR(MP_QSTR_ST7735R), MP_ROM_INT(DISP_TYPE_ST7735R) }, - { MP_ROM_QSTR(MP_QSTR_ST7735B), MP_ROM_INT(DISP_TYPE_ST7735B) }, - { MP_ROM_QSTR(MP_QSTR_M5STACK), MP_ROM_INT(DISP_TYPE_M5STACK) }, - { MP_ROM_QSTR(MP_QSTR_GENERIC), MP_ROM_INT(DISP_TYPE_GENERIC) }, - - { MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(CENTER) }, - { MP_ROM_QSTR(MP_QSTR_RIGHT), MP_ROM_INT(RIGHT) }, - { MP_ROM_QSTR(MP_QSTR_BOTTOM), MP_ROM_INT(BOTTOM) }, - { MP_ROM_QSTR(MP_QSTR_LASTX), MP_ROM_INT(LASTX) }, - { MP_ROM_QSTR(MP_QSTR_LASTY), MP_ROM_INT(LASTY) }, - - { MP_ROM_QSTR(MP_QSTR_PORTRAIT), MP_ROM_INT(PORTRAIT) }, - { MP_ROM_QSTR(MP_QSTR_LANDSCAPE), MP_ROM_INT(LANDSCAPE) }, - { MP_ROM_QSTR(MP_QSTR_PORTRAIT_FLIP), MP_ROM_INT(PORTRAIT_FLIP) }, - { MP_ROM_QSTR(MP_QSTR_LANDSCAPE_FLIP), MP_ROM_INT(LANDSCAPE_FLIP) }, - - { MP_ROM_QSTR(MP_QSTR_FONT_Default), MP_ROM_INT(DEFAULT_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_DejaVu18), MP_ROM_INT(DEJAVU18_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_DejaVu24), MP_ROM_INT(DEJAVU24_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_Ubuntu), MP_ROM_INT(UBUNTU16_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_Comic), MP_ROM_INT(COMIC24_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_Minya), MP_ROM_INT(MINYA24_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_Tooney), MP_ROM_INT(TOONEY32_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_Small), MP_ROM_INT(SMALL_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_DefaultSmall), MP_ROM_INT(DEF_SMALL_FONT) }, - { MP_ROM_QSTR(MP_QSTR_FONT_7seg), MP_ROM_INT(FONT_7SEG) }, - - { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(iTFT_BLACK) }, - { MP_ROM_QSTR(MP_QSTR_NAVY), MP_ROM_INT(iTFT_NAVY) }, - { MP_ROM_QSTR(MP_QSTR_DARKGREEN), MP_ROM_INT(iTFT_DARKGREEN) }, - { MP_ROM_QSTR(MP_QSTR_DARKCYAN), MP_ROM_INT(iTFT_DARKCYAN) }, - { MP_ROM_QSTR(MP_QSTR_MAROON), MP_ROM_INT(iTFT_MAROON) }, - { MP_ROM_QSTR(MP_QSTR_PURPLE), MP_ROM_INT(iTFT_PURPLE) }, - { MP_ROM_QSTR(MP_QSTR_OLIVE), MP_ROM_INT(iTFT_OLIVE) }, - { MP_ROM_QSTR(MP_QSTR_LIGHTGREY), MP_ROM_INT(iTFT_LIGHTGREY) }, - { MP_ROM_QSTR(MP_QSTR_DARKGREY), MP_ROM_INT(iTFT_DARKGREY) }, - { MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(iTFT_BLUE) }, - { MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(iTFT_GREEN) }, - { MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(iTFT_CYAN) }, - { MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(iTFT_RED) }, - { MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(iTFT_MAGENTA) }, - { MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(iTFT_YELLOW) }, - { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(iTFT_WHITE) }, - { MP_ROM_QSTR(MP_QSTR_ORANGE), MP_ROM_INT(iTFT_ORANGE) }, - { MP_ROM_QSTR(MP_QSTR_GREENYELLOW), MP_ROM_INT(iTFT_GREENYELLOW) }, - { MP_ROM_QSTR(MP_QSTR_PINK), MP_ROM_INT(iTFT_PINK) }, - - { MP_ROM_QSTR(MP_QSTR_COLOR_BITS16), MP_ROM_INT(16) }, - { MP_ROM_QSTR(MP_QSTR_COLOR_BITS24), MP_ROM_INT(24) }, - - { MP_ROM_QSTR(MP_QSTR_JPG), MP_ROM_INT(IMAGE_TYPE_JPG) }, - { MP_ROM_QSTR(MP_QSTR_BMP), MP_ROM_INT(IMAGE_TYPE_BMP) }, - - { MP_ROM_QSTR(MP_QSTR_HSPI), MP_ROM_INT(HSPI_HOST) }, - { MP_ROM_QSTR(MP_QSTR_VSPI), MP_ROM_INT(VSPI_HOST) }, - - { MP_ROM_QSTR(MP_QSTR_TOUCH_NONE), MP_ROM_INT(TOUCH_TYPE_NONE) }, - { MP_ROM_QSTR(MP_QSTR_TOUCH_XPT), MP_ROM_INT(TOUCH_TYPE_XPT2046) }, - { MP_ROM_QSTR(MP_QSTR_TOUCH_STMPE), MP_ROM_INT(TOUCH_TYPE_STMPE610) }, -}; -STATIC MP_DEFINE_CONST_DICT(display_tft_locals_dict, display_tft_locals_dict_table); - -//====================================== -const mp_obj_type_t display_tft_type = { - { &mp_type_type }, - .name = MP_QSTR_TFT, - .print = display_tft_printinfo, - .make_new = display_tft_make_new, - .locals_dict = (mp_obj_t)&display_tft_locals_dict, -}; +#ifdef CONFIG_MICROPY_USE_TFT +extern const mp_obj_type_t display_tft_type; +#endif +#ifdef CONFIG_MICROPY_USE_EVE +extern const mp_obj_type_t display_eve_type; +#endif //=============================================================== STATIC const mp_rom_map_elem_t display_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_display) }, + #ifdef CONFIG_MICROPY_USE_TFT { MP_OBJ_NEW_QSTR(MP_QSTR_TFT), MP_ROM_PTR(&display_tft_type) }, + #endif + #ifdef CONFIG_MICROPY_USE_EVE + { MP_OBJ_NEW_QSTR(MP_QSTR_EVE), MP_ROM_PTR(&display_eve_type) }, + #endif }; //=============================================================================== @@ -1592,3 +63,4 @@ const mp_obj_module_t mp_module_display = { .globals = (mp_obj_dict_t*)&display_module_globals, }; +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/moddisplay_eve.c b/MicroPython_BUILD/components/micropython/esp32/moddisplay_eve.c new file mode 100644 index 00000000..bbc5c383 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/moddisplay_eve.c @@ -0,0 +1,4461 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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 "sdkconfig.h" + +#if CONFIG_MICROPY_USE_EVE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" +#include "esp_task_wdt.h" +#include "esp_log.h" + +#include "py/obj.h" +#include "py/objarray.h" + +#include "driver/gpio.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "mphalport.h" +#include "tft/tft.h" +#include "moddisplay_tft.h" +#include "eve/FT8.h" + + +#define FT8_ENABLE_PNG_LOADING 1 +#define IMAGE_TYPE_PNG 0 +#define IMAGE_TYPE_JPG 1 +#define IMAGE_TYPE_RAW 2 +#define IMAGE_TYPE_BIN 3 +#define IMAGE_TYPE_NONE 4 + +typedef struct _display_eve_obj_t { + mp_obj_base_t base; + machine_hw_spi_obj_t *spi; + eve_config_t dconfig; + exspi_device_handle_t disp_spi_dev; + exspi_device_handle_t *disp_spi; + uint16_t width; + uint16_t height; + uint8_t in_list; +} display_eve_obj_t; + +typedef struct _eve_font_metrics_t { + uint8_t widths[EVE_FONT_WIDTHS_SIZE]; + uint32_t format; + uint32_t stride; + uint32_t width; + uint32_t height; + int32_t ptr; +} eve_font_metrics_t; + +typedef struct _font_eve_obj_t { + mp_obj_base_t base; + uint32_t addr; + uint32_t size; + eve_font_metrics_t metrics; + uint8_t handle; + uint8_t format; + uint8_t maxwidth; + uint8_t minwidth; + uint8_t nchars; + uint8_t firstc; + uint8_t loaded; +} font_eve_obj_t; + +typedef struct _image_eve_obj_t { + mp_obj_base_t base; + uint32_t addr; + uint32_t size; + uint16_t width; + uint16_t height; + uint8_t format; + uint8_t orig_fmt; + uint8_t loaded; +} image_eve_obj_t; + +typedef struct _console_eve_obj_t { + mp_obj_base_t base; + uint32_t addr; + uint32_t size; + uint32_t curr_addr; + uint16_t x; + uint16_t y; + uint16_t width; + uint16_t height; + uint16_t rowbytes; + mp_float_t scale; + uint32_t fgcolor; + uint32_t bgcolor; + uint8_t vgacolor; + uint8_t rowspace; + uint8_t type; + uint8_t show_cursor; + uint8_t wrap; + uint8_t loaded; +} console_eve_obj_t; + +typedef struct _list_eve_obj_t { + mp_obj_base_t base; + uint32_t addr; + uint32_t size; + uint8_t loaded; +} list_eve_obj_t; + +typedef struct _ramg_objects_t { + uint16_t count; + uint16_t size; + void **objects; +} ramg_objects_t; + +const mp_obj_type_t display_eve_type; +const mp_obj_type_t font_eve_type; +const mp_obj_type_t image_eve_type; +const mp_obj_type_t list_eve_type; +const mp_obj_type_t console_eve_type; +const mp_obj_type_t tft_eve_type; + +static display_eve_obj_t *eve_obj = NULL; +static font_eve_obj_t *user_fonts[MAX_USER_FONTS] = {NULL}; +static ramg_objects_t ramg_objects = {0, 0, NULL}; +static uint16_t eve_cmd_start_addr = 0; +static int16_t loaded_lists = 0; +static int16_t loaded_images = 0; +static int16_t loaded_fonts = 0; + +extern uint8_t disp_used_spi_host; + +static const char* const ft8_prim[] = { + "BITMAPS", + "POINTS", + "LINES", + "LINE_STRIP", + "EDGE_STRIP_R", + "EDGE_STRIP_L", + "EDGE_STRIP_A", + "EDGE_STRIP_B", + "RECTS", + "?", +}; + +static const char* const ft8_imgtypes[] = { + "PNG", + "JPEG", + "RAW_COMPRESSED", + "RAW", +}; + +static const char* const ft8_bmp_formats[] = { + "ARGB1555", + "L1", + "L4", + "L8", + "RGB332", + "ARGB2", + "ARGB4", + "RGB565", + "PALETTED", + "TEXT8X8", + "TEXTVGA", + "BARGRAPH", +}; + +static const char TAG[] = "[ModEve]"; +static const uint8_t stride_factor[18] = {0, 4, 2, 1, 1, 1, 0, 0, 16, 1, 0, 1, 16, 16, 1, 1, 1, 3 }; + +//------------------------------------------------------------ +static int _check_jpeg(uint8_t *data, int *width, int *height) +{ + int tmp; + int idx = 0; + tmp = (data[idx]<<8) | data[idx+1]; + if (tmp != 0xFFD8) return -1; + idx += 2; + tmp = (data[idx]<<8) | data[idx+1]; + if (tmp != 0xFFE0) return -2; + idx += 2; + tmp = (data[idx]<<8) | data[idx+1]; // size + idx += 2; + if (memcmp(data+idx, "JFIF", 4)) return -3; + idx += (tmp-2); + + // segment + do { + if (data[idx] != 0xFF) return -4; + tmp = (data[idx]<<8) | data[idx+1]; + if (tmp == 0xFFC0) break; + idx += 2; + tmp = (data[idx]<<8) | data[idx+1]; // size + idx += tmp; + } while (idx < (254)); + + if (tmp != 0xFFC0) return -5; + if ((idx+8) > 256) return -6; + // get width and height + idx += 4; + if (data[idx] != 8) return -7; + idx++; + *height = (data[idx]<<8) | data[idx+1]; + idx += 2; + *width = (data[idx]<<8) | data[idx+1]; + return 0; +} + +#if FT8_ENABLE_PNG_LOADING +//------------------------------------------------------------ +static int _check_png(uint8_t *data, int *width, int *height) +{ + int idx = 0; + if (memcmp(data, "\x89PNG\x0d\x0a\x1a\x0a", 8)) return -1; + idx += 12; + if (memcmp(data+idx, "IHDR", 4)) return -2; + idx += 6; + *width = (data[idx] << 8) | data[idx+1]; + idx += 4; + *height = (data[idx] << 8) | data[idx+1]; + idx += 2; + if (data[idx] != 8) return -3; // only bit depth 8 is supported + idx++; + if (data[idx] == 4) return -4; // Grayscale and alpha not supported + return data[idx]; +} +#endif + +#ifdef CONFIG_EVE_CHIP_TYPE1 +//--------------------------------------------------------------------------------------- +static int _check_avi(uint8_t *data, int *width, int *height, int* playtime, int *frames) +{ + int idx = 0; + if (memcmp(data, "RIFF", 4)) return -1; + idx = 8; + if (memcmp(data+idx, "AVI ", 4)) return -2; + if ((memcmp(data+108, "vidsMJPG", 8)) && (memcmp(data+108, "vidsmjpg", 8))) return -3; + memcpy(width, data+64, 4); + memcpy(height, data+68, 4); + uint32_t sec_between_frames, total_frames; + memcpy(&sec_between_frames, data+32, 4); + memcpy(&total_frames, data+48, 4); + uint64_t time = total_frames * sec_between_frames; + *playtime = time / 1000000; + *frames = total_frames; + + return 0; +} +#endif + +//------------------------------------------------------ +STATIC void spi_deinit_internal(display_eve_obj_t *self) +{ + if (self->disp_spi->handle) { + esp_err_t ret; + // Deinitialize display spi device(s) + ret = remove_extspi_device(self->disp_spi); + if (ret != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Error removing display device"); + } + + gpio_pad_select_gpio(self->dconfig.miso); + gpio_pad_select_gpio(self->dconfig.mosi); + gpio_pad_select_gpio(self->dconfig.sck); + + eve_spibus_is_init = 0; + spi_is_init = 0; + eve_obj = NULL; + } +} + +//----------------------------------- +static bool check_ramg(uint32_t size) +{ + if ((ft8_ramg_ptr+size) > (FT8_RAM_G_SIZE)) return false; + return true; +} + +//------------------------------------ +static bool add_ramg_object(void *obj) +{ + if (ramg_objects.count == ramg_objects.size) return false; + + void **obj_pos = ramg_objects.objects + (ramg_objects.count*sizeof(void*)); + *obj_pos = obj; + ramg_objects.count++; + obj_pos += sizeof(void*); + if (ramg_objects.count == ramg_objects.size) { + // add space for 16 new objects + void **tmp_ptr = realloc(ramg_objects.objects, (ramg_objects.size+16)*sizeof(void*)); + if (tmp_ptr) { + ramg_objects.objects = tmp_ptr; + ramg_objects.size += 16; + memset(obj_pos, 0, 16*sizeof(void*)); + } + } + return true; +} + +//--------------------------------------------------------------------------- +static void adjust_ramg_objects(void *this_obj, uint32_t addr, uint32_t size) +{ + void **obj_pos; + // delete this object + for (int i=0; i 0)memcpy(obj_pos, obj_pos+sizeof(void*), sizeof(ramg_objects_t) * obj_after_count); + // delete the last object + memset(ramg_objects.objects + (sizeof(void*) * (ramg_objects.count-1)), 0, sizeof(ramg_objects_t)); + ramg_objects.count--; + break; + } + } + // adjust the RAM_G addresses of the remaining objects + for (int i=0; itype == &font_eve_type) { + font_eve_obj_t *obj = (font_eve_obj_t *)ptr; + if (obj->addr > addr) { + obj->addr -= size; + obj->metrics.ptr -= size; + } + } + else if (base->type == &image_eve_type) { + image_eve_obj_t *obj = (image_eve_obj_t *)ptr; + if (obj->addr > addr) { + obj->addr -= size; + } + } + else if (base->type == &list_eve_type) { + list_eve_obj_t *obj = (list_eve_obj_t *)ptr; + if (obj->addr > addr) { + obj->addr -= size; + } + } + else if (base->type == &console_eve_type) { + console_eve_obj_t *obj = (console_eve_obj_t *)ptr; + if (obj->addr > addr) { + obj->addr -= size; + } + } + #ifdef CONFIG_MICROPY_USE_TFT + else if (base->type == &tft_eve_type) { + tft_eve_obj_t *obj = (tft_eve_obj_t *)ptr; + if (obj->addr > addr) { + obj->addr -= size; + } + } + #endif + } + } +} + +//------------------------------------------------ +static void print_objects(const mp_print_t *print) +{ + if (ramg_objects.count == 0) return; + void **obj_pos; + for (int i=0; itype == &font_eve_type) { + font_eve_obj_t *obj = (font_eve_obj_t *)ptr; + mp_printf(print, " %2d: Font, addr=%u, size=%u\n", i, obj->addr,obj->size); + } + else if (base->type == &image_eve_type) { + image_eve_obj_t *obj = (image_eve_obj_t *)ptr; + mp_printf(print, " %2d: Image, addr=%u, size=%u\n", i, obj->addr,obj->size); + } + else if (base->type == &list_eve_type) { + list_eve_obj_t *obj = (list_eve_obj_t *)ptr; + mp_printf(print, " %2d: List, addr=%u, size=%u\n", i, obj->addr,obj->size); + } + else if (base->type == &console_eve_type) { + console_eve_obj_t *obj = (console_eve_obj_t *)ptr; + mp_printf(print, " %2d: Console, addr=%u, size=%u\n", i, obj->addr,obj->size); + } + #ifdef CONFIG_MICROPY_USE_TFT + else if (base->type == &tft_eve_type) { + tft_eve_obj_t *obj = (tft_eve_obj_t *)ptr; + mp_printf(print, " %2d: Tft, addr=%u, size=%u\n", i, obj->addr,obj->size); + } + #endif + else { + mp_printf(print, " %2d: Unknown object type\n", i); + } + } + } +} + +//----------------------------------------------------------------------------------------------- +STATIC void display_eve_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + display_eve_obj_t *self = self_in; + if (self->disp_spi->handle) { + if (eve_chip_id > 0) { + mp_printf(print, "EVE ( %dx%d, Type=FT%X, Ready: %s, Clk=%u Hz\n", + self->width, self->height, eve_chip_id, ((self->disp_spi->handle) ? "yes" : "no"), self->dconfig.speed); + mp_printf(print, " Pins: miso=%d, mosi=%d, clk=%d, cs=%d, pd=%d\n", self->dconfig.miso, self->dconfig.mosi, self->dconfig.sck, self->dconfig.cs, self->dconfig.pd); + mp_printf(print, " Free Objects RAM: %u (%u used)\n", FT8_RAM_G+FT8_RAM_G_SIZE-ft8_ramg_ptr, ft8_ramg_ptr); + mp_printf(print, " Loaded objects: fonts=%d, images=%d, lists=%d\n", loaded_fonts, loaded_images, loaded_lists); + print_objects(print); + mp_printf(print, " )"); + } + else { + mp_printf(print, "EVE ( FT8xx not detected )"); + } + } + else { + mp_printf(print, "EVE ( Not initialized )"); + } +} + +//--------------------------------------------------------------------------------------------- +STATIC void font_eve_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + font_eve_obj_t *self = self_in; + if (self->loaded) { + mp_printf(print, "EVE_FONT ( handle=%d )\n", self->handle); + mp_printf(print, " Format: L%d\n", self->format); + mp_printf(print, " Stride: %d\n", self->metrics.stride); + mp_printf(print, " Font width: %d\n", self->metrics.width); + mp_printf(print, " Font height: %d\n", self->metrics.height); + mp_printf(print, " Max char width: %d\n", self->maxwidth); + mp_printf(print, " Min char width: %d\n", self->minwidth); + mp_printf(print, " RAM_G address: %u\n", self->addr); + mp_printf(print, " RAM_G size: %u\n", self->size); + mp_printf(print, " Data addr: %d\n", self->metrics.ptr); + mp_printf(print, " Number of chars: %d\n", self->nchars); + mp_printf(print, " First char: %d\n", self->firstc); + } + else { + mp_printf(print, "EVE_FONT ( Unloaded )"); + } +} + +//---------------------------------------------------------------------------------------------- +STATIC void image_eve_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + image_eve_obj_t *self = self_in; + if (self->loaded) { + mp_printf(print, "EVE_IMAGE ( format=%s (from %s), addr=%u, size=%u, w=%d, h=%d )", + ft8_bmp_formats[self->format], ft8_imgtypes[self->orig_fmt], self->addr, self->size, self->width, self->height); + } + else { + mp_printf(print, "EVE_IMAGE ( Unloaded )"); + } +} + +//--------------------------------------------------------------------------------------------- +STATIC void list_eve_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + list_eve_obj_t *self = self_in; + if (self->loaded) { + mp_printf(print, "EVE_LIST ( addr=%u, size=%u )", self->addr, self->size); + } + else { + mp_printf(print, "EVE_LIST ( Unloaded )"); + } +} + +//------------------------------------------------------------------------------------------------ +STATIC void console_eve_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + console_eve_obj_t *self = self_in; + if (self->loaded) { + mp_printf(print, "EVE_CONSOLE_%s [%d * %d] ( addr=%u, size=%u, cursor: (%d,%d), row space=%d, scale=%1.2f )", + (self->type == FT8_TEXT8X8) ? "8x8" : "VGA", self->width, self->height, self->addr, self->size, self->x, self->y, self->rowspace, self->scale); + } + else { + mp_printf(print, "EVE_CONSOLE ( Unloaded )"); + } +} + +#ifdef CONFIG_MICROPY_USE_TFT +//-------------------------------------------------------------------------------------------- +STATIC void tft_eve_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + tft_eve_obj_t *self = self_in; + if (self->loaded) { + mp_printf(print, "EVE_TFT_%s [%d * %d] ( addr=%u, size=%u )", + (self->type == FT8_RGB565) ? "RGB565" : "RGB332", self->width, self->height, self->addr, self->size); + } + else { + mp_printf(print, "EVE_TFT ( Unloaded )"); + } +} +#endif + +//-------------------------------------------- +static esp_err_t _EVE_calibrate(bool nvs_read) +{ + uint32_t cal_const = 0; + char calibs[16]; + esp_err_t err; + + if (nvs_read) { + // Get calibration values from NVS + if (mpy_nvs_handle == 0) err = ESP_FAIL; + for (int i=0; i<6; i++) { + sprintf(calibs, "eve_calib_%c", (char)(i+0x61)); + err = nvs_get_u32(mpy_nvs_handle, calibs, &cal_const); + if (err != ESP_OK) break; + FT8_memWrite32(REG_TOUCH_TRANSFORM_A + (i*4), cal_const); + } + return err; + } + + // Perform calibration + FT8_start_cmd_burst(); + FT8_cmd_dl(CMD_DLSTART); + FT8_cmd_dl(DL_CLEAR_RGB | 0x00e0e0e0); + FT8_cmd_dl(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG); + FT8_cmd_dl(DL_COLOR_RGB | 0x00000040); + FT8_cmd_text(400, 240, 28, FT8_OPT_CENTERX, "Please tap on the dot"); + FT8_cmd_calibrate(); + + FT8_cmd_dl(DL_DISPLAY); + FT8_cmd_dl(CMD_SWAP); + + FT8_end_cmd_burst(); + + bool res = FT8_cmd_execute(30000); + + FT8_start_cmd_burst(); + FT8_cmd_dl(CMD_DLSTART); + FT8_cmd_dl(DL_CLEAR_RGB); + FT8_cmd_dl(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG); + if (res) { + FT8_cmd_dl(DL_COLOR_RGB | 0x0000FF00); + FT8_cmd_text(400, 240, 28, FT8_OPT_CENTERX, "Calibration OK"); + } + else { + FT8_cmd_dl(DL_COLOR_RGB | 0x0000FF00); + FT8_cmd_text(400, 240, 28, FT8_OPT_CENTERX, "Calibration failed"); + } + FT8_cmd_dl(DL_DISPLAY); + FT8_cmd_dl(CMD_SWAP); + FT8_end_cmd_burst(); + FT8_cmd_execute(250); + + err = ESP_OK; + if (res) { + // Save calibration constants to NVS + for (int i=0; i<6; i++) { + cal_const = FT8_memRead32(REG_TOUCH_TRANSFORM_A + (i*4)); + sprintf(calibs, "eve_calib_%c", (char)(i+0x61)); + err = nvs_set_u32(mpy_nvs_handle, calibs, cal_const); + if (err != ESP_OK) break; + nvs_commit(mpy_nvs_handle); + } + } + + return err; +} + +#ifdef CONFIG_EVE_CHIP_TYPE1 +//------------------------------------------------------- +static void _eve_rotate(display_eve_obj_t *self, int rot) +{ + FT8_start_cmd_burst(); + FT8_cmd_dl(CMD_DLSTART); + FT8_cmd_setrotate(rot); + FT8_cmd_dl(DL_DISPLAY); + FT8_end_cmd_burst(); + FT8_cmd_execute(250); + + if ((rot & 2)) { + // portrait, invert width/heigth + self->width = self->dconfig.height; + self->height = self->dconfig.width; + } + else { + // landscape + self->width = self->dconfig.width; + self->height = self->dconfig.height; + } +} +#endif + +// === EVE object constructor === +//--------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_eve_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) +{ + if (eve_obj) { + mp_raise_msg(&mp_type_OSError, "EVE object instance already exists!"); + } + display_eve_obj_t *self = m_new_obj(display_eve_obj_t); + memset(self, 0, sizeof(display_eve_obj_t)); + self->base.type = &display_eve_type; + self->spi = NULL; + self->disp_spi_dev.handle = NULL; + self->disp_spi_dev.cs = -1; + self->disp_spi_dev.dc = -1; + self->disp_spi_dev.selected = 0; + self->disp_spi = &self->disp_spi_dev; + eve_spi = NULL; + memset(user_fonts, 0, sizeof(user_fonts)); + ft8_ramg_ptr = FT8_RAM_G; + //list_ptr = EVE_STATIC_LIST; + ramg_objects.count = 0; + ramg_objects.size = 0; + if (ramg_objects.objects == NULL) { + ramg_objects.objects = malloc(16 * sizeof(uint32_t)); + if (ramg_objects.objects == NULL) { + mp_raise_msg(&mp_type_OSError, "Error creating EVE instance"); + } + } + ramg_objects.size = 16; + loaded_lists = 0; + loaded_images = 0; + eve_chip_id = 0; + eve_obj = self; + + return MP_OBJ_FROM_PTR(self); +} + +// ToDo: Change this +// -------------------- +static void _eve_logo() +{ + FT8_start_cmd_burst(); // start writing to the cmd-fifo as one stream of bytes, only sending the address once + FT8_cmd_dl(CMD_DLSTART); // start the display list + FT8_cmd_dl(CMD_LOGO); + FT8_cmd_dl(DL_DISPLAY); // End the display list. FT81X will ignore all the commands following this command. + FT8_cmd_dl(CMD_SWAP); // make this list active + FT8_end_cmd_burst(); // stop writing to the cmd-fifo + FT8_cmd_start(); + vTaskDelay(2500 / portTICK_RATE_MS); + + // Wait till both read & write pointer register are equal to zero + uint16_t wr, rd; + do { + wr = FT8_memRead16(REG_CMD_WRITE); + rd = FT8_memRead16(REG_CMD_READ); + } while ((wr != 0) && (wr != rd)); + FT8_get_cmdoffset(); +} + +//------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_eve_config(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_hsize, ARG_vsize, ARG_vsync0, ARG_vsync1, ARG_voffset, ARG_vcycle, ARG_hsync0, ARG_hsync1, ARG_hoffset, ARG_hcycle, ARG_pclkpol, ARG_swizzle, ARG_pclk, ARG_cspread, ARG_rzthresh, ARG_hascrystal,ARG_hasgt911 }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_hsize, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 800 } }, + { MP_QSTR_vsize, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 480 } }, + { MP_QSTR_vsync0, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_vsync1, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 2 } }, + { MP_QSTR_voffset, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 13 } }, + { MP_QSTR_vcycle, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 525 } }, + { MP_QSTR_hsync0, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_hsync1, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 20 } }, + { MP_QSTR_hoffset, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 64 } }, + { MP_QSTR_hcycle, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 952 } }, + + { MP_QSTR_pclkpol, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 1 } }, + { MP_QSTR_swizzle, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_pclk, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 2 } }, + { MP_QSTR_cspread, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_rzthresh, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 2000 } }, + { MP_QSTR_hascrystal, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = true } }, + { MP_QSTR_hasgt911, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + + self->dconfig.disp_config.hsize = args[ARG_hsize].u_int; + self->dconfig.disp_config.vsize = args[ARG_vsize].u_int; + self->dconfig.disp_config.vsync0 = args[ARG_vsync0].u_int; + self->dconfig.disp_config.vsync1 = args[ARG_vsync1].u_int; + self->dconfig.disp_config.voffset = args[ARG_voffset].u_int; + self->dconfig.disp_config.vcycle = args[ARG_vcycle].u_int; + self->dconfig.disp_config.hsync0 = args[ARG_hsync0].u_int; + self->dconfig.disp_config.hsync1 = args[ARG_hsync1].u_int; + self->dconfig.disp_config.hoffset = args[ARG_hoffset].u_int; + self->dconfig.disp_config.hcycle = args[ARG_hcycle].u_int; + self->dconfig.disp_config.pclkpol = args[ARG_pclkpol].u_int; + self->dconfig.disp_config.swizzle = args[ARG_swizzle].u_int; + self->dconfig.disp_config.pclk = args[ARG_pclk].u_int; + self->dconfig.disp_config.cspread = args[ARG_cspread].u_int; + self->dconfig.disp_config.touch_thresh = args[ARG_rzthresh].u_int; + self->dconfig.disp_config.has_crystal = args[ARG_hascrystal].u_bool; + self->dconfig.disp_config.has_GT911 = args[ARG_hasgt911].u_bool; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_eve_config_obj, 0, display_eve_config); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_eve_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_host, ARG_width, ARG_height, ARG_speed, ARG_miso, ARG_mosi, ARG_clk, ARG_cs, ARG_pd, ARG_rot, ARG_splash }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_spihost, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = HSPI_HOST } }, + { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 800 } }, + { MP_QSTR_height, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 480 } }, + { MP_QSTR_speed, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 10000000 } }, + { MP_QSTR_miso, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_mosi, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_clk, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_cs, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_pd, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_rot, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_splash, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + esp_err_t ret; + + #ifdef CONFIG_FT8_USER_TYPE + + if ((self->dconfig.disp_config.hsize == 0) || (self->dconfig.disp_config.vsize == 0)) { + mp_raise_ValueError("EVE display not configured"); + } + + #else + + #if defined (FT8_HAS_CRYSTAL) + self->dconfig.disp_config.has_crystal = 1; + #else + self->dconfig.disp_config.has_crystal = 0; + #endif + #if defined (FT8_HAS_GT911) + self->dconfig.disp_config.has_GT911 = 1; + #else + self->dconfig.disp_config.has_GT911 = 0; + #endif + self->dconfig.disp_config.cspread = FT8_CSPREAD; + self->dconfig.disp_config.hcycle = FT8_HCYCLE; + self->dconfig.disp_config.hoffset = FT8_HOFFSET; + self->dconfig.disp_config.hsize = FT8_HSIZE; + self->dconfig.disp_config.hsync0 = FT8_HSYNC0; + self->dconfig.disp_config.hsync1 = FT8_HSYNC1; + self->dconfig.disp_config.pclk = FT8_PCLK; + self->dconfig.disp_config.pclkpol = FT8_PCLKPOL; + self->dconfig.disp_config.swizzle = FT8_SWIZZLE; + self->dconfig.disp_config.touch_thresh = FT8_TOUCH_RZTHRESH; + self->dconfig.disp_config.vcycle = FT8_VCYCLE; + self->dconfig.disp_config.voffset = FT8_VOFFSET; + self->dconfig.disp_config.vsize = FT8_VSIZE; + self->dconfig.disp_config.vsync0 = FT8_VSYNC0; + self->dconfig.disp_config.vsync1 = FT8_VSYNC1; + + self->dconfig.height = FT8_HSIZE; + self->dconfig.width = FT8_VSIZE; + #endif + + // === deinitialize display spi device if it was initialized === + if (self->disp_spi->handle) spi_deinit_internal(self); + + // === Get arguments === + if ((args[ARG_host].u_int != HSPI_HOST) && (args[ARG_host].u_int != VSPI_HOST)) { + mp_raise_ValueError("SPI host must be either HSPI(1) or VSPI(2)"); + } + if ((SPIbus_configs[VSPI_HOST] == NULL) && (args[ARG_host].u_int == VSPI_HOST)) { + mp_raise_ValueError("SPI host must be HSPI(1), VSPI(2) used by SPIRAM"); + } + + self->dconfig.host = args[ARG_host].u_int; + self->dconfig.width = args[ARG_width].u_int; // native display width + self->dconfig.height = args[ARG_height].u_int; // native display height + self->width = self->dconfig.width; + self->height = self->dconfig.height; + + self->dconfig.pd = args[ARG_pd].u_int; + + self->dconfig.miso = args[ARG_miso].u_int; + self->dconfig.mosi = args[ARG_mosi].u_int; + self->dconfig.sck = args[ARG_clk].u_int; + + self->dconfig.cs = args[ARG_cs].u_int; + + // ================================ + // ==== Initialize the Display ==== + ret = FT8_init(&self->dconfig, self->disp_spi); + if (ret != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Error initializing display"); + } + + disp_used_spi_host = args[ARG_host].u_int; + + // ==== Set SPI clock used for display operations ==== + self->dconfig.speed = spi_set_speed(self->disp_spi, args[ARG_speed].u_int); + + if (args[ARG_splash].u_bool) { + _eve_logo(); + } + + ret = _EVE_calibrate(true); + if (ret != ESP_OK) ret = _EVE_calibrate(false); + + if (ret == ESP_OK) { + #ifdef CONFIG_EVE_CHIP_TYPE1 + if (args[ARG_rot].u_int >= 0) { + _eve_rotate(self, args[ARG_rot].u_int & 7); + } + #endif + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_eve_init_obj, 0, display_eve_init); + + +// Check if EVE object is initialized +// and if the functions can be executed in current context +//---------------------------------------------------------- +static void _check_inlist(display_eve_obj_t *self, uint8_t f) +{ + if ((eve_obj == NULL) || (eve_chip_id == 0) || (self->disp_spi->handle == NULL)) { + mp_raise_msg(&mp_type_OSError, "EVE object not initialized!"); + } + if ((f == 0) && (self->in_list)) { + mp_raise_ValueError("Can only be used outside display list"); + } + else if ((f == 1) && (self->in_list == 0)) { + mp_raise_ValueError("Display list not started"); + } +} + +// --------------------------------------------------------------- +STATIC mp_obj_t EVE_calibrate(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 0); + + esp_err_t err; + + if ((n_args > 1) && (mp_obj_is_true(args[1]))) { + err = _EVE_calibrate(true); + if (err == ESP_OK) return mp_const_true; + return mp_const_false; + } + + err = _EVE_calibrate(false); + + if (err == ESP_OK) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_calibrate_obj, 1, 2, EVE_calibrate); + + +#ifdef CONFIG_EVE_CHIP_TYPE1 +// ---------------------------------------------------------- +STATIC mp_obj_t EVE_rotate(mp_obj_t self_in, mp_obj_t rot_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + int rot = mp_obj_get_int(rot_in); + if ((rot < 0) || (rot > 7)) { + mp_raise_ValueError("Invalid rotation value"); + } + _eve_rotate(self, rot); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_rotate_obj, EVE_rotate); +#endif + +// Start creating display list +// -------------------------------------------- +STATIC mp_obj_t EVE_startlist(mp_obj_t self_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + FT8_CP_reset(); + FT8_memWrite32(REG_CMD_DL, 0); + + eve_cmd_start_addr = eve_cmdOffset; + FT8_start_cmd_burst(); // start writing to the cmd-fifo as one stream of bytes, only sending the address once + FT8_cmd_dl(CMD_DLSTART); // start the display list + //FT8_cmd_dl(CMD_COLDSTART); + self->in_list = 1; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_startlist_obj, EVE_startlist); + +// End display list, make it active and show on display +// ----------------------------------------- +STATIC mp_obj_t EVE_endlist(mp_obj_t self_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + FT8_cmd_dl(DL_DISPLAY); // End the display list. FT81X will ignore all the commands following this command. + FT8_cmd_dl(CMD_SWAP); // make this list active + + FT8_end_cmd_burst(); // stop writing to the cmd-fifo + bool res = FT8_cmd_execute(250); + self->in_list = 0; + + if (res) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_endlist_obj, EVE_endlist); + +// End the current list and save it to static DL RAM +// Returns List object +// ------------------------------------------- +STATIC mp_obj_t EVE_savelist(mp_obj_t self_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + // Execute current list + FT8_end_cmd_burst(); // stop writing to the cmd-fifo + bool res = FT8_cmd_execute(250); + self->in_list = 0; + if (!res) return mp_const_false; + + // Copy to static list + uint32_t list_size = FT8_memRead32(REG_CMD_DL) & 0x1FFF; + if (!check_ramg(list_size)) { + mp_raise_ValueError("No place to append list"); + } + FT8_cmd_memcpy(ft8_ramg_ptr, FT8_RAM_DL, list_size); + res = FT8_cmd_execute(250); + if (!res) return mp_const_false; + + // Create LIST instance object + list_eve_obj_t *list_obj = m_new_obj(list_eve_obj_t); + memset(list_obj, 0, sizeof(list_eve_obj_t)); + list_obj->base.type = &list_eve_type; + + list_obj->addr = ft8_ramg_ptr; + list_obj->size = list_size; + list_obj->loaded = 1; + + if (!add_ramg_object((void *)list_obj)) { + mp_raise_ValueError("Error adding ramg object"); + } + ft8_ramg_ptr += list_size; + loaded_lists++; + + return MP_OBJ_FROM_PTR(list_obj); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_savelist_obj, EVE_savelist); + + +// --------------------------------------------------------------- +STATIC mp_obj_t EVE_appendlist(mp_obj_t self_in, mp_obj_t list_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + if (mp_obj_get_type(list_in) != &list_eve_type) { + mp_raise_ValueError("List object expected"); + } + + list_eve_obj_t *list = (list_eve_obj_t *)(list_in); + if (list->loaded == 0) { + mp_raise_ValueError("List unloaded"); + } + + FT8_cmd_append(list->addr, list->size); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_appendlist_obj, EVE_appendlist); + +// ----------------------------------------------------------- +STATIC mp_obj_t EVE_clear(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + uint32_t color = 0; + uint8_t alpha = 0; + if (n_args > 1) color = mp_obj_get_int(args[1]) & 0x00ffffff; + if (n_args > 2) alpha = mp_obj_get_int(args[2]) & 0xff; + FT8_cmd_dl(DL_CLEAR_RGB | color); + FT8_cmd_dl(CLEAR_COLOR_A(alpha)); + // clear the screen - this and the previous prevent artifacts between lists. + // Attributes are the color, stencil and tag buffers + FT8_cmd_dl(CLEAR(1,1,1)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_clear_obj, 1, 3, EVE_clear); + +// ----------------------------------------------------------- +STATIC mp_obj_t EVE_color(mp_obj_t self_in, mp_obj_t color_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + mp_int_t color = mp_obj_get_int(color_in); + FT8_cmd_dl(DL_COLOR_RGB | ((uint32_t)color & 0x00ffffff)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_color_obj, EVE_color); + +// ------------------------------------------------------------- +STATIC mp_obj_t EVE_fgcolor(mp_obj_t self_in, mp_obj_t color_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + mp_int_t color = mp_obj_get_int(color_in); + FT8_cmd_fgcolor((uint32_t)color & 0x00ffffff); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_fgcolor_obj, EVE_fgcolor); + +// ------------------------------------------------------------- +STATIC mp_obj_t EVE_bgcolor(mp_obj_t self_in, mp_obj_t color_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + mp_int_t color = mp_obj_get_int(color_in); + FT8_cmd_bgcolor((uint32_t)color & 0x00ffffff); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_bgcolor_obj, EVE_bgcolor); + +// ----------------------------------------------------------- +STATIC mp_obj_t EVE_alpha(mp_obj_t self_in, mp_obj_t alpha_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + int alpha = mp_obj_get_int(alpha_in) & 0xFF; + FT8_cmd_dl(COLOR_A((uint8_t)alpha)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_alpha_obj, EVE_alpha); + +// --------------------------------------------------------------- +STATIC mp_obj_t EVE_alphafunc(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint8_t func = mp_obj_get_int(args[1]) & 7; + uint8_t ref = 0; + if (n_args > 2) ref = mp_obj_get_int(args[2]) & 255; + + FT8_cmd_dl(ALPHA_FUNC(func, ref)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_alphafunc_obj, 2, 3, EVE_alphafunc); + +// ----------------------------------------------------------------- +STATIC mp_obj_t EVE_stencilfunc(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint8_t func = mp_obj_get_int(args[1]) & 7; + uint8_t mask = mp_obj_get_int(args[2]) & 255; + uint8_t ref = 0; + if (n_args > 3) ref = mp_obj_get_int(args[3]) & 255; + + FT8_cmd_dl(STENCIL_FUNC(func, ref, mask)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_stencilfunc_obj, 3, 4, EVE_stencilfunc); + +// ---------------------------------------------------------------- +STATIC mp_obj_t EVE_stencilmask(mp_obj_t self_in, mp_obj_t mask_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + + uint8_t mask = mp_obj_get_int(mask_in) & 255; + + FT8_cmd_dl(STENCIL_MASK(mask)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_stencilmask_obj, EVE_stencilmask); + +// ---------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_stencilop(mp_obj_t self_in, mp_obj_t sfail_in, mp_obj_t spass_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + + uint8_t sfail = mp_obj_get_int(sfail_in) & 7; + uint8_t spass = mp_obj_get_int(sfail_in) & 7; + + FT8_cmd_dl(STENCIL_OP(sfail, spass)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(EVE_stencilop_obj, EVE_stencilop); + +// --------------------------------------------------------------- +STATIC mp_obj_t EVE_colormask(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + FT8_cmd_dl(COLOR_MASK(mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3]), mp_obj_get_int(args[4]))); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_colormask_obj, 5, 5, EVE_colormask); + +// ----------------------------------------------------------- +STATIC mp_obj_t EVE_blend(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + FT8_cmd_dl(BLEND_FUNC(mp_obj_get_int(args[1]), mp_obj_get_int(args[2]))); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_blend_obj, 3, 3, EVE_blend); + +// ------------------------------------------------------------- +STATIC mp_obj_t EVE_backlight(mp_obj_t self_in, mp_obj_t bkl_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + int bkl = mp_obj_get_int(bkl_in) & 0x7F; + FT8_memWrite8(REG_PWM_DUTY, bkl); // set the backlight + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_backlight_obj, EVE_backlight); + +// ---------------------------------------------------------------------- +STATIC mp_obj_t EVE_scale(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + + float x = mp_obj_get_float(x_in); + float y = mp_obj_get_float(y_in); + int32_t ix = (uint32_t)(x * 65536); + int32_t iy = (uint32_t)(y * 65536); + + FT8_cmd_scale(ix, iy); + FT8_cmd_setmatrix(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(EVE_scale_obj, EVE_scale); + +// ----------------------------------------------------------- +STATIC mp_obj_t EVE_point(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t x = mp_obj_get_int(args[1]); + uint16_t y = mp_obj_get_int(args[2]); + uint16_t r = mp_obj_get_int(args[3]); + + FT8_cmd_point(x, y, r); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_point_obj, 4, 4, EVE_point); + +// ------------------------------------------------------------ +STATIC mp_obj_t EVE_circle(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t x = mp_obj_get_int(args[1]); + uint16_t y = mp_obj_get_int(args[2]); + uint16_t r = mp_obj_get_int(args[3]); + uint32_t color = mp_obj_get_int(args[4]) & 0x00ffffff; + uint16_t lsize = 1; + if (n_args > 5) lsize = mp_obj_get_int(args[5]); + + // draw to alpha buffer + FT8_cmd_dl(COLOR_MASK(0, 0, 0, 1)); + FT8_cmd_dl(BLEND_FUNC(FT8_ONE, FT8_ONE_MINUS_SRC_ALPHA)); + FT8_cmd_point(x, y, r); // outer circle + FT8_cmd_dl(BLEND_FUNC(FT8_ZERO, FT8_ONE_MINUS_SRC_ALPHA)); + FT8_cmd_point(x, y, r-lsize); // inner circle + + // Draw outher circle from alpha buffer + FT8_cmd_dl(COLOR_MASK(1, 1, 1, 0)); + FT8_cmd_dl(BLEND_FUNC(FT8_DST_ALPHA, FT8_ONE)); + FT8_cmd_dl(DL_COLOR_RGB | color); + //FT8_cmd_rect(x-r, y-r, x+r, y+r, 1); + FT8_cmd_point(x, y, r); // outer circle + + //FT8_cmd_dl(COLOR_MASK(1, 1, 1, 1)); + FT8_cmd_dl(BLEND_FUNC(FT8_SRC_ALPHA, FT8_ONE_MINUS_SRC_ALPHA)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_circle_obj, 5, 6, EVE_circle); + +// ---------------------------------------------------------- +STATIC mp_obj_t EVE_line(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t x0 = mp_obj_get_int(args[1]); + uint16_t y0 = mp_obj_get_int(args[2]); + uint16_t x1 = mp_obj_get_int(args[3]); + uint16_t y1 = mp_obj_get_int(args[4]); + uint16_t width = mp_obj_get_int(args[5]) & 255; + + FT8_cmd_line(x0, y0, x1, y1, width); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_line_obj, 6, 6, EVE_line); + +// ---------------------------------------------------------- +STATIC mp_obj_t EVE_rect(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t x0 = mp_obj_get_int(args[1]); + uint16_t y0 = mp_obj_get_int(args[2]); + uint16_t x1 = mp_obj_get_int(args[3]); + uint16_t y1 = mp_obj_get_int(args[4]); + uint16_t corner = 1; + if (n_args > 5) corner = mp_obj_get_int(args[5]) & 255; + + FT8_cmd_rect(x0, y0, x1, y1, corner); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_rect_obj, 5, 6, EVE_rect); + +// --------------------------------------------------------------- +STATIC mp_obj_t EVE_rectangle(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t lwidth = 1; + if (n_args > 5) lwidth = mp_obj_get_int(args[5]); + uint16_t data[10]; + uint16_t x0 = mp_obj_get_int(args[1]); + uint16_t y0 = mp_obj_get_int(args[2]); + uint16_t x1 = mp_obj_get_int(args[3]); + uint16_t y1 = mp_obj_get_int(args[4]); + data[0] = x0; + data[1] = y0; + data[2] = x1; + data[3] = y0; + data[4] = x1; + data[5] = y1; + data[6] = x0; + data[7] = y1; + data[8] = x0; + data[9] = y0; + + FT8_cmd_strip(data, 10, FT8_LINE_STRIP, lwidth); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_rectangle_obj, 5, 6, EVE_rectangle); + +// -------------------------------------------------------------- +STATIC mp_obj_t EVE_triangle(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t lwidth = 1; + if (n_args > 7) lwidth = mp_obj_get_int(args[7]); + uint16_t data[8]; + data[0] = mp_obj_get_int(args[1]); + data[1] = mp_obj_get_int(args[2]); + data[2] = mp_obj_get_int(args[3]); + data[3] = mp_obj_get_int(args[4]); + data[4] = mp_obj_get_int(args[5]); + data[5] = mp_obj_get_int(args[6]); + data[6] = mp_obj_get_int(args[1]); + data[7] = mp_obj_get_int(args[2]); + + FT8_cmd_strip(data, 8, FT8_LINE_STRIP, lwidth); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_triangle_obj, 7, 8, EVE_triangle); + +// ------------------------------------------------------------ +STATIC mp_obj_t EVE_strips(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t lwidth = 1; + if (n_args > 3) lwidth = mp_obj_get_int(args[3]); + + uint16_t type = mp_obj_get_int(args[1]); + + if (!MP_OBJ_IS_TYPE(args[2], &mp_type_array)) { + mp_raise_ValueError("array argument expected"); + } + mp_obj_array_t * arr = (mp_obj_array_t *)MP_OBJ_TO_PTR(args[2]); + if ((arr->typecode != 'h') && (arr->typecode == 'H')) { + mp_raise_ValueError("array argument of type 'h', 'H' or 'B' expected"); + } + if ((arr->len < 2) || ((arr->len % 2) != 0)) { + mp_raise_ValueError("array argument length must be even and >= 2"); + } + uint16_t *buff = (uint16_t *)arr->items; + + FT8_cmd_strip(buff, arr->len*2, type, lwidth); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_strips_obj, 3, 4, EVE_strips); + +// ----------------------------------------------------------------- +STATIC mp_obj_t EVE_scissorSize(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + int16_t x = -1; + int16_t y = -1; + + uint16_t w = mp_obj_get_int(args[1]); + uint16_t h = mp_obj_get_int(args[2]); + if (n_args == 5) { + x = mp_obj_get_int(args[3]); + y = mp_obj_get_int(args[4]); + } + + FT8_cmd_dl(SCISSOR_SIZE(w, h)); + if ((x >= 0) && (y >= 0)) FT8_cmd_dl(SCISSOR_XY(x, y)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_scissorSize_obj, 3, 5, EVE_scissorSize); + +// --------------------------------------------------------------- +STATIC mp_obj_t EVE_scissorXY(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 1); + + uint16_t x = mp_obj_get_int(args[3]); + uint16_t y = mp_obj_get_int(args[4]); + + FT8_cmd_dl(SCISSOR_XY(x, y)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_scissorXY_obj, 3, 3, EVE_scissorXY); + +// -------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_text(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_text, ARG_font, ARG_align }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_font, MP_ARG_INT, { .u_int = 20 } }, + { MP_QSTR_align, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + #ifdef CONFIG_EVE_CHIP_TYPE1 + int max_font = 34; + #else + int max_font = 31; + #endif + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t font = args[ARG_font].u_int; + uint32_t align = (uint32_t)args[ARG_align].u_int; + if ((font < 0) || (font > max_font)) { + mp_raise_ValueError("Unsupported font size"); + } + uint32_t allowed_opts = FT8_OPT_CENTERX | FT8_OPT_CENTERY | FT8_OPT_CENTER | FT8_OPT_RIGHTX; + if ((align & allowed_opts) != align) { + mp_raise_ValueError("Unsupported text align"); + } + const char *st = mp_obj_str_get_str(args[ARG_text].u_obj); + + if (font > 31) { + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_romfont(1, font); + font = 1; + #endif + } + FT8_cmd_text(x, y, font, align, st); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_text_obj, 0, EVE_text); + +// -------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_number(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_num, ARG_font, ARG_align, ARG_base }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_num, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_font, MP_ARG_INT, { .u_int = 20 } }, + { MP_QSTR_align, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_base, MP_ARG_INT, { .u_int = -1 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + #ifdef CONFIG_EVE_CHIP_TYPE1 + int max_font = 34; + #else + int max_font = 31; + #endif + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t font = args[ARG_font].u_int; + uint32_t align = (uint32_t)args[ARG_align].u_int; + if ((font < 0) || (font > max_font)) { + mp_raise_ValueError("Unsupported font size"); + } + uint32_t allowed_opts = FT8_OPT_CENTERX | FT8_OPT_CENTERY | FT8_OPT_CENTER | FT8_OPT_RIGHTX | FT8_OPT_SIGNED; + if ((align & allowed_opts) != align) { + mp_raise_ValueError("Unsupported number align"); + } + int32_t num = mp_obj_get_int(args[ARG_num].u_obj); + if (num < 0) align |= FT8_OPT_SIGNED; + if (font > 31) { + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_romfont(1, font); + font = 1; + #endif + } + + #ifdef CONFIG_EVE_CHIP_TYPE1 + int base = 10; + if ((args[ARG_base].u_int > 1) && (args[ARG_base].u_int < 37)) { + base = args[ARG_base].u_int; + FT8_cmd_setbase(base); + } + #endif + FT8_cmd_number(x, y, font, align, num); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_number_obj, 0, EVE_number); + +// ---------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_button(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_width, ARG_height, ARG_text, ARG_font, ARG_opt }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_font, MP_ARG_INT, { .u_int = 20 } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t width = args[ARG_width].u_int; + mp_int_t height = args[ARG_height].u_int; + mp_int_t font = args[ARG_font].u_int; + mp_int_t opt = args[ARG_opt].u_int; + if ((font < 0) || (font > 31)) { + mp_raise_ValueError("Unsupported font size"); + } + if ((opt != 0) && (opt != FT8_OPT_FLAT)) { + mp_raise_ValueError("Unsupported option"); + } + const char *st = mp_obj_str_get_str(args[ARG_text].u_obj); + + FT8_cmd_button(x, y, width, height, font, opt, st); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_button_obj, 0, EVE_button); + +//--------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_toggle(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_x, ARG_y, ARG_width, ARG_state, ARG_text, ARG_font, ARG_opt }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_state, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_font, MP_ARG_INT, { .u_int = 20 } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t width = args[ARG_width].u_int; + mp_int_t state = args[ARG_state].u_int; + if (state) state = 65535; + mp_int_t font = args[ARG_font].u_int; + mp_int_t opt = args[ARG_opt].u_int; + if ((font < 0) || (font > 31)) { + mp_raise_ValueError("Unsupported font size"); + } + if ((opt != 0) && (opt != FT8_OPT_FLAT)) { + mp_raise_ValueError("Unsupported option"); + } + const char *st = mp_obj_str_get_str(args[ARG_text].u_obj); + + FT8_cmd_toggle(x, y, width, font, opt, state, st); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_toggle_obj, 0, EVE_toggle); + +//------------------------------------------------------------------------------------------ +STATIC mp_obj_t EVE_scrollbar(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_x, ARG_y, ARG_width, ARG_height, ARG_value, ARG_size, ARG_range, ARG_opt }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_size, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_range, MP_ARG_INT, { .u_int = 100 } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t width = args[ARG_width].u_int; + mp_int_t height = args[ARG_height].u_int; + mp_int_t value = args[ARG_value].u_int; + mp_int_t size = args[ARG_size].u_int; + if (size < 0) size = width / 5; + mp_int_t range = args[ARG_range].u_int; + mp_int_t opt = args[ARG_opt].u_int; + if ((opt != 0) && (opt != FT8_OPT_FLAT)) { + mp_raise_ValueError("Unsupported option"); + } + + FT8_cmd_scrollbar(x, y, width, height, opt, value, size, range); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_scrollbar_obj, 0, EVE_scrollbar); + +//---------------------------------------------------------------------------------------------------------- +STATIC void EVE_slider_progress(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, uint8_t type) +{ + enum { ARG_x, ARG_y, ARG_width, ARG_height, ARG_value, ARG_range, ARG_opt }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_range, MP_ARG_INT, { .u_int = 100 } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t width = args[ARG_width].u_int; + mp_int_t height = args[ARG_height].u_int; + mp_int_t value = args[ARG_value].u_int; + mp_int_t range = args[ARG_range].u_int; + mp_int_t opt = args[ARG_opt].u_int; + if ((opt != 0) && (opt != FT8_OPT_FLAT)) { + mp_raise_ValueError("Unsupported option"); + } + + if (type) FT8_cmd_progress(x, y, width, height, opt, value, range); + else FT8_cmd_slider(x, y, width, height, opt, value, range); +} + +//--------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_slider(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + EVE_slider_progress(n_args, pos_args, kw_args, 0); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_slider_obj, 0, EVE_slider); + +//----------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_progress(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + EVE_slider_progress(n_args, pos_args, kw_args, 1); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_progress_obj, 0, EVE_progress); + +//------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_keys(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_x, ARG_y, ARG_width, ARG_height, ARG_labels, ARG_font, ARG_opt }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_labels, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_font, MP_ARG_INT, { .u_int = 20 } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t width = args[ARG_width].u_int; + mp_int_t height = args[ARG_height].u_int; + mp_int_t font = args[ARG_font].u_int; + mp_int_t opt = args[ARG_opt].u_int; + const char *labels = mp_obj_str_get_str(args[ARG_labels].u_obj); + if ((font < 0) || (font > 31)) { + mp_raise_ValueError("Unsupported font size"); + } + if ((opt >= 32) && (opt < 128)) { + if (strchr(labels, opt) == NULL) { + mp_raise_ValueError("Unsupported option"); + } + } + else { + uint32_t allowed_opts = FT8_OPT_CENTERX | FT8_OPT_CENTERY | FT8_OPT_CENTER | FT8_OPT_RIGHTX | FT8_OPT_FLAT; + if ((opt & allowed_opts) != opt) { + mp_raise_ValueError("Unsupported option"); + } + } + + FT8_cmd_keys(x, y, width, height, font, opt, labels); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_keys_obj, 0, EVE_keys); + +// --------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_clock(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_r, ARG_time, ARG_opt }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_time, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t r = args[ARG_r].u_int; + uint32_t opt = (uint32_t)args[ARG_opt].u_int; + uint32_t allowed_opts = FT8_OPT_FLAT | FT8_OPT_NOBACK | FT8_OPT_NOTICKS | FT8_OPT_NOPOINTER | FT8_OPT_NOSECS | FT8_OPT_NOHANDS; + if ((opt & allowed_opts) != opt) { + mp_raise_ValueError("Unsupported option"); + } + struct tm *tm_info; + struct tm tm_inf; + + if (args[ARG_time].u_obj != mp_const_none) { + mp_obj_t *time_items; + + mp_obj_get_array_fixed_n(args[1].u_obj, 8, &time_items); + + tm_inf.tm_year = mp_obj_get_int(time_items[0]) - 1900; + tm_inf.tm_mon = mp_obj_get_int(time_items[1]) - 1; + tm_inf.tm_mday = mp_obj_get_int(time_items[2]); + tm_inf.tm_hour = mp_obj_get_int(time_items[3]); + tm_inf.tm_min = mp_obj_get_int(time_items[4]); + tm_inf.tm_sec = mp_obj_get_int(time_items[5]); + tm_inf.tm_wday = mp_obj_get_int(time_items[6]) - 1; + tm_inf.tm_yday = mp_obj_get_int(time_items[7]) - 1; + tm_info = &tm_inf; + } + else { + time_t seconds; + time(&seconds); // get the time from the RTC + tm_info = localtime(&seconds); + } + + FT8_cmd_clock(x, y, r, opt, tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec, 0); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_clock_obj, 0, EVE_clock); + +// --------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_gauge(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_r, ARG_major, ARG_minor, ARG_range, ARG_val, ARG_opt }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_major, MP_ARG_INT, { .u_int = 10 } }, + { MP_QSTR_minor, MP_ARG_INT, { .u_int = 2 } }, + { MP_QSTR_range, MP_ARG_INT, { .u_int = 100 } }, + { MP_QSTR_val, MP_ARG_INT, { .u_int = 50 } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + mp_int_t x = args[ARG_x].u_int; + mp_int_t y = args[ARG_y].u_int; + mp_int_t r = args[ARG_r].u_int; + mp_int_t major = args[ARG_major].u_int; + mp_int_t minor = args[ARG_minor].u_int; + mp_int_t val = args[ARG_val].u_int; + mp_int_t range = args[ARG_range].u_int; + uint32_t opt = (uint32_t)args[ARG_opt].u_int; + uint32_t allowed_opts = FT8_OPT_FLAT | FT8_OPT_NOBACK | FT8_OPT_NOTICKS | FT8_OPT_NOPOINTER ; + if ((opt & allowed_opts) != opt) { + mp_raise_ValueError("Unsupported option"); + } + + FT8_cmd_gauge(x, y, r, opt, major, minor, val, range); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_gauge_obj, 0, EVE_gauge); + +// ------------------------------------------------------------------------------------------ +STATIC mp_obj_t EVE_gradient(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x0, ARG_y0, ARG_rgb0, ARG_x1, ARG_y1, ARG_rgb1 }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x0, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y0, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_rgb0, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_rgb1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + int16_t x0 = args[ARG_x0].u_int; + int16_t y0 = args[ARG_y0].u_int; + uint32_t rgb0 = args[ARG_rgb0].u_int; + int16_t x1 = args[ARG_x1].u_int; + int16_t y1 = args[ARG_y1].u_int; + uint32_t rgb1 = args[ARG_rgb1].u_int; + + FT8_cmd_gradient(x0, y0, rgb0, x1, y1, rgb1); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_gradient_obj, 0, EVE_gradient); + +// --------------------------------------------- +STATIC mp_obj_t EVE_getprops(mp_obj_t self_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + uint32_t w, h, ptr; + uint16_t offset = FT8_cmd_getprops(0); + FT8_cmd_execute(250); + w = FT8_memRead32(FT8_RAM_CMD + offset); + offset += 4; + offset &= 0x0fff; + h = FT8_memRead32(FT8_RAM_CMD + offset); + offset += 4; + offset &= 0x0fff; + ptr = FT8_memRead32(FT8_RAM_CMD + offset); + + mp_obj_t tuple[3]; + tuple[0] = mp_obj_new_int(w); + tuple[1] = mp_obj_new_int(h); + tuple[2] = mp_obj_new_int(ptr); + + return mp_obj_new_tuple(3, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_getprops_obj, EVE_getprops); + +// ------------------------------------------------------------- +STATIC mp_obj_t EVE_fontinfo(mp_obj_t self_in, mp_obj_t font_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + if (mp_obj_get_type(font_in) == &font_eve_type) { + font_eve_printinfo(&mp_plat_print, font_in, PRINT_STR); + return mp_const_none; + } + + int fhandle = mp_obj_get_int(font_in); + if ((fhandle < MAX_USER_FONTS) && user_fonts[fhandle] != NULL) { + font_eve_printinfo(&mp_plat_print, user_fonts[fhandle], PRINT_STR); + return mp_const_none; + } + + // === ROM font, get metrics and print the font properties + if ((fhandle < 16) || (fhandle > ((eve_chip_id < 0x810) ? 31:34))) { + mp_raise_ValueError("Invalid font handle"); + } + + font_eve_obj_t font; + font.base.type = &font_eve_type; + // get the ROM fonts start address, fonts table starts at font 16 + uint32_t fp = FT8_memRead32(FT8_ROM_FONT_ADDR); + // calculate the address of the requested font + font.addr = fp + (EVE_FONT_METRICS_SIZE * (fhandle - 16)); + + // read the font metrics + FT8_memRead_buffer(font.addr, (uint8_t *)(&font.metrics.widths[0]), EVE_FONT_METRICS_SIZE); + + uint32_t fformat = font.metrics.format; + if (fformat == 17) fformat = 2; + else if (fformat == 2) fformat = 4; + else if (fformat == 3) fformat = 8; + font.minwidth = 99; + font.maxwidth = 0; + font.nchars = 0; + for (int i=0; i 0) { + font.nchars++; + if (font.firstc == 0) font.firstc = i; + if (font.metrics.widths[i] < font.minwidth) font.minwidth = font.metrics.widths[i]; + if (font.metrics.widths[i] > font.maxwidth) font.maxwidth = font.metrics.widths[i]; + } + } + font.handle = fhandle; + font.format = (uint8_t)fformat; + + font_eve_printinfo(&mp_plat_print, (mp_obj_t)&font, PRINT_STR); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_fontinfo_obj, EVE_fontinfo); + +// ------------------------------------------------------------- +STATIC mp_obj_t EVE_userfont(mp_obj_t self_in, mp_obj_t font_in) +{ + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + if (mp_obj_get_type(font_in) != &font_eve_type) { + mp_raise_ValueError("Font object expected"); + } + + font_eve_obj_t *font = (font_eve_obj_t *)(font_in); + if (font->loaded == 0) { + mp_raise_ValueError("Font unloaded"); + } + + #ifdef CONFIG_EVE_CHIP_TYPE1 + // For FT81x use CMD_SETFONT2 + FT8_cmd_setbitmap(font->metrics.ptr, font->metrics.format, font->metrics.width, font->metrics.height); + FT8_cmd_setfont2(font->handle, font->addr, font->firstc); + #else + // For FT80x use CMD_SETFONT + FT8_cmd_dl(BEGIN(FT8_BITMAPS)); + FT8_cmd_dl(BITMAP_HANDLE(font->handle)); + FT8_cmd_dl(BITMAP_SOURCE(font->metrics.ptr)); + FT8_cmd_dl(BITMAP_LAYOUT(font->metrics.format, font->metrics.stride, font->metrics.height)); + FT8_cmd_dl(BITMAP_SIZE(FT8_NEAREST, FT8_BORDER, FT8_BORDER, font->metrics.width, font->metrics.height)); + FT8_cmd_setfont(font->handle, font->addr); + #endif + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_userfont_obj, EVE_userfont); + +// ------------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_setbitmap(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_addr, ARG_x, ARG_y, ARG_width, ARG_height, ARG_format, ARG_wrapx, ARG_wrapy, ARG_filter, ARG_scalex, ARG_scaley }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_format, MP_ARG_INT, { .u_int = FT8_RGB565 } }, + { MP_QSTR_wrapx, MP_ARG_INT, { .u_int = FT8_BORDER } }, + { MP_QSTR_wrapy, MP_ARG_INT, { .u_int = FT8_BORDER } }, + { MP_QSTR_filter, MP_ARG_INT, { .u_int = FT8_NEAREST } }, + { MP_QSTR_scalex, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_scaley, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + uint32_t addr = args[ARG_addr].u_int; + int format = args[ARG_format].u_int; + if ((format < 0) || (format > 17) || (format == 8) || (format == 12) || (format == 13)) { + mp_raise_ValueError("Unsupported format"); + } + uint16_t width = args[ARG_width].u_int; + uint16_t height = args[ARG_height].u_int; + uint16_t x = args[ARG_x].u_int; + uint16_t y = args[ARG_y].u_int; + uint8_t wrapx = args[ARG_wrapx].u_int & 1; + uint8_t wrapy = args[ARG_wrapy].u_int & 1; + uint8_t filter = args[ARG_filter].u_int & 1; + mp_float_t fx=1.0, fy=1.0; + int32_t sx=0, sy=0; + uint16_t stride = (width*2) >> stride_factor[format]; + uint16_t sheight = height; + + if (args[ARG_scalex].u_obj != mp_const_none) { + fx = mp_obj_get_float(args[ARG_scalex].u_obj); + fy = fx; + if (args[ARG_scaley].u_obj != mp_const_none) { + fy = mp_obj_get_float(args[ARG_scaley].u_obj); + } + sx = (int32_t)round((fx * 65536)); + sy = (int32_t)round((fy * 65536)); + width = (int16_t)round((fx * width)); + sheight = (int16_t)round((fy * height)); + } + + FT8_cmd_dl(BITMAP_SOURCE(addr)); + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_LAYOUT_H(stride>>10, height>>9)); + #endif + FT8_cmd_dl(BITMAP_LAYOUT(format, stride , height)); + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_SIZE_H(width>>9, sheight>>9)); + #endif + FT8_cmd_dl(BITMAP_SIZE(filter, wrapx, wrapy, width, sheight)); + + FT8_cmd_dl(DL_BEGIN | FT8_BITMAPS); + if (sx != 0) { + FT8_cmd_dl(CMD_LOADIDENTITY); + FT8_cmd_scale(sx, sy); + FT8_cmd_setmatrix(); + } + FT8_cmd_dl(VERTEX2F(x*16, y*16)); + FT8_cmd_dl(DL_END); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_setbitmap_obj, 0, EVE_setbitmap); + +// ------------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_showimage(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_x, ARG_y, ARG_img, ARG_wrapx, ARG_wrapy, ARG_filter, ARG_scalex, ARG_scaley }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_image, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_wrapx, MP_ARG_INT, { .u_int = FT8_BORDER } }, + { MP_QSTR_wrapy, MP_ARG_INT, { .u_int = FT8_BORDER } }, + { MP_QSTR_filter, MP_ARG_INT, { .u_int = FT8_NEAREST } }, + { MP_QSTR_scalex, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_scaley, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_eve_obj_t *self = pos_args[0]; + _check_inlist(self, 1); + + if (mp_obj_get_type(args[ARG_img].u_obj) != &image_eve_type) { + mp_raise_ValueError("Image object expected"); + } + + image_eve_obj_t *image = (image_eve_obj_t *)(args[ARG_img].u_obj); + if (image->loaded == 0) { + mp_raise_ValueError("Image unloaded"); + } + + uint16_t width = image->width; + uint16_t height = image->height; + uint16_t x = args[ARG_x].u_int; + uint16_t y = args[ARG_y].u_int; + uint8_t wrapx = args[ARG_wrapx].u_int & 1; + uint8_t wrapy = args[ARG_wrapy].u_int & 1; + uint8_t filter = args[ARG_filter].u_int & 1; + mp_float_t fx=1.0, fy=1.0; + int32_t sx=0, sy=0; + uint16_t stride = (width*2) >> stride_factor[image->format]; + uint16_t sheight = height; + + if (args[ARG_scalex].u_obj != mp_const_none) { + fx = mp_obj_get_float(args[ARG_scalex].u_obj); + fy = fx; + if (args[ARG_scaley].u_obj != mp_const_none) { + fy = mp_obj_get_float(args[ARG_scaley].u_obj); + } + sx = (int32_t)round((fx * 65536)); + sy = (int32_t)round((fy * 65536)); + width = (int16_t)round((fx * width)); + sheight = (int16_t)round((fy * height)); + } + + FT8_cmd_dl(BITMAP_SOURCE(image->addr)); + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_LAYOUT_H(stride>>10, height>>9)); + #endif + FT8_cmd_dl(BITMAP_LAYOUT(image->format, stride , height)); + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_SIZE_H(width>>9, sheight>>9)); + #endif + FT8_cmd_dl(BITMAP_SIZE(filter, wrapx, wrapy, width, sheight)); + + FT8_cmd_dl(DL_BEGIN | FT8_BITMAPS); + if (sx != 0) { + FT8_cmd_dl(CMD_LOADIDENTITY); + FT8_cmd_scale(sx, sy); + FT8_cmd_setmatrix(); + } + FT8_cmd_dl(VERTEX2F(x*16, y*16)); + FT8_cmd_dl(DL_END); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_showimage_obj, 0, EVE_showimage); + +#ifdef CONFIG_EVE_CHIP_TYPE1 +//------------------------------------------------------------------------------------------ +STATIC mp_obj_t EVE_playvideo(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_file, ARG_opt, ARG_mode, ARG_vol }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_mode, MP_ARG_INT, { .u_int = 1 } }, + { MP_QSTR_vol, MP_ARG_INT, { .u_int = -1 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + //display_eve_obj_t *self = pos_args[0]; + + _check_inlist(eve_obj, 0); + + uint32_t addr = ft8_ramg_ptr; + int size=0, frames=0; + char *fname = NULL; + char fullname[128] = {'\0'}; + struct stat sb; + fname = (char *)mp_obj_str_get_str(args[ARG_file].u_obj); + uint32_t allowed_opts = FT8_OPT_MONO | FT8_OPT_MEDIAFIFO | FT8_OPT_NOTEAR | FT8_OPT_SOUND | FT8_OPT_FULLSCREEN; + uint32_t opt = args[ARG_opt].u_int & allowed_opts; + opt |= FT8_OPT_MEDIAFIFO; + uint32_t mode = args[ARG_mode].u_int; + + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + + if (stat(fullname, &sb) != 0) { + mp_raise_ValueError("Error getting file info"); + } + int file_len = sb.st_size; + + // try to determine image type + FILE *fhndl = fopen(fullname, "rb"); + if (fhndl == NULL) { + mp_raise_ValueError("Error opening file"); + } + + int width=0, height=0, time=0; + uint8_t buf[256]; + if (fread(buf, 1, 256, fhndl) == 256) { + buf[255] = 0; + res = _check_avi(buf, &width, &height, &time, &frames); + if (res != 0) { + fclose(fhndl); + mp_raise_ValueError("Wriong file format, only MJPEG AVI files are supported"); + } + size = width*height * 2; + if (size > (FT8_RAM_G_SIZE-addr-65536-4)) { + fclose(fhndl); + mp_raise_ValueError("No space left in Eve RAM"); + } + } + else { + fclose(fhndl); + mp_raise_ValueError("Error reading file info"); + } + fseek(fhndl, 0, SEEK_SET); + + if (args[ARG_vol].u_int > 0) FT8_memWrite8(REG_VOL_PB, args[ARG_vol].u_int & 0xFF); // set audio volume + + res = FT8_Fifo_init(fhndl); + if (res != 0) { + fclose(fhndl); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error initializing mediafifo")); + } + + res = FT8_sendDataViaMediafifo(fhndl, addr, opt, (uint8_t)mode); + if (res < 0) return mp_const_false; + + if (mode == 2) { + mp_obj_t tuple[5]; + tuple[0] = mp_obj_new_int(width); + tuple[1] = mp_obj_new_int(height); + tuple[2] = mp_obj_new_int(time); + tuple[3] = mp_obj_new_int(addr); + tuple[4] = mp_obj_new_int(frames); + + return mp_obj_new_tuple(5, tuple); + } + + FT8_Fifo_deinit(); + ESP_LOGD(TAG, "PlayVideo: file length=%d, played=%d\n", file_len, file_len - ft8_stFifo.file_remain); + + fclose(fhndl); + + return mp_const_true; + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_playvideo_obj, 0, EVE_playvideo); + +// --------------------------------------------------------------- +STATIC mp_obj_t EVE_videoframe(mp_obj_t self_in, mp_obj_t addr_in) +{ + //display_eve_obj_t *self = self_in; + _check_inlist(eve_obj, 1); + + uint32_t addr = mp_obj_get_int(addr_in); + FT8_cmd_videoframe(addr); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_videoframe_obj, EVE_videoframe); + +// --------------------------------------------- +STATIC mp_obj_t EVE_lastframe(mp_obj_t self_in) +{ + //display_eve_obj_t *self = self_in; + _check_inlist(eve_obj, 0); + + if (FT8_memRead32(ft8_stFifo.fifo_buff-4)) return mp_const_false; + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_lastframe_obj, EVE_lastframe); + +// ---------------------------------------------- +STATIC mp_obj_t EVE_videobuffer(mp_obj_t self_in) +{ + //display_eve_obj_t *self = self_in; + _check_inlist(eve_obj, 0); + + int res = FT8_Fifo_service(); + if (res < 0) { + ESP_LOGE(TAG, "Error in Fifo service"); + FT8_CP_reset(); + return mp_obj_new_int(res); + } + + return mp_obj_new_int(ft8_stFifo.file_remain); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_videobuffer_obj, EVE_videobuffer); + +// --------------------------------------------- +STATIC mp_obj_t EVE_closevideo(mp_obj_t self_in) +{ + //display_eve_obj_t *self = self_in; + _check_inlist(eve_obj, 0); + + if (ft8_stFifo.pFile) fclose(ft8_stFifo.pFile); + FT8_Fifo_deinit(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_closevideo_obj, EVE_closevideo); +#endif + +// ---------------------------------------------------------- +STATIC mp_obj_t EVE_vol_pb(mp_obj_t self_in, mp_obj_t vol_in) +{ + _check_inlist(eve_obj, 0); + + uint8_t volume = mp_obj_get_int(vol_in) & 0xFF; + FT8_memWrite8(REG_VOL_PB, volume); // set audio volume + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_vol_pb_obj, EVE_vol_pb); + +// ------------------------------------------------------------- +STATIC mp_obj_t EVE_vol_sound(mp_obj_t self_in, mp_obj_t vol_in) +{ + _check_inlist(eve_obj, 0); + + uint8_t volume = mp_obj_get_int(vol_in) & 0xFF; + FT8_memWrite8(REG_VOL_SOUND, volume); // set sound volume + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_vol_sound_obj, EVE_vol_sound); + +// ------------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_sound(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_effect, ARG_note, ARG_vol, ARG_wait }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_effect, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 255 } }, + { MP_QSTR_note, MP_ARG_INT, { .u_int = 84 } }, + { MP_QSTR_vol, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _check_inlist(eve_obj, 0); + + + int effect = args[ARG_effect].u_int; + int note = args[ARG_note].u_int; + if ((note < 21) || (note > 108)) { + mp_raise_ValueError("Invalid MIDI note"); + } + + int effect_type = -1; + if (effect == 0) effect_type = 2; // silence + else if (effect < 0x09) effect_type = 3; // waves and effects + else if ((effect >= 0x10) && (effect <= 0x1F)) effect_type = 1; // pips + else if ((effect == 0x23) || (effect == 0x2C) || ((effect >= 0x30) && (effect <= 0x39))) effect_type = 2; // DTMF tones + else if ((effect >= 0x40) && (effect <= 0x49)) effect_type = 1; // instruments + else if ((effect >= 0x50) && (effect <= 0x58)) effect_type = 0; // sound effects + else if ((effect == 0x60) || (effect == 0x61)) effect_type = 0; // mute/unmute + if (effect_type < 0) { + mp_raise_ValueError("Invalid sound effect"); + } + + uint16_t sound = effect; + if (effect_type & 1) sound |= (note << 8); // has pitch/note + + // stop the previous sound + //FT8_memWrite16(REG_SOUND, 0); + //FT8_memWrite8(REG_PLAY, 1); + + if (args[ARG_vol].u_int >= 0) { + // set the sound volume + FT8_memWrite8(REG_VOL_SOUND, args[ARG_vol].u_int & 0xFF); + } + + // start the sound effect + FT8_memWrite16(REG_SOUND, sound); + FT8_memWrite8(REG_PLAY, 1); + + if (args[ARG_wait].u_int > 0) { + if (effect_type & 2) { + // coutinuous sound, wait for given time + mp_hal_delay_ms(args[ARG_wait].u_int); + FT8_memWrite16(REG_SOUND, 0x60); // mute + FT8_memWrite8(REG_PLAY, 1); + } + else { + // non continuous sound, wait untill finished + while (FT8_memRead8(REG_PLAY)) { + mp_hal_delay_ms(3); + } + } + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(EVE_sound_obj, 0, EVE_sound); + +// ---------------------------------------------------------------------------- +// ---- List dump methods ----------------------------------------------------- +// ---------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +static uint16_t process_eve_command(uint32_t cmd, uint32_t base, uint16_t *idx) +{ + uint16_t proc_bytes = 4; + uint32_t ccmd = cmd & 0xFF000000; + *idx += 4; + *idx &= 0xfff; + if (cmd == DL_DISPLAY) mp_printf(&mp_plat_print, "DISPLAY (End Display List)\n"); + else if (ccmd == DL_CLEAR_RGB) mp_printf(&mp_plat_print, "CLEAR_COLOR_RGB (0x%06x)\n", cmd & 0xFFFFFF); + else if (ccmd == DL_CLEAR) mp_printf(&mp_plat_print, "CLEAR (%d, %d, %d)\n", (cmd>>2)&1, (cmd>>1)&1, cmd&1); + else if (ccmd == DL_CLEAR) mp_printf(&mp_plat_print, "CLEAR (%d, %d, %d)\n", (cmd>>2)&1, (cmd>>1)&1, cmd&1); + else if (ccmd == 0x0F000000) mp_printf(&mp_plat_print, "CLEAR_COLOR_A (%d)\n", cmd & 0xFF); + else if (ccmd == 0x11000000) mp_printf(&mp_plat_print, "CLEAR_STENCIL (%d)\n", cmd & 0xFF); + else if (ccmd == 0x12000000) mp_printf(&mp_plat_print, "CLEAR_TAG (%d)\n", cmd & 0xFF); + else if (ccmd == 0x03000000) mp_printf(&mp_plat_print, "TAG (%d)\n", cmd & 0xFF); + else if (ccmd == 0x01400000) mp_printf(&mp_plat_print, "TAG_MASK (%d)\n", cmd & 1); + else if (ccmd == DL_POINT_SIZE) mp_printf(&mp_plat_print, "POINT_SIZE (%d)\n", cmd & 8192); + else if (ccmd == 0x0E000000) mp_printf(&mp_plat_print, "LINE_WIDTH (%d)\n", cmd & 4095); + else if (ccmd == DL_END) mp_printf(&mp_plat_print, "END\n"); + else if (ccmd == DL_BEGIN) { + if (((cmd & 0x0F)-1) < 9) mp_printf(&mp_plat_print, "BEGIN %s\n", ft8_prim[(cmd & 0x0F)-1]); + else mp_printf(&mp_plat_print, "BEGIN ? (%d)\n", cmd & 0x0F); + } + else if (ccmd == 0x01000000) mp_printf(&mp_plat_print, "BITMAP_SOURCE (%d)\n", cmd & 0xFFFFFF); + else if (ccmd == 0x07000000) mp_printf(&mp_plat_print, "BITMAP_LAYOUT (%d, %d, %d)\n", (cmd>>19)&31, (cmd>>9)&1023, cmd&511); + else if (ccmd == 0x28000000) mp_printf(&mp_plat_print, "BITMAP_LAYOUT_H (%d, %d)\n", (cmd>>2)&3, cmd&3); + else if (ccmd == 0x29000000) mp_printf(&mp_plat_print, "BITMAP_SIZE_H (%d, %d)\n", (cmd>>2)&3, cmd&3); + else if (ccmd == 0x08000000) mp_printf(&mp_plat_print, "BITMAP_SIZE (%d, %d, %d, %d, %d)\n", (cmd>>20)&1, (cmd>>19)&1, (cmd>>18)&1, (cmd>>9)&512, cmd&511); + else if (ccmd == 0x05000000) mp_printf(&mp_plat_print, "BITMAP_HANDLE (%0d)\n", cmd & 31); + else if (ccmd == 0x2A000000) mp_printf(&mp_plat_print, "PALETTE_SOURCE (%d)\n", cmd & 0x3FFFFF); + else if (ccmd == 0x2B000000) mp_printf(&mp_plat_print, "VERTEX_TRANSLATE_X (%d)\n", cmd & 131071); + else if (ccmd == 0x2C000000) mp_printf(&mp_plat_print, "VERTEX_TRANSLATE_Y (%d)\n", cmd & 131071); + else if (ccmd == 0x0b000000) mp_printf(&mp_plat_print, "BLEND_FUNC (%d, %d)\n", (cmd>>3)&7, cmd&7); + else if (ccmd == 0x09000000) mp_printf(&mp_plat_print, "ALPHA_FUNC (%d, %d)\n", (cmd>>8)&7, cmd&255); + else if (ccmd == 0x10000000) mp_printf(&mp_plat_print, "COLOR_A (%d)\n", cmd&255); + else if (ccmd == 0x20000000) mp_printf(&mp_plat_print, "COLOR_MASK (%d, %d, %d, %d)\n", (cmd>>3)&1, (cmd>>2)&1, (cmd>>1)&1, cmd&1); + else if (ccmd == 0x04000000) mp_printf(&mp_plat_print, "COLOR_RGB (%d, %d, %d)\n", (cmd>>16)&255, (cmd>>8)&255, cmd&255); + else if (ccmd == 0x22000000) mp_printf(&mp_plat_print, "SAVE_CONTEXT\n"); + else if (ccmd == 0x23000000) mp_printf(&mp_plat_print, "RESTORE_CONTEXT\n"); + else if ((ccmd >= 0x15000000) && (ccmd <= 0x1A000000)) mp_printf(&mp_plat_print, "BITMAP_TRANSFORM_%c (%d)\n", 65+((ccmd>>24)-0x15), cmd&131071); + #ifdef CONFIG_EVE_CHIP_TYPE1 + else if (ccmd == NOP()) mp_printf(&mp_plat_print, "NOP\n"); + #endif + else if ((cmd & 0xC0000000) == 0x40000000) mp_printf(&mp_plat_print, "VERTEX2F (%d, %d)\n", (cmd >> 15)&32767, cmd&32767); + else if ((cmd & 0xC0000000) == 0x80000000) mp_printf(&mp_plat_print, "VERTEXII (%d, %d, %d, %d)\n", (cmd >> 21)&0x1FF, (cmd >> 12)&0x1FF, (cmd >> 7)&31, cmd&127); + else { + uint16_t j = *idx; + switch (cmd) { + case (CMD_DLSTART): + mp_printf(&mp_plat_print, "CMD_DLSTART\n"); + break; + case (CMD_SWAP): + mp_printf(&mp_plat_print, "CMD_SWAP\n"); + break; + case (CMD_LOADIDENTITY): + mp_printf(&mp_plat_print, "CMD_LOADIDENTITY\n"); + break; + case (CMD_SETMATRIX): + mp_printf(&mp_plat_print, "CMD_SETMATRIX\n"); + break; + case (CMD_SCALE): { + mp_printf(&mp_plat_print, "CMD_SCALE\n"); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(%1.3f,", (float)(cmd / 65536.0)); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "%1.3f)\n", (float)(cmd / 65536.0)); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_COLDSTART): + mp_printf(&mp_plat_print, "CMD_COLDSTART\n"); + break; + case (CMD_FGCOLOR): { + mp_printf(&mp_plat_print, "CMD_FGCOLOR "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(0x%06x)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_BGCOLOR): { + mp_printf(&mp_plat_print, "CMD_BGCOLOR "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(0x%06x)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_INFLATE): { + mp_printf(&mp_plat_print, "CMD_INFLATE "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_GETPTR): { + mp_printf(&mp_plat_print, "CMD_GETPTR "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_LOADIMAGE): { + mp_printf(&mp_plat_print, "CMD_LOADIMAGE "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(%d,", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + #ifdef CONFIG_EVE_CHIP_TYPE1 + case (CMD_MEDIAFIFO): { + mp_printf(&mp_plat_print, "CMD_MEDIAFIFO "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(%d,", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_SETBITMAP): { + mp_printf(&mp_plat_print, "CMD_SETBITMAP "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(addr=%d, ", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "fmt=%d, w=%d, ", cmd & 0xffff, cmd >> 16); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "h=%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_SETFONT2): { + mp_printf(&mp_plat_print, "CMD_SETFONT2: "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(font=%d, ", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "addr=%d, ", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "1st char=%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + #endif + case (CMD_GETPROPS): { + mp_printf(&mp_plat_print, "CMD_GETPROPS "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(addr=%d, ", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "w=%d, ", cmd & 0xfff); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "h=%d)\n", cmd & 0xfff); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_APPEND): { + mp_printf(&mp_plat_print, "CMD_APPEND "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(%d,", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + case (CMD_TEXT): { + mp_printf(&mp_plat_print, "CMD_TEXT "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(%d,%d), ", cmd & 0xFFFF, cmd >> 16); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "f=%d, opt=%d\n", cmd & 0xFFFF, cmd >> 16); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + j += 4; + j &= 0xfff; + proc_bytes += 4; + mp_printf(&mp_plat_print, " '"); + while (1) { + char *txt = (char *)&cmd; + char ch = *txt; + for (int k=0; k<4; k++) { + ch = *txt++; + if (ch == '\0') break; + if ((ch > 0) && (ch < 32)) ch = '.'; + if (ch > 0) { + if (ch >= 32) mp_printf(&mp_plat_print, "%c", ch); + else mp_printf(&mp_plat_print, "\\x%2x", ch); + } + } + if (ch == '\0') break; + cmd = FT8_memRead32(base + j); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + mp_printf(&mp_plat_print, "'\n"); + } + break; + case (CMD_SETFONT): { + mp_printf(&mp_plat_print, "CMD_SETFONT: "); + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "(font=%d, ", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + cmd = FT8_memRead32(base + j); + mp_printf(&mp_plat_print, "addr=%d)\n", cmd); + j += 4; + j &= 0xfff; + proc_bytes += 4; + } + break; + default: + mp_printf(&mp_plat_print, "[%08x]\n", cmd); + } + *idx = j; + } + return proc_bytes; +} + +// ------------------------------------------------------------- +STATIC mp_obj_t EVE_dumpcmd(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 0); + + bool verbose = true; + if (n_args > 1) verbose = mp_obj_is_true(args[1]); + int list_size; + if (eve_cmdOffset < eve_cmd_start_addr) list_size = FT8_CMDFIFO_SIZE-eve_cmd_start_addr + eve_cmdOffset; + else list_size = eve_cmdOffset-eve_cmd_start_addr; + uint32_t cmd; + uint16_t idx = eve_cmd_start_addr; + + mp_printf(&mp_plat_print, "Command buffer content, size = %d\n", list_size); + while (list_size > 0) { + cmd = FT8_memRead32(FT8_RAM_CMD + idx); + if (verbose) { + mp_printf(&mp_plat_print, "%04d: ", idx); + list_size -= process_eve_command(cmd, FT8_RAM_CMD, &idx); + } + else { + mp_printf(&mp_plat_print, "%04d: %08x\n", idx, cmd); + idx += 4; + list_size -= 4; + if (cmd == DL_DISPLAY) break; + } + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_dumpcmd_obj, 1, 2, EVE_dumpcmd); + +// -------------------------------------------------------------- +STATIC mp_obj_t EVE_dumplist(size_t n_args, const mp_obj_t *args) +{ + display_eve_obj_t *self = args[0]; + _check_inlist(self, 0); + + bool verbose = true; + if (n_args > 1) verbose = mp_obj_is_true(args[1]); + uint16_t list_size = FT8_memRead32(REG_CMD_DL) & 0x1FFF; + uint32_t cmd; + uint16_t idx = 0; + mp_printf(&mp_plat_print, "Display list content, size = %d\n", list_size); + while (idx < list_size) { + cmd = FT8_memRead32(FT8_RAM_DL + idx); + if (verbose) { + mp_printf(&mp_plat_print, "%04d: ", idx); + process_eve_command(cmd, FT8_RAM_DL, &idx); + } + else { + mp_printf(&mp_plat_print, "%04d: %08x\n", idx, cmd); + idx += 4; + } + if (cmd == DL_DISPLAY) break; + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_dumplist_obj, 1, 2, EVE_dumplist); + +// ------------------------------------------------ +STATIC mp_obj_t EVE_freeobjects(mp_obj_t self_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + memset(user_fonts, 0, sizeof(user_fonts)); + memset(ramg_objects.objects, 0, sizeof(void*) * ramg_objects.size); + ramg_objects.count = 0; + + ft8_ramg_ptr = FT8_RAM_G; + loaded_images = 0; + loaded_fonts = 0; + loaded_lists = 0; + + FT8_cmd_memzero(FT8_RAM_G, FT8_RAM_G_SIZE); + FT8_cmd_execute(250); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_freeobjects_obj, EVE_freeobjects); + +// --------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_memWrite(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buff_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + int addr = mp_obj_get_int(addr_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buff_in, &bufinfo, MP_BUFFER_READ); + + FT8_memWrite_flash_buffer(addr, bufinfo.buf, bufinfo.len, false); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(EVE_memWrite_obj, EVE_memWrite); + +// ------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_memRead(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t len_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + int addr = mp_obj_get_int(addr_in); + int len = mp_obj_get_int(len_in); + vstr_t vstr; + vstr_init_len(&vstr, len); + + FT8_memRead_buffer(addr, (uint8_t *)vstr.buf, len); + + // Return read data as string + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(EVE_memRead_obj, EVE_memRead); + +// ------------------------------------------------------------------------------- +STATIC mp_obj_t EVE_memZero(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t len_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + int addr = mp_obj_get_int(addr_in); + int len = mp_obj_get_int(len_in); + + FT8_cmd_memzero(addr, len); + FT8_cmd_execute(250); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(EVE_memZero_obj, EVE_memZero); + +// -------------------------------------------------------------- +STATIC mp_obj_t EVE_memSet(size_t n_args, const mp_obj_t *args) { + display_eve_obj_t *self = args[0]; + _check_inlist(self, 0); + + int addr = mp_obj_get_int(args[1]); + int len = mp_obj_get_int(args[2]); + uint8_t val = mp_obj_get_int(args[3]) & 0xff; + + FT8_cmd_memset(addr, val, len); + FT8_cmd_execute(250); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(EVE_memSet_obj, 4, 4, EVE_memSet); + +// --------------------------------------------------------- +STATIC mp_obj_t EVE_tag(mp_obj_t self_in, mp_obj_t tag_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + + uint8_t tag = mp_obj_get_int(tag_in) & 0xff; + if (tag) FT8_cmd_dl(TAG(tag)); + else FT8_cmd_dl(TAG_MASK(0)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_tag_obj, EVE_tag); + +// -------------------------------------------------------------- +STATIC mp_obj_t EVE_tagmask(mp_obj_t self_in, mp_obj_t mask_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 1); + + bool mask = mp_obj_is_true(mask_in); + + FT8_cmd_dl(TAG_MASK(mask)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(EVE_tagmask_obj, EVE_tagmask); + +// ------------------------------------------- +STATIC mp_obj_t EVE_gettag(mp_obj_t self_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + int tag = FT8_get_touch_tag(); + + return mp_obj_new_int(tag); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_gettag_obj, EVE_gettag); + +// --------------------------------------------- +STATIC mp_obj_t EVE_gettagXY(mp_obj_t self_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + uint32_t tagxy = FT8_memRead32(REG_TOUCH_TAG_XY); + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_int(tagxy & 0xFFFF); + tuple[1] = mp_obj_new_int(tagxy >> 16); + + return mp_obj_new_tuple(2, tuple); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_gettagXY_obj, EVE_gettagXY); + +// -------------------------------------------- +STATIC mp_obj_t EVE_touchXY(mp_obj_t self_in) { + display_eve_obj_t *self = self_in; + _check_inlist(self, 0); + + uint32_t touchxy = FT8_memRead32(REG_TOUCH_SCREEN_XY); + if ((touchxy & 0x80008000)) return mp_const_false; + + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_int(touchxy >> 16); // X + tuple[1] = mp_obj_new_int(touchxy & 0xFFFF); // Y + + return mp_obj_new_tuple(2, tuple); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_touchXY_obj, EVE_touchXY); + +// ----------------------------------------------- +STATIC mp_obj_t EVE_screensize(mp_obj_t self_in) { + display_eve_obj_t *self = self_in; + + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_int(self->width); + tuple[1] = mp_obj_new_int(self->height); + + return mp_obj_new_tuple(2, tuple); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(EVE_screensize_obj, EVE_screensize); + + + +// --------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------- + +// ==== FONT object ============================================ + +// constructor +//---------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t font_eve_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_file }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _check_inlist(eve_obj, 0); + uint32_t addr = ft8_ramg_ptr; // object address in Eve RAM_G + + char *fname = NULL; + char fullname[128] = {'\0'}; + int len; + struct stat sb; + uint8_t fhandle = MAX_USER_FONTS; + + fname = (char *)mp_obj_str_get_str(args[ARG_file].u_obj); + + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + + if (stat(fullname, &sb) != 0) { + mp_raise_ValueError("Error getting file info"); + } + len = sb.st_size; + if (!check_ramg(len)) { + mp_raise_ValueError("No space left in Eve RAM"); + } + // Find free font structure + for (int i=0; i < MAX_USER_FONTS; i++) { + if (user_fonts[i] == NULL) { + fhandle = i; + break; + } + } + if (fhandle >= MAX_USER_FONTS) { + mp_raise_ValueError("No free font handles left"); + } + + eve_font_metrics_t metrics; + uint8_t *pmetrics = (uint8_t *)(&metrics.widths[0]); + uint32_t size = 0; + + // Read the font into Eve RAM_G + FILE *fhndl = fopen(fullname, "rb"); + if (fhndl != NULL) { + // get the font metrics block + if (fread(pmetrics, 1, EVE_FONT_METRICS_SIZE, fhndl) == EVE_FONT_METRICS_SIZE) { + uint8_t *buff = malloc(1024); + if (buff == NULL) { + fclose(fhndl); + mp_raise_ValueError("Error allocating read buffer"); + } + uint32_t fptr = addr + EVE_FONT_METRICS_SIZE; + size += EVE_FONT_METRICS_SIZE; + // Set the font's raw data address + if (eve_chip_id < 0x810) metrics.ptr = addr - (metrics.stride * metrics.height) + EVE_FONT_METRICS_SIZE; + else metrics.ptr = addr + EVE_FONT_METRICS_SIZE; + // transfer the font metrics block + FT8_memWrite_flash_buffer(FT8_RAM_G+addr, pmetrics, EVE_FONT_METRICS_SIZE, true); + // transfer the raw font data + do { + len = fread(buff, 1, 1024, fhndl); + if (len <= 0) break; + if (len < 1024) memset(buff+len, 0, 1024-len); + if ((len % 4) != 0) len += (4 - (len % 4)); + FT8_memWrite_flash_buffer(FT8_RAM_G+fptr, buff, len, true); + fptr += len; + size += len; + } while (len > 0); + + free(buff); + } + else { + fclose(fhndl); + mp_raise_ValueError("Error reading font file"); + } + fclose(fhndl); + } + else { + mp_raise_ValueError("Error opening font file"); + } + + uint8_t nchars = 0; + uint8_t firstc = 0; + uint32_t fformat = metrics.format; + if (fformat == 17) fformat = 2; + else if (fformat == 2) fformat = 4; + else if (fformat == 3) fformat = 8; + uint8_t minwidth = 99, maxwidth = 0; + for (int i=0; i<128; i++) { + if (metrics.widths[i] > 0) { + nchars++; + if (firstc == 0) firstc = i; + if (metrics.widths[i] < minwidth) minwidth = metrics.widths[i]; + if (metrics.widths[i] > maxwidth) maxwidth = metrics.widths[i]; + } + } + + // Create FONT instance object + font_eve_obj_t *self = m_new_obj(font_eve_obj_t); + memset(self, 0, sizeof(font_eve_obj_t)); + self->base.type = &font_eve_type; + + memcpy((uint8_t *)(&self->metrics.widths[0]), pmetrics, sizeof(eve_font_metrics_t)); + self->addr = addr; + self->size = size; + self->handle = fhandle; + self->firstc = firstc; + self->maxwidth = maxwidth; + self->minwidth = minwidth; + self->nchars = nchars; + self->format = (uint8_t)fformat; + self->loaded = 1; + + if (!add_ramg_object((void *)self)) { + mp_raise_ValueError("Error adding ramg object"); + } + user_fonts[fhandle] = self; + + ft8_ramg_ptr += size; + loaded_fonts++; + + return MP_OBJ_FROM_PTR(self); +} + +// -------------------------------------------- +STATIC mp_obj_t FONT_EVE_free(mp_obj_t self_in) +{ + _check_inlist(eve_obj, 0); + font_eve_obj_t *self = (font_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_true; + + bool res = true; + if ((self->addr+self->size) < ft8_ramg_ptr) { + // move other objects in RAM_G above this one + FT8_cmd_memcpy(self->addr, self->addr + self->size, ft8_ramg_ptr - (self->addr+self->size)); + res = FT8_cmd_execute(250); + } + adjust_ramg_objects((void *)self, self->addr, self->size); + ft8_ramg_ptr -= self->size; + user_fonts[self->handle] = NULL; + loaded_fonts--; + self->loaded = 0; + + if (res) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(FONT_EVE_free_obj, FONT_EVE_free); + +// -------------------------------------------- +STATIC mp_obj_t FONT_EVE_info(mp_obj_t self_in) +{ + font_eve_obj_t *self = (font_eve_obj_t *)self_in; + + font_eve_printinfo(&mp_plat_print, self, PRINT_STR); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(FONT_EVE_info_obj, FONT_EVE_info); + +// --------------------------------------------- +STATIC mp_obj_t FONT_EVE_props(mp_obj_t self_in) +{ + font_eve_obj_t *self = (font_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_false; + + mp_obj_t tuple[7]; + tuple[0] = mp_obj_new_int(self->handle); + tuple[1] = mp_obj_new_int(self->metrics.width); + tuple[2] = mp_obj_new_int(self->metrics.height); + tuple[3] = mp_obj_new_int(self->minwidth); + tuple[4] = mp_obj_new_int(self->maxwidth); + tuple[5] = mp_obj_new_int(self->nchars); + tuple[6] = mp_obj_new_int(self->firstc); + + return mp_obj_new_tuple(7, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(FONT_EVE_props_obj, FONT_EVE_props); + +//------------------------------------------------------------- +STATIC const mp_rom_map_elem_t font_eve_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&FONT_EVE_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&FONT_EVE_free_obj) }, + { MP_ROM_QSTR(MP_QSTR_props), MP_ROM_PTR(&FONT_EVE_props_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(font_eve_locals_dict, font_eve_locals_dict_table); + +//----------------------------------- +const mp_obj_type_t font_eve_type = { + { &mp_type_type }, + .name = MP_QSTR_FONT, + .print = font_eve_printinfo, + .make_new = font_eve_make_new, + .locals_dict = (mp_obj_t)&font_eve_locals_dict, +}; + +// ^^^^ FONT object end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +// ==== IMAGE object =========================================== + +// constructor +//---------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t image_eve_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_file, ARG_opt, ARG_type, ARG_format, ARG_width, ARG_height }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_type, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_format, MP_ARG_INT, { .u_int = FT8_RGB565 } }, + { MP_QSTR_width, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_INT, { .u_int = 0 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _check_inlist(eve_obj, 0); + + char *fname = NULL; + char fullname[128] = {'\0'}; + int len=0, size=0; + fname = (char *)mp_obj_str_get_str(args[ARG_file].u_obj); + #ifdef CONFIG_EVE_CHIP_TYPE1 + uint32_t allowed_opts = FT8_OPT_MONO | FT8_OPT_FULLSCREEN | FT8_OPT_MEDIAFIFO; + #else + uint32_t allowed_opts = FT8_OPT_MONO; + #endif + uint32_t opt = args[ARG_opt].u_int & allowed_opts; + opt |= FT8_OPT_NODL; + uint32_t addr = ft8_ramg_ptr; // address in Eve RAM_G + int format = args[ARG_format].u_int; + int width = args[ARG_width].u_int; + int height = args[ARG_height].u_int; + + int img_type = args[ARG_type].u_int; + if (img_type < 0) { + img_type = IMAGE_TYPE_NONE; + // try to determine image type + char upr_fname[128] = {'\0'}; + int fname_len = strlen(upr_fname); + strcpy(upr_fname, fname); + for (int i=0; i < strlen(upr_fname); i++) { + upr_fname[i] = toupper((unsigned char) upr_fname[i]); + } + if (strstr(upr_fname, ".JPG") == (upr_fname+fname_len-4)) img_type = IMAGE_TYPE_JPG; + else if (strstr(upr_fname, ".JPEG") == (upr_fname+fname_len-5)) img_type = IMAGE_TYPE_JPG; + else if (strstr(upr_fname, ".PNG") == (upr_fname+fname_len-4)) img_type = IMAGE_TYPE_PNG; + else if (strstr(upr_fname, ".RAW") == (upr_fname+fname_len-4)) img_type = IMAGE_TYPE_RAW; + else if (strstr(upr_fname, ".BIN") == (upr_fname+fname_len-4)) img_type = IMAGE_TYPE_BIN; + else { + mp_raise_ValueError("Unsupported image file extension"); + } + } + else if ((img_type != IMAGE_TYPE_JPG) && (img_type != IMAGE_TYPE_PNG) && (img_type != IMAGE_TYPE_RAW) && (img_type != IMAGE_TYPE_BIN)) { + mp_raise_ValueError("Unsupported image file type"); + } + + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + + // try to determine image type + FILE *fhndl = fopen(fullname, "rb"); + if (fhndl != NULL) { + // get file size + if (fseek(fhndl,0,SEEK_END) == 0) { + len = ftell(fhndl); + } + if (fseek(fhndl,0,SEEK_SET)) len = 0; + if (len == 0) { + fclose(fhndl); + mp_raise_ValueError("Error getting file size"); + } + uint8_t buf[256]; + if (fread(buf, 1, 256, fhndl) == 256) { + if ((img_type == IMAGE_TYPE_JPG) || (img_type == IMAGE_TYPE_PNG)) { + // Check if it is a JPG or PNG file + res = _check_jpeg(buf, &width, &height); + if (res != 0) { + #if FT8_ENABLE_PNG_LOADING + if (eve_chip_id < 0x810) { + fclose(fhndl); + mp_raise_ValueError("Only JPEG images are supported"); + } + // Not a jpeg image, check if PNG + res = _check_png(buf, &width, &height); + if (res < 0) { + // Not a PNG image + fclose(fhndl); + ESP_LOGD(TAG, "Not PNG (%d)", res); + mp_raise_ValueError("Only JPEG and PNG images are supported"); + } + opt &= 0xFFFFFFFE; + if (res == 0) { + format = FT8_L8; // Greyscale + opt |= FT8_OPT_MONO; + } + else if (res == 2) format = FT8_RGB565; // Truecolor + else if (res == 6) format = FT8_ARGB4; // Truecolor with alpha + else { + fclose(fhndl); + mp_raise_ValueError("PNG color type not supported"); + } + #else + fclose(fhndl); + mp_raise_ValueError("Only JPEG images are supported"); + #endif + } + size = width*height; + if ((opt & FT8_OPT_MONO) != 0) format = FT8_L8; + else size *= 2; + if (size > (FT8_RAM_G_SIZE-addr)) { + fclose(fhndl); + mp_raise_ValueError("No space left in Eve RAM"); + } + } + else if ((img_type == IMAGE_TYPE_RAW) || (img_type == IMAGE_TYPE_BIN)) { + // Image parameters must be given + if ((width <= 0) || (height <= 0)) { + mp_raise_ValueError("Wrong image dimensions"); + } + if ((format < 0) || (format > 7)) { + mp_raise_ValueError("Unsupported image format"); + } + size = width*height; + if (format == FT8_L1) size /= 8; + else if (format == FT8_L4) size /= 2; + else if ((format == FT8_ARGB1555) || (format == FT8_ARGB4) || (format == FT8_RGB565)) size *= 2; + if ((img_type == IMAGE_TYPE_RAW) && (size != len)) { + // We know the image size, check it + mp_raise_ValueError("Wrong image size"); + } + } + } + else { + fclose(fhndl); + mp_raise_ValueError("Error reading file image file"); + } + fseek(fhndl, 0, SEEK_SET); + } + else { + mp_raise_ValueError("Error opening file"); + } + + // set RAM_G area to zero + FT8_cmd_memzero(addr, size); + FT8_cmd_execute(250); + // Write some values to check the RAM after image decoding + FT8_memWrite32(addr+size-4, 0x1234abcd); // This should be overwritten + FT8_memWrite32(addr+size, size); // This must be the preserved + + FT8_CP_reset(); + + uint32_t tmp1, tmp2; + if ((img_type == IMAGE_TYPE_JPG) || (img_type == IMAGE_TYPE_PNG)) { + // === Decode JPG or PNG image === + #ifdef CONFIG_EVE_CHIP_TYPE1 + if ((opt & FT8_OPT_MEDIAFIFO) != 0) { + res = FT8_Fifo_init(fhndl); + if (res != 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error initializing mediafifo")); + } + res = FT8_sendDataViaMediafifo(fhndl, addr, opt, 0); + fclose(fhndl); + FT8_Fifo_deinit(); + } + else + #endif + { + res = FT8_cmd_loadimage(addr, opt, fhndl, len, 1); + + fclose(fhndl); + } + if (res < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error loading image file into EVE RAM")); + } + // == Check if the image was decoded as expected == + // Compare width and height returned by EVE Command processor with expected values + uint32_t offset = FT8_cmd_getprops(addr); + FT8_cmd_execute(250); + tmp1 = FT8_memRead32(FT8_RAM_CMD + offset); + offset += 4; + offset &= 0x0fff; + tmp2 = FT8_memRead32(FT8_RAM_CMD + offset); + if ((tmp1 != width) || (tmp2 != height)) { + ESP_LOGW(TAG, "Image dimension check failed (%d,%d) <> (%d,%d)\n", tmp1, tmp2, width, height); + } + } + else if (img_type == IMAGE_TYPE_BIN) { + // === Deflate compressed image === + res = FT8_cmd_loadimage(addr, opt, fhndl, len, 2); + ESP_LOGD(TAG, "Written bytes: %d (%d)\n", res, len); + + fclose(fhndl); + if (res < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error loading image file into EVE RAM")); + } + // == Check if the image was decoded as expected == + uint32_t offset = FT8_cmd_getptr(); + FT8_cmd_execute(250); + tmp1 = FT8_memRead32(FT8_RAM_CMD + offset); + if (tmp1 != (ft8_ramg_ptr + size)) { + ESP_LOGW(TAG, "End RAM ptr check failed (%d <> %d)\n", tmp1, ft8_ramg_ptr + size); + } + } + else if (img_type == IMAGE_TYPE_RAW) { + // === Send RAW image to RAM_G === + res = FT8_cmd_loadimage(addr, opt, fhndl, len, 3); + ESP_LOGD(TAG, "Written bytes: %d (%d)\n", res, len); + + fclose(fhndl); + if (res < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error loading image file into EVE RAM")); + } + } + + // Compare the values written to RAM before decoding + tmp1 = FT8_memRead32(FT8_RAM_G+addr+size); + tmp2 = FT8_memRead32(FT8_RAM_G+addr+size-4); + if ((tmp1 != size) || (tmp2 == 0x1234abcd)) { + ESP_LOGW(TAG, "RAM check failed: %s %s\n", (tmp1 != size) ? "Too big" : "", (tmp2 == 0x1234abcd) ? "Too small" : ""); + } + + ft8_ramg_ptr += size; + loaded_images++; + + // Create IMAGE instance object + image_eve_obj_t *self = m_new_obj(image_eve_obj_t); + memset(self, 0, sizeof(image_eve_obj_t)); + self->base.type = &image_eve_type; + + self->addr = addr; + self->width = width; + self->height = height; + self->size = size; + self->format = format; + self->orig_fmt = img_type; + self->loaded = 1; + + if (!add_ramg_object((void *)self)) { + mp_raise_ValueError("Error adding ramg object"); + } + + return MP_OBJ_FROM_PTR(self); +} + +// --------------------------------------------- +STATIC mp_obj_t IMAGE_EVE_free(mp_obj_t self_in) +{ + _check_inlist(eve_obj, 0); + image_eve_obj_t *self = (image_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_true; + + FT8_cmd_memcpy(self->addr, self->addr + self->size, ft8_ramg_ptr - (self->addr+self->size)); + bool res = FT8_cmd_execute(250); + ft8_ramg_ptr -= self->size; + loaded_images--; + self->loaded = 0; + + adjust_ramg_objects((void *)self, self->addr, self->size); + + if (res) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(IMAGE_EVE_free_obj, IMAGE_EVE_free); + +// --------------------------------------------- +STATIC mp_obj_t IMAGE_EVE_info(mp_obj_t self_in) +{ + image_eve_obj_t *self = (image_eve_obj_t *)self_in; + + image_eve_printinfo(&mp_plat_print, self, PRINT_STR); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(IMAGE_EVE_info_obj, IMAGE_EVE_info); + +// --------------------------------------------- +STATIC mp_obj_t IMAGE_EVE_props(mp_obj_t self_in) +{ + image_eve_obj_t *self = (image_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_false; + + mp_obj_t tuple[5]; + tuple[0] = mp_obj_new_int(self->addr); + tuple[1] = mp_obj_new_int(self->size); + tuple[2] = mp_obj_new_int(self->width); + tuple[3] = mp_obj_new_int(self->height); + tuple[4] = mp_obj_new_int(self->format); + + return mp_obj_new_tuple(5, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(IMAGE_EVE_props_obj, IMAGE_EVE_props); + +//-------------------------------------------------------------- +STATIC const mp_rom_map_elem_t image_eve_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&IMAGE_EVE_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&IMAGE_EVE_free_obj) }, + { MP_ROM_QSTR(MP_QSTR_props), MP_ROM_PTR(&IMAGE_EVE_props_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(image_eve_locals_dict, image_eve_locals_dict_table); + +//------------------------------------ +const mp_obj_type_t image_eve_type = { + { &mp_type_type }, + .name = MP_QSTR_IMAGE, + .print = image_eve_printinfo, + .make_new = image_eve_make_new, + .locals_dict = (mp_obj_t)&image_eve_locals_dict, +}; + +// ^^^^ IMAGE object end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +// ==== LIST object ============================================ + +// constructor +//---------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t LIST_eve_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + mp_raise_ValueError("Can only be created by 'savelist' method"); + return mp_const_none; +} + +// --------------------------------------------- +STATIC mp_obj_t LIST_EVE_free(mp_obj_t self_in) +{ + _check_inlist(eve_obj, 0); + image_eve_obj_t *self = (image_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_true; + + FT8_cmd_memcpy(self->addr, self->addr + self->size, ft8_ramg_ptr - (self->addr+self->size)); + bool res = FT8_cmd_execute(250); + ft8_ramg_ptr -= self->size; + loaded_lists--; + self->loaded = 0; + + adjust_ramg_objects((void *)self, self->addr, self->size); + + if (res) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(LIST_EVE_free_obj, LIST_EVE_free); + +// --------------------------------------------- +STATIC mp_obj_t LIST_EVE_info(mp_obj_t self_in) +{ + list_eve_obj_t *self = (list_eve_obj_t *)self_in; + + list_eve_printinfo(&mp_plat_print, self, PRINT_STR); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(LIST_EVE_info_obj, LIST_EVE_info); + +// --------------------------------------------- +STATIC mp_obj_t LIST_EVE_props(mp_obj_t self_in) +{ + list_eve_obj_t *self = (list_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_false; + + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_int(self->addr); + tuple[1] = mp_obj_new_int(self->size); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(LIST_EVE_props_obj, LIST_EVE_props); + +//------------------------------------------------------------- +STATIC const mp_rom_map_elem_t list_eve_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&LIST_EVE_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&LIST_EVE_free_obj) }, + { MP_ROM_QSTR(MP_QSTR_props), MP_ROM_PTR(&LIST_EVE_props_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(list_eve_locals_dict, list_eve_locals_dict_table); + +//----------------------------------- +const mp_obj_type_t list_eve_type = { + { &mp_type_type }, + .name = MP_QSTR_LIST, + .print = list_eve_printinfo, + .make_new = LIST_eve_make_new, + .locals_dict = (mp_obj_t)&list_eve_locals_dict, +}; + +// ^^^^ IMAGE object end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +// ==== CONSOLE object =========================================== + + +//-------------------------------------------------------- +static uint8_t console_rgb_to_vga(console_eve_obj_t *self) +{ + uint8_t c8 = 0; + c8 |= (self->fgcolor & 0x0000C0) ? 0x01 : 0; + c8 |= (self->fgcolor & 0x00C000) ? 0x02 : 0; + c8 |= (self->fgcolor & 0xC00000) ? 0x04 : 0; + c8 |= (self->fgcolor & 0x808080) ? 0x08 : 0; + + c8 |= (self->bgcolor & 0x0000C0) ? 0x10 : 0; + c8 |= (self->bgcolor & 0x00C000) ? 0x20 : 0; + c8 |= (self->bgcolor & 0xC00000) ? 0x40 : 0; + c8 |= (self->bgcolor & 0x808080) ? 0x80 : 0; + + return c8; +} + +/* +//-------------------------------------------------------------------- +static void console_vga_to_rgb(console_eve_obj_t *self, uint8_t color) +{ + uint8_t c32 = 0; + uint32_t ci = (color & 0x08) ? 0x80 : 0; + c32 |= ((color & 0x01) ? 0x7f : 0) | ci; + c32 |= ((color & 0x02) ? 0x7f00 : 0) | (ci<<8); + c32 |= ((color & 0x04) ? 0x7f0000 : 0) | (ci<<16); + self->fgcolor = c32; + + c32 = 0; + ci = (color & 0x80) ? 0x80 : 0; + c32 |= ((color & 0x01) ? 0x7f : 0) | ci; + c32 |= ((color & 0x02) ? 0x7f00 : 0) | (ci<<8); + c32 |= ((color & 0x04) ? 0x7f0000 : 0) | (ci<<16); + self->bgcolor = c32; +} +*/ + +//---------------------------------------------------------------------- +static void console_memclear(console_eve_obj_t *self, int addr, int len) +{ + if (self->type == FT8_TEXTVGA) { + len *= 2; + uint8_t row[len]; + for (int i=0; ivgacolor; + } + FT8_cmd_memwrite(addr , row, len); + } + else FT8_cmd_memset(addr, 0x20, len); + FT8_cmd_execute(250); +} + +//------------------------------------------------- +static void console_cursor(console_eve_obj_t *self) +{ + if (!self->show_cursor) return; + + uint8_t crs[2]; + crs [0] = 220; + crs[1] = 0x0E; + if (self->type == FT8_TEXTVGA) FT8_cmd_memwrite(self->curr_addr, crs, 2); + else FT8_cmd_memwrite(self->curr_addr, crs, 1); + FT8_cmd_execute(250); +} + +//------------------------------------------------ +static void console_clear(console_eve_obj_t *self) +{ + if (self->type == FT8_TEXTVGA) { + for (int i=0; iheight; i++) { + console_memclear(self, self->addr + (self->rowbytes * i), self->width); + } + } + else { + FT8_cmd_memset(self->addr, 0x20, self->size); + FT8_cmd_execute(250); + } +} + +//------------------------------------------------- +static void console_scroll(console_eve_obj_t *self) +{ + // scroll + FT8_cmd_memcpy(self->addr, self->addr + self->rowbytes, self->size - self->rowbytes); + FT8_cmd_execute(250); + // clear the last row + self->y = self->height - 1; + self->x = 0; + self->curr_addr = self->addr + (self->size - self->rowbytes); + console_memclear(self, self->addr + (self->rowbytes * self->y), self->width); + console_cursor(self); + return; +} + +//----------------------------------------------------------------------------------------- +static void console_row_add(console_eve_obj_t *self, uint8_t * row, uint8_t c, int *rowpos) +{ + uint8_t n = 1; + if (self->type == FT8_TEXTVGA) { + row[*rowpos] = c; + row[*rowpos+1] = self->vgacolor; + n = 2; + } + else row[*rowpos] = c; + *rowpos += n; +} + +//---------------------------------------------------------------------------- +static void _console_write_row(console_eve_obj_t *self, uint8_t *row, int len) +{ + if (len == 0) return; + FT8_cmd_memwrite(self->curr_addr, row, len); + FT8_cmd_execute(250); +} + +//------------------------------------------------------------ +static void _console_addrinc(console_eve_obj_t *self, int len) +{ + if (len == 0) return; + // set cursor and current address + self->curr_addr += len; + self->y = (self->curr_addr-self->addr) / self->rowbytes; + self->x = (self->curr_addr-self->addr) % self->rowbytes; + if (self->type == FT8_TEXTVGA) self->x /= 2; + if (self->y >= self->height) console_scroll(self); +} + +//--------------------------------------------------------------------------- +static void console_write_row(console_eve_obj_t *self, uint8_t *row, int len) +{ + _console_write_row(self, row, len); + _console_addrinc(self, len); +} + +//--------------------------------------------------------------------------- +static void console_write_blank_eol(console_eve_obj_t *self, uint8_t addrinc) +{ + int len = 0; + if (self->type == FT8_TEXTVGA) { + len = self->rowbytes - (self->x*2); + uint8_t buff16[len]; + for (int i=0; ivgacolor; + } + _console_write_row(self, buff16, len); + } + else { + len = self->rowbytes - self->x; + uint8_t buff8[len]; + for (int i=0; ix = 0; + self->y++; + if (self->y >= self->height) console_scroll(self); + else { + if (self->type == FT8_TEXTVGA) self->curr_addr = self->addr + (self->rowbytes * self->y) + (self->x * 2); + else self->curr_addr = self->addr + (self->rowbytes * self->y) + self->x; + } +} + + +// constructor +//------------------------------------------------------------------------------------------------------------------ +STATIC mp_obj_t console_eve_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_x, ARG_y, ARG_type, ARG_scale }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_type, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = FT8_TEXT8X8 } }, + { MP_QSTR_scale, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _check_inlist(eve_obj, 0); + + int format = args[ARG_type].u_int; + if ((format != FT8_TEXT8X8) && (format != FT8_TEXTVGA)) { + mp_raise_ValueError("Unsupported console type"); + } + uint16_t x = args[ARG_x].u_int; + uint16_t y = args[ARG_y].u_int; + uint16_t rowbytes = x; + uint32_t size = x * y; + if (format == FT8_TEXTVGA) { + size *= 2; + rowbytes *= 2; + } + + uint32_t addr = ft8_ramg_ptr; // address in Eve RAM_G + if (size > (FT8_RAM_G_SIZE-addr)) { + mp_raise_ValueError("No space left in Eve RAM"); + } + + mp_float_t fscale=1.0; + if (args[ARG_scale].u_obj != mp_const_none) { + fscale = mp_obj_get_float(args[ARG_scale].u_obj); + if (fscale < 1.2) fscale = 1.0; + } + + // Create console instance object + console_eve_obj_t *self = m_new_obj(console_eve_obj_t); + memset(self, 0, sizeof(console_eve_obj_t)); + self->base.type = &console_eve_type; + + self->addr = addr; + self->size = size; + self->curr_addr = addr; + self->x = 0; + self->y = 0; + self->width = x; + self->height = y; + self->rowbytes = rowbytes; + self->scale = fscale; + self->rowspace = 0; + self->fgcolor = 0x0000FF00; + self->bgcolor = 0; + self->type = format; + self->show_cursor = 0; + self->wrap = 0; + self->loaded = 1; + self->vgacolor = console_rgb_to_vga(self); + + if (!add_ramg_object((void *)self)) { + mp_raise_ValueError("Error adding ramg object"); + } + + ft8_ramg_ptr += size; + + console_clear(self); + console_cursor(self); + + return MP_OBJ_FROM_PTR(self); +} + +//------------------------------------------------ +STATIC mp_obj_t CONSOLE_EVE_free(mp_obj_t self_in) +{ + _check_inlist(eve_obj, 0); + console_eve_obj_t *self = (console_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_true; + + FT8_cmd_memcpy(self->addr, self->addr + self->size, ft8_ramg_ptr - (self->addr+self->size)); + bool res = FT8_cmd_execute(250); + ft8_ramg_ptr -= self->size; + self->loaded = 0; + + adjust_ramg_objects((void *)self, self->addr, self->size); + + if (res) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(CONSOLE_EVE_free_obj, CONSOLE_EVE_free); + +//-------------------------------------------------------------------- +STATIC mp_obj_t CONSOLE_EVE_clear(size_t n_args, const mp_obj_t *args) +{ + _check_inlist(eve_obj, 0); + console_eve_obj_t *self = (console_eve_obj_t *)args[0]; + if (self->loaded == 0) return mp_const_true; + + if (n_args > 1) { + int y = mp_obj_get_int(args[1]); + if (y < 0) y = 0; + if (y >= self->height) y = self->height - 1; + console_memclear(self, self->addr + (self->rowbytes * y), self->width); + } + else { + self->x = 0; + self->y = 0; + self->fgcolor = 0x0000FF00; + self->bgcolor = 0; + self->vgacolor = console_rgb_to_vga(self); + console_clear(self); + } + self->curr_addr = self->addr; + console_cursor(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(CONSOLE_EVE_clear_obj, 1, 2, CONSOLE_EVE_clear); + +//--------------------------------------------------------------------------------------------- +STATIC mp_obj_t CONSOLE_EVE_show(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_x, ARG_y, ARG_rowspace, ARG_filter, ARG_cursor, ARG_color, ARG_bgcolor, ARG_wrap }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_rowspace, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_filter, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = FT8_NEAREST } }, + { MP_QSTR_cursor, MP_ARG_KW_ONLY | MP_ARG_BOOL,{ .u_bool = false } }, + { MP_QSTR_fgcolor, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_bgcolor, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + }; + _check_inlist(eve_obj, 1); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + console_eve_obj_t *self = pos_args[0]; + + if (self->loaded == 0) { + mp_raise_ValueError("Unloaded"); + } + + if (args[ARG_color].u_int >= 0) { + self->fgcolor = args[ARG_color].u_int; + self->vgacolor = console_rgb_to_vga(self); + } + if (args[ARG_bgcolor].u_int >= 0) { + self->bgcolor = args[ARG_bgcolor].u_int; + self->vgacolor = console_rgb_to_vga(self); + } + if (args[ARG_wrap].u_int >= 0) self->wrap = args[ARG_wrap].u_int & 1; + self->show_cursor = args[ARG_cursor].u_bool; + int rowspace = self->rowspace; + if (args[ARG_rowspace].u_int >= 0) { + rowspace = args[ARG_rowspace].u_int; + if (rowspace < 0) rowspace = 0; + if (rowspace > 8) rowspace = 8; + } + if (self->rowspace != rowspace) self->rowspace = rowspace; + int x = args[ARG_x].u_int; + int y = args[ARG_y].u_int; + uint16_t width = self->width * 8 ; + uint16_t swidth = width; + uint16_t height = 8; + uint16_t sheight = height; + uint16_t stride = (width*2) >> stride_factor[self->type]; + uint8_t filter = args[ARG_filter].u_int & 1; + int32_t scale=0; + if (self->scale > 1.19) { + //filter = FT8_BILINEAR; + swidth = (int16_t)(self->scale * width); + sheight = (int16_t)(self->scale * height); + scale = (int32_t)(self->scale * 65536); + } + + if (self->type == FT8_TEXTVGA) { + height *= 2; + sheight *= 2; + // draw backgroung rectangle + FT8_cmd_dl(DL_COLOR_RGB | (self->bgcolor & 0x00ffffff)); + FT8_cmd_rect(x, y, x+swidth, y+((sheight+self->rowspace)*self->height), 1); + // to draw characters non transparent + FT8_cmd_dl(DL_COLOR_RGB | 0x00ffffff); + FT8_cmd_dl(BLEND_FUNC(FT8_ONE, FT8_ZERO)); + } + else { + // draw backgroung rectangle + FT8_cmd_dl(DL_COLOR_RGB | (self->bgcolor & 0x00ffffff)); + FT8_cmd_rect(x, y, x+swidth, y+((sheight+self->rowspace)*self->height), 1); + } + + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_LAYOUT_H(stride>>10, height>>9)); + #endif + FT8_cmd_dl(BITMAP_LAYOUT(self->type, stride , height)); + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_SIZE_H(swidth>>9, sheight>>9)); + #endif + FT8_cmd_dl(BITMAP_SIZE(filter, FT8_BORDER, FT8_BORDER, swidth, sheight)); + if (scale) { + FT8_cmd_dl(CMD_LOADIDENTITY); + FT8_cmd_scale(scale, scale); + FT8_cmd_setmatrix(); + } + FT8_cmd_dl(DL_BEGIN | FT8_BITMAPS); + if (self->type == FT8_TEXT8X8) FT8_cmd_dl(DL_COLOR_RGB | (self->fgcolor & 0x00ffffff)); + + for (int i=0; iheight; i++) { + FT8_cmd_dl(BITMAP_SOURCE(self->addr + (self->rowbytes * i))); + FT8_cmd_dl(VERTEX2F(x*16, (y + (i*(sheight+self->rowspace)))*16)); + } + FT8_cmd_dl(DL_END); + if (self->type == FT8_TEXTVGA) { + FT8_cmd_dl(BLEND_FUNC(FT8_SRC_ALPHA, FT8_ONE_MINUS_SRC_ALPHA)); + } + if (scale) { + FT8_cmd_dl(CMD_LOADIDENTITY); + FT8_cmd_scale(65536, 65536); + FT8_cmd_setmatrix(); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(CONSOLE_EVE_show_obj, 0, CONSOLE_EVE_show); + +//--------------------------------------------------------------------------------------------- +STATIC mp_obj_t CONSOLE_EVE_text(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_text, ARG_x, ARG_y, ARG_color, ARG_bgcolor }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_x, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_y, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fgcolor, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_bgcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + _check_inlist(eve_obj, 0); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + console_eve_obj_t *self = pos_args[0]; + if (self->loaded == 0) { + mp_raise_ValueError("Unloaded"); + } + + const char *st = mp_obj_str_get_str(args[ARG_text].u_obj); + if (strlen(st) == 0) return mp_const_none; + + // create the row buffer + uint8_t row[self->rowbytes]; + + int idx=0; + int len = strlen(st); + int rowstart, rowpos, lastblank; + uint8_t bpc = (self->type == FT8_TEXTVGA) ? 2 : 1; + uint16_t x = self->x; + uint16_t y = self->y; + if (args[ARG_color].u_int >= 0) { + self->fgcolor = args[ARG_color].u_int; + self->vgacolor = console_rgb_to_vga(self); + } + if (args[ARG_bgcolor].u_int >= 0) { + self->bgcolor = args[ARG_bgcolor].u_int; + self->vgacolor = console_rgb_to_vga(self); + } + + if ((args[ARG_x].u_int >= 0) || (args[ARG_y].u_int >= 0)) { + if (args[ARG_x].u_int >= 0) x = args[ARG_x].u_int; + if (args[ARG_y].u_int >= 0) y = args[ARG_y].u_int; + if ((x >= self->width) || (y >= self->height)) { + mp_raise_ValueError("Position outside console area"); + } + self->x = x; + self->y = y; + if (self->type == FT8_TEXTVGA) self->curr_addr = self->addr + (self->rowbytes * y) + (x * 2); + else self->curr_addr = self->addr + (self->rowbytes * y) + x; + console_cursor(self); + } + + rowstart = self->x; + rowpos = rowstart; + lastblank = -1; + + uint8_t vgacolor = self->vgacolor; // save original vga color + while (idx < len) { + if (st[idx] == 0x08) { + // *** ('\b'), set color if in TEXTVGA mode + idx++; + if (idx >= len) break; + if (self->type == FT8_TEXTVGA) { + // set color + if (st[idx] == 0xff) self->vgacolor = vgacolor; + else self->vgacolor = st[idx]; + } + idx++; + } + else if (st[idx] == 0x0A) { + // *** new line ('\n') + console_write_row(self, row+rowstart, rowpos-rowstart); + console_new_line(self); + rowstart = self->x; + rowpos = rowstart; + lastblank = -1; + idx++; + } + else if (st[idx] == 0x0D) { + // *** clear to the end of line ('\r'), preserve position + console_write_row(self, row+rowstart, rowpos-rowstart); + if (self->x > 0) console_write_blank_eol(self, 0); + rowstart = self->x; + rowpos = rowstart; + lastblank = -1; + idx++; + } + /* + else if (st[idx] == '\t') { + // *** tab, write 4 spaces + if ((self->rowbytes - rowpos) >= 4) { + for (int n=0; n<4; n++) { + console_row_add(self, row, 0x20, &rowpos); + } + } + idx++; + } + */ + else if (st[idx] < 32) idx++; // ignore non-printable characters + else { + // printable character, add it to row buffer + if (st[idx] == 0x20) lastblank = rowpos; + console_row_add(self, row, st[idx], &rowpos); + + if (rowpos >= self->rowbytes) { + // === row buffer filled, write it === + if ((self->wrap) && (lastblank >= 0)) { + // word wrapping is used, write up to the last blank character + // and advance row position + console_write_row(self, row+rowstart, lastblank-rowstart); + if (self->x > 0) console_write_blank_eol(self, 1); + // write remaining characters + rowstart = lastblank + bpc; + } + console_write_row(self, row+rowstart, rowpos-rowstart); + rowstart = self->x; + rowpos = rowstart; + lastblank = -1; + } + idx++; + } + } + if (rowpos > 0) console_write_row(self, row+rowstart, rowpos-rowstart); + + self->vgacolor = vgacolor; // restore original vga color + console_cursor(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(CONSOLE_EVE_text_obj, 0, CONSOLE_EVE_text); + + +//---------------------------------------------------------------- +STATIC const mp_rom_map_elem_t console_eve_locals_dict_table[] = { + // instance methods + //{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&CONSOLE_EVE_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&CONSOLE_EVE_free_obj) }, + { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&CONSOLE_EVE_show_obj) }, + { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&CONSOLE_EVE_text_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&CONSOLE_EVE_clear_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(console_eve_locals_dict, console_eve_locals_dict_table); + + +//----------------------------------- +const mp_obj_type_t console_eve_type = { + { &mp_type_type }, + .name = MP_QSTR_CONSOLE, + .print = console_eve_printinfo, + .make_new = console_eve_make_new, + .locals_dict = (mp_obj_t)&console_eve_locals_dict, +}; + +// ^^^^ CONSOLE object end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +#ifdef CONFIG_MICROPY_USE_TFT + +// ==== TFT object =============================================== + + +// constructor +//--------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t tft_eve_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + enum { ARG_x, ARG_y, ARG_type }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_type, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = FT8_RGB332 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _check_inlist(eve_obj, 0); + + int format = args[ARG_type].u_int; + if ((format != FT8_RGB332) && (format != FT8_RGB565)) { + mp_raise_ValueError("Unsupported console type"); + } + uint16_t x = args[ARG_x].u_int; + uint16_t y = args[ARG_y].u_int; + uint32_t size = x * y; + uint16_t rowsize = x; + uint8_t bpp = 1; + if (format == FT8_RGB565) { + size *= 2; + rowsize *= 2; + bpp = 2; + } + + uint32_t addr = ft8_ramg_ptr; // address in Eve RAM_G + if (size > (FT8_RAM_G_SIZE-addr)) { + mp_raise_ValueError("No space left in Eve RAM"); + } + + // Create tft instance object + tft_eve_obj_t *self = m_new_obj(tft_eve_obj_t); + memset(self, 0, sizeof(tft_eve_obj_t)); + self->base.type = &tft_eve_type; + + self->addr = addr; + self->size = size; + self->width = x; + self->height = y; + self->rowsize = rowsize; + self->byte_per_pixel = bpp; + self->type = format; + self->loaded = 1; + self->prev_tft_mode = tft_active_mode; + + if (!add_ramg_object((void *)self)) { + mp_raise_ValueError("Error adding ramg object"); + } + + ft8_ramg_ptr += size; + eve_tft_obj = NULL; + + FT8_cmd_memzero(self->addr, self->size); + FT8_cmd_execute(250); + + return MP_OBJ_FROM_PTR(self); +} + +//-------------------------------------------- +STATIC mp_obj_t TFT_EVE_free(mp_obj_t self_in) +{ + _check_inlist(eve_obj, 0); + tft_eve_obj_t *self = (tft_eve_obj_t *)self_in; + if (self->loaded == 0) return mp_const_true; + + FT8_cmd_memcpy(self->addr, self->addr + self->size, ft8_ramg_ptr - (self->addr+self->size)); + bool res = FT8_cmd_execute(250); + ft8_ramg_ptr -= self->size; + self->loaded = 0; + + adjust_ramg_objects((void *)self, self->addr, self->size); + + if (res) return mp_const_true; + return mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(TFT_EVE_free_obj, TFT_EVE_free); + +//------------------------------------------------ +static void _tft_eve_activate(tft_eve_obj_t *self) +{ + self->prev_tft_mode = tft_active_mode; + tft_active_mode = TFT_MODE_EVE; + disp_spi = NULL; + // === SET TFT GLOBAL VARIABLES + TFT_saveClipWin(); + _width = self->width; + _height = self->height; + dispWin.x1 = 0; + dispWin.y1 = 0; + dispWin.x2 = _width; + dispWin.y2 = _height; +} + +//------------------------------------------------ +STATIC mp_obj_t TFT_EVE_activate(mp_obj_t self_in) +{ + tft_eve_obj_t *self = (tft_eve_obj_t *)self_in; + eve_tft_obj = self; + if (tft_active_mode != TFT_MODE_EVE) _tft_eve_activate(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(TFT_EVE_activate_obj, TFT_EVE_activate); + +//-------------------------------------------------- +STATIC mp_obj_t TFT_EVE_deactivate(mp_obj_t self_in) +{ + tft_eve_obj_t *self = (tft_eve_obj_t *)self_in; + if (tft_active_mode == TFT_MODE_EVE) { + tft_active_mode = self->prev_tft_mode; + eve_tft_obj = NULL; + TFT_restoreClipWin(); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(TFT_EVE_deactivate_obj, TFT_EVE_deactivate); + +//-------------------------------------------------------------------- +STATIC mp_obj_t TFT_EVE_clear(size_t n_args, const mp_obj_t *args) +{ + _check_inlist(eve_obj, 0); + tft_eve_obj_t *self = (tft_eve_obj_t *)args[0]; + if (self->loaded == 0) return mp_const_true; + + FT8_cmd_memzero(self->addr, self->size); + FT8_cmd_execute(250); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(TFT_EVE_clear_obj, 1, 2, TFT_EVE_clear); + +//----------------------------------------------------------------------------------------- +STATIC mp_obj_t TFT_EVE_show(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_x, ARG_y }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + }; + _check_inlist(eve_obj, 1); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + tft_eve_obj_t *self = pos_args[0]; + + if (self->loaded == 0) { + mp_raise_ValueError("Unloaded"); + } + + int x = args[ARG_x].u_int; + int y = args[ARG_y].u_int; + + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_LAYOUT_H(self->rowsize>>10, self->height>>9)); + #endif + FT8_cmd_dl(BITMAP_LAYOUT(self->type, self->rowsize , self->height)); + #ifdef CONFIG_EVE_CHIP_TYPE1 + FT8_cmd_dl(BITMAP_SIZE_H(self->width>>9, self->height>>9)); + #endif + FT8_cmd_dl(BITMAP_SIZE(FT8_NEAREST, FT8_BORDER, FT8_BORDER, self->width, self->height)); + FT8_cmd_dl(DL_BEGIN | FT8_BITMAPS); + FT8_cmd_dl(BITMAP_SOURCE(self->addr)); + FT8_cmd_dl(VERTEX2F(x*16, y*16)); + FT8_cmd_dl(DL_END); + + eve_tft_obj = self; + if (tft_active_mode != TFT_MODE_EVE) _tft_eve_activate(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(TFT_EVE_show_obj, 0, TFT_EVE_show); + +//------------------------------------------------------------ +STATIC const mp_rom_map_elem_t tft_eve_locals_dict_table[] = { + // instance methods + //{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&TFT_EVE_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_free), MP_ROM_PTR(&TFT_EVE_free_obj) }, + { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&TFT_EVE_activate_obj) }, + { MP_ROM_QSTR(MP_QSTR_deselect), MP_ROM_PTR(&TFT_EVE_deactivate_obj) }, + { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&TFT_EVE_show_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&TFT_EVE_clear_obj) }, + + { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&display_tft_drawPixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&display_tft_drawLine_obj) }, + { MP_ROM_QSTR(MP_QSTR_lineByAngle), MP_ROM_PTR(&display_tft_drawLineByAngle_obj) }, + { MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&display_tft_drawTriangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&display_tft_drawCircle_obj) }, + { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&display_tft_drawEllipse_obj) }, + { MP_ROM_QSTR(MP_QSTR_arc), MP_ROM_PTR(&display_tft_drawArc_obj) }, + { MP_ROM_QSTR(MP_QSTR_polygon), MP_ROM_PTR(&display_tft_drawPoly_obj) }, + { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&display_tft_drawRect_obj) }, + { MP_ROM_QSTR(MP_QSTR_roundrect), MP_ROM_PTR(&display_tft_drawRoundRect_obj) }, + { MP_ROM_QSTR(MP_QSTR_font), MP_ROM_PTR(&display_tft_setFont_obj) }, + { MP_ROM_QSTR(MP_QSTR_fontSize), MP_ROM_PTR(&display_tft_getFontSize_obj) }, + { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&display_tft_print_obj) }, + { MP_ROM_QSTR(MP_QSTR_screensize), MP_ROM_PTR(&display_tft_getSize_obj) }, + { MP_ROM_QSTR(MP_QSTR_setwin), MP_ROM_PTR(&display_tft_setclipwin_obj) }, + { MP_ROM_QSTR(MP_QSTR_resetwin), MP_ROM_PTR(&display_tft_resetclipwin_obj) }, + + // Constants + { MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(CENTER) }, + { MP_ROM_QSTR(MP_QSTR_RIGHT), MP_ROM_INT(RIGHT) }, + { MP_ROM_QSTR(MP_QSTR_BOTTOM), MP_ROM_INT(BOTTOM) }, + { MP_ROM_QSTR(MP_QSTR_LASTX), MP_ROM_INT(LASTX) }, + { MP_ROM_QSTR(MP_QSTR_LASTY), MP_ROM_INT(LASTY) }, + + { MP_ROM_QSTR(MP_QSTR_FONT_Default), MP_ROM_INT(DEFAULT_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_DejaVu18), MP_ROM_INT(DEJAVU18_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_DejaVu24), MP_ROM_INT(DEJAVU24_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Ubuntu), MP_ROM_INT(UBUNTU16_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Comic), MP_ROM_INT(COMIC24_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Minya), MP_ROM_INT(MINYA24_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Tooney), MP_ROM_INT(TOONEY32_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Small), MP_ROM_INT(SMALL_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_DefaultSmall), MP_ROM_INT(DEF_SMALL_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_7seg), MP_ROM_INT(FONT_7SEG) }, + + { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(iTFT_BLACK) }, + { MP_ROM_QSTR(MP_QSTR_NAVY), MP_ROM_INT(iTFT_NAVY) }, + { MP_ROM_QSTR(MP_QSTR_DARKGREEN), MP_ROM_INT(iTFT_DARKGREEN) }, + { MP_ROM_QSTR(MP_QSTR_DARKCYAN), MP_ROM_INT(iTFT_DARKCYAN) }, + { MP_ROM_QSTR(MP_QSTR_MAROON), MP_ROM_INT(iTFT_MAROON) }, + { MP_ROM_QSTR(MP_QSTR_PURPLE), MP_ROM_INT(iTFT_PURPLE) }, + { MP_ROM_QSTR(MP_QSTR_OLIVE), MP_ROM_INT(iTFT_OLIVE) }, + { MP_ROM_QSTR(MP_QSTR_LIGHTGREY), MP_ROM_INT(iTFT_LIGHTGREY) }, + { MP_ROM_QSTR(MP_QSTR_DARKGREY), MP_ROM_INT(iTFT_DARKGREY) }, + { MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(iTFT_BLUE) }, + { MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(iTFT_GREEN) }, + { MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(iTFT_CYAN) }, + { MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(iTFT_RED) }, + { MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(iTFT_MAGENTA) }, + { MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(iTFT_YELLOW) }, + { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(iTFT_WHITE) }, + { MP_ROM_QSTR(MP_QSTR_ORANGE), MP_ROM_INT(iTFT_ORANGE) }, + { MP_ROM_QSTR(MP_QSTR_GREENYELLOW), MP_ROM_INT(iTFT_GREENYELLOW) }, + { MP_ROM_QSTR(MP_QSTR_PINK), MP_ROM_INT(iTFT_PINK) }, +}; +STATIC MP_DEFINE_CONST_DICT(tft_eve_locals_dict, tft_eve_locals_dict_table); + + +//----------------------------------- +const mp_obj_type_t tft_eve_type = { + { &mp_type_type }, + .name = MP_QSTR_TFT, + .print = tft_eve_printinfo, + .make_new = tft_eve_make_new, + .locals_dict = (mp_obj_t)&tft_eve_locals_dict, +}; + +// ^^^^ TFT object ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#endif + +//================================================================ +STATIC const mp_rom_map_elem_t display_eve_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&display_eve_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&display_eve_config_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&display_tft_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_calibrate), MP_ROM_PTR(&EVE_calibrate_obj) }, + { MP_ROM_QSTR(MP_QSTR_startlist), MP_ROM_PTR(&EVE_startlist_obj) }, + { MP_ROM_QSTR(MP_QSTR_endlist), MP_ROM_PTR(&EVE_endlist_obj) }, + { MP_ROM_QSTR(MP_QSTR_savelist), MP_ROM_PTR(&EVE_savelist_obj) }, + { MP_ROM_QSTR(MP_QSTR_appendlist), MP_ROM_PTR(&EVE_appendlist_obj) }, + { MP_ROM_QSTR(MP_QSTR_dumplist), MP_ROM_PTR(&EVE_dumplist_obj) }, + { MP_ROM_QSTR(MP_QSTR_dumpcmd), MP_ROM_PTR(&EVE_dumpcmd_obj) }, + { MP_ROM_QSTR(MP_QSTR_point), MP_ROM_PTR(&EVE_point_obj) }, + { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&EVE_circle_obj) }, + { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&EVE_line_obj) }, + { MP_ROM_QSTR(MP_QSTR_strips), MP_ROM_PTR(&EVE_strips_obj) }, + { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&EVE_rect_obj) }, + { MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&EVE_rectangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&EVE_triangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_scissorSize), MP_ROM_PTR(&EVE_scissorSize_obj) }, + { MP_ROM_QSTR(MP_QSTR_scissorXY), MP_ROM_PTR(&EVE_scissorXY_obj) }, + { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&EVE_text_obj) }, + { MP_ROM_QSTR(MP_QSTR_number), MP_ROM_PTR(&EVE_number_obj) }, + { MP_ROM_QSTR(MP_QSTR_button), MP_ROM_PTR(&EVE_button_obj) }, + { MP_ROM_QSTR(MP_QSTR_keys), MP_ROM_PTR(&EVE_keys_obj) }, + { MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&EVE_clock_obj) }, + { MP_ROM_QSTR(MP_QSTR_gauge), MP_ROM_PTR(&EVE_gauge_obj) }, + { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&EVE_toggle_obj) }, + { MP_ROM_QSTR(MP_QSTR_scrollbar), MP_ROM_PTR(&EVE_scrollbar_obj) }, + { MP_ROM_QSTR(MP_QSTR_slider), MP_ROM_PTR(&EVE_slider_obj) }, + { MP_ROM_QSTR(MP_QSTR_progress), MP_ROM_PTR(&EVE_progress_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&EVE_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&EVE_backlight_obj) }, + { MP_ROM_QSTR(MP_QSTR_color), MP_ROM_PTR(&EVE_color_obj) }, + { MP_ROM_QSTR(MP_QSTR_fgcolor), MP_ROM_PTR(&EVE_fgcolor_obj) }, + { MP_ROM_QSTR(MP_QSTR_bgcolor), MP_ROM_PTR(&EVE_bgcolor_obj) }, + { MP_ROM_QSTR(MP_QSTR_alpha), MP_ROM_PTR(&EVE_alpha_obj) }, + { MP_ROM_QSTR(MP_QSTR_alphafunc), MP_ROM_PTR(&EVE_alphafunc_obj) }, + { MP_ROM_QSTR(MP_QSTR_colormask), MP_ROM_PTR(&EVE_colormask_obj) }, + { MP_ROM_QSTR(MP_QSTR_blend), MP_ROM_PTR(&EVE_blend_obj) }, + { MP_ROM_QSTR(MP_QSTR_stencilfunc), MP_ROM_PTR(&EVE_stencilfunc_obj) }, + { MP_ROM_QSTR(MP_QSTR_stencilmask), MP_ROM_PTR(&EVE_stencilmask_obj) }, + { MP_ROM_QSTR(MP_QSTR_stencilop), MP_ROM_PTR(&EVE_stencilop_obj) }, + { MP_ROM_QSTR(MP_QSTR_gradient), MP_ROM_PTR(&EVE_gradient_obj) }, + { MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&EVE_showimage_obj) }, + { MP_ROM_QSTR(MP_QSTR_setbitmap), MP_ROM_PTR(&EVE_setbitmap_obj) }, + #ifdef CONFIG_EVE_CHIP_TYPE1 + { MP_ROM_QSTR(MP_QSTR_video), MP_ROM_PTR(&EVE_playvideo_obj) }, + { MP_ROM_QSTR(MP_QSTR_closevideo), MP_ROM_PTR(&EVE_closevideo_obj) }, + { MP_ROM_QSTR(MP_QSTR_videoframe), MP_ROM_PTR(&EVE_videoframe_obj) }, + { MP_ROM_QSTR(MP_QSTR_lastframe), MP_ROM_PTR(&EVE_lastframe_obj) }, + { MP_ROM_QSTR(MP_QSTR_videobuffer), MP_ROM_PTR(&EVE_videobuffer_obj) }, + { MP_ROM_QSTR(MP_QSTR_rotate), MP_ROM_PTR(&EVE_rotate_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_getprops), MP_ROM_PTR(&EVE_getprops_obj) }, + { MP_ROM_QSTR(MP_QSTR_userfont), MP_ROM_PTR(&EVE_userfont_obj) }, + { MP_ROM_QSTR(MP_QSTR_fontinfo), MP_ROM_PTR(&EVE_fontinfo_obj) }, + { MP_ROM_QSTR(MP_QSTR_freeobjects), MP_ROM_PTR(&EVE_freeobjects_obj) }, + { MP_ROM_QSTR(MP_QSTR_memWrite), MP_ROM_PTR(&EVE_memWrite_obj) }, + { MP_ROM_QSTR(MP_QSTR_memRead), MP_ROM_PTR(&EVE_memRead_obj) }, + { MP_ROM_QSTR(MP_QSTR_memZero), MP_ROM_PTR(&EVE_memZero_obj) }, + { MP_ROM_QSTR(MP_QSTR_memSet), MP_ROM_PTR(&EVE_memSet_obj) }, + { MP_ROM_QSTR(MP_QSTR_tag), MP_ROM_PTR(&EVE_tag_obj) }, + { MP_ROM_QSTR(MP_QSTR_tagmask), MP_ROM_PTR(&EVE_tagmask_obj) }, + { MP_ROM_QSTR(MP_QSTR_gettag), MP_ROM_PTR(&EVE_gettag_obj) }, + { MP_ROM_QSTR(MP_QSTR_gettagXY), MP_ROM_PTR(&EVE_gettagXY_obj) }, + { MP_ROM_QSTR(MP_QSTR_touchXY), MP_ROM_PTR(&EVE_touchXY_obj) }, + { MP_ROM_QSTR(MP_QSTR_vol_play), MP_ROM_PTR(&EVE_vol_pb_obj) }, + { MP_ROM_QSTR(MP_QSTR_vol_sound), MP_ROM_PTR(&EVE_vol_sound_obj) }, + { MP_ROM_QSTR(MP_QSTR_sound), MP_ROM_PTR(&EVE_sound_obj) }, + { MP_ROM_QSTR(MP_QSTR_screensize), MP_ROM_PTR(&EVE_screensize_obj) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_Font), MP_ROM_PTR(&font_eve_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_Image), MP_ROM_PTR(&image_eve_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_Console), MP_ROM_PTR(&console_eve_type) }, + #ifdef CONFIG_MICROPY_USE_TFT + { MP_OBJ_NEW_QSTR(MP_QSTR_Tft), MP_ROM_PTR(&tft_eve_type) }, + #endif + + // SPI bus constants + { MP_ROM_QSTR(MP_QSTR_HSPI), MP_ROM_INT(HSPI_HOST) }, + { MP_ROM_QSTR(MP_QSTR_VSPI), MP_ROM_INT(VSPI_HOST) }, + + // Options constants + { MP_ROM_QSTR(MP_QSTR_OPT_CENTERX), MP_ROM_INT(FT8_OPT_CENTERX) }, + { MP_ROM_QSTR(MP_QSTR_OPT_CENTERY), MP_ROM_INT(FT8_OPT_CENTERY) }, + { MP_ROM_QSTR(MP_QSTR_OPT_CENTER), MP_ROM_INT(FT8_OPT_CENTER) }, + { MP_ROM_QSTR(MP_QSTR_OPT_RIGHTX), MP_ROM_INT(FT8_OPT_RIGHTX) }, + { MP_ROM_QSTR(MP_QSTR_OPT_LEFTX), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_OPT_FLAT), MP_ROM_INT(FT8_OPT_FLAT) }, + { MP_ROM_QSTR(MP_QSTR_OPT_3D), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_OPT_MONO), MP_ROM_INT(FT8_OPT_MONO) }, + { MP_ROM_QSTR(MP_QSTR_OPT_NODL), MP_ROM_INT(FT8_OPT_NODL) }, + { MP_ROM_QSTR(MP_QSTR_OPT_SIGNED), MP_ROM_INT(FT8_OPT_SIGNED) }, + { MP_ROM_QSTR(MP_QSTR_OPT_NOBACK), MP_ROM_INT(FT8_OPT_NOBACK) }, + { MP_ROM_QSTR(MP_QSTR_OPT_NOTICKS), MP_ROM_INT(FT8_OPT_NOTICKS) }, + { MP_ROM_QSTR(MP_QSTR_OPT_NOPOINTER), MP_ROM_INT(FT8_OPT_NOPOINTER) }, + { MP_ROM_QSTR(MP_QSTR_OPT_NOHANDS), MP_ROM_INT(FT8_OPT_NOHANDS) }, + { MP_ROM_QSTR(MP_QSTR_OPT_NOSECS), MP_ROM_INT(FT8_OPT_NOSECS) }, + #ifdef CONFIG_EVE_CHIP_TYPE1 + { MP_ROM_QSTR(MP_QSTR_OPT_NOTEAR), MP_ROM_INT(FT8_OPT_NOTEAR) }, + { MP_ROM_QSTR(MP_QSTR_OPT_FULLSCREEN), MP_ROM_INT(FT8_OPT_FULLSCREEN) }, + { MP_ROM_QSTR(MP_QSTR_OPT_MEDIAFIFO), MP_ROM_INT(FT8_OPT_MEDIAFIFO) }, + { MP_ROM_QSTR(MP_QSTR_OPT_SOUND), MP_ROM_INT(FT8_OPT_SOUND) }, + { MP_ROM_QSTR(MP_QSTR_OPT_RGB565), MP_ROM_INT(0) }, + #endif + + // Blend constants + { MP_ROM_QSTR(MP_QSTR_ZERO), MP_ROM_INT(FT8_ZERO) }, + { MP_ROM_QSTR(MP_QSTR_ONE), MP_ROM_INT(FT8_ONE) }, + { MP_ROM_QSTR(MP_QSTR_SRC_ALPHA), MP_ROM_INT(FT8_SRC_ALPHA) }, + { MP_ROM_QSTR(MP_QSTR_DST_ALPHA), MP_ROM_INT(FT8_DST_ALPHA) }, + { MP_ROM_QSTR(MP_QSTR_ONE_MINUS_SRC_ALPHA), MP_ROM_INT(FT8_ONE_MINUS_SRC_ALPHA) }, + { MP_ROM_QSTR(MP_QSTR_ONE_MINUS_DST_ALPHA), MP_ROM_INT(FT8_ONE_MINUS_DST_ALPHA) }, + + // Bitmap Wrap & Filter constants + { MP_ROM_QSTR(MP_QSTR_NEAREST), MP_ROM_INT(FT8_NEAREST) }, + { MP_ROM_QSTR(MP_QSTR_BILINEAR), MP_ROM_INT(FT8_BILINEAR) }, + { MP_ROM_QSTR(MP_QSTR_BORDER), MP_ROM_INT(FT8_BORDER) }, + { MP_ROM_QSTR(MP_QSTR_REPEAT), MP_ROM_INT(FT8_REPEAT) }, + + // Bitmap format constants + { MP_ROM_QSTR(MP_QSTR_IMG_ARGB1555), MP_ROM_INT(FT8_ARGB1555) }, + { MP_ROM_QSTR(MP_QSTR_IMG_L1), MP_ROM_INT(FT8_L1) }, + #ifdef CONFIG_EVE_CHIP_TYPE1 + { MP_ROM_QSTR(MP_QSTR_IMG_L2), MP_ROM_INT(FT8_L2) }, + #endif + { MP_ROM_QSTR(MP_QSTR_IMG_L4), MP_ROM_INT(FT8_L4) }, + { MP_ROM_QSTR(MP_QSTR_IMG_L8), MP_ROM_INT(FT8_L8) }, + { MP_ROM_QSTR(MP_QSTR_IMG_RGB332), MP_ROM_INT(FT8_RGB332) }, + { MP_ROM_QSTR(MP_QSTR_IMG_ARGB2), MP_ROM_INT(FT8_ARGB2) }, + { MP_ROM_QSTR(MP_QSTR_IMG_ARGB4), MP_ROM_INT(FT8_ARGB4) }, + { MP_ROM_QSTR(MP_QSTR_IMG_RGB565), MP_ROM_INT(FT8_RGB565) }, + { MP_ROM_QSTR(MP_QSTR_BMP_TEXT8X8), MP_ROM_INT(FT8_TEXT8X8) }, + { MP_ROM_QSTR(MP_QSTR_BMP_TEXTVGA), MP_ROM_INT(FT8_TEXTVGA) }, + { MP_ROM_QSTR(MP_QSTR_BMP_PALETTED), MP_ROM_INT(FT8_PALETTED) }, + { MP_ROM_QSTR(MP_QSTR_BMP_BARGRAPH), MP_ROM_INT(FT8_BARGRAPH) }, + + // Image type constants + { MP_ROM_QSTR(MP_QSTR_IMG_PNG), MP_ROM_INT(IMAGE_TYPE_PNG) }, + { MP_ROM_QSTR(MP_QSTR_IMG_JPG), MP_ROM_INT(IMAGE_TYPE_JPG) }, + { MP_ROM_QSTR(MP_QSTR_IMG_RAW), MP_ROM_INT(IMAGE_TYPE_RAW) }, + { MP_ROM_QSTR(MP_QSTR_IMG_COMPRESSED), MP_ROM_INT(IMAGE_TYPE_BIN) }, + { MP_ROM_QSTR(MP_QSTR_IMG_AUTO), MP_ROM_INT(IMAGE_TYPE_NONE) }, + + // Color constants + { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(EVE_BLACK) }, + { MP_ROM_QSTR(MP_QSTR_NAVY), MP_ROM_INT(EVE_NAVY) }, + { MP_ROM_QSTR(MP_QSTR_DARKGREEN), MP_ROM_INT(EVE_DARKGREEN) }, + { MP_ROM_QSTR(MP_QSTR_DARKCYAN), MP_ROM_INT(EVE_DARKCYAN) }, + { MP_ROM_QSTR(MP_QSTR_MAROON), MP_ROM_INT(EVE_MAROON) }, + { MP_ROM_QSTR(MP_QSTR_PURPLE), MP_ROM_INT(EVE_PURPLE) }, + { MP_ROM_QSTR(MP_QSTR_OLIVE), MP_ROM_INT(EVE_OLIVE) }, + { MP_ROM_QSTR(MP_QSTR_LIGHTGREY), MP_ROM_INT(EVE_LIGHTGREY) }, + { MP_ROM_QSTR(MP_QSTR_DARKGREY), MP_ROM_INT(EVE_DARKGREY) }, + { MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(EVE_BLUE) }, + { MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(EVE_GREEN) }, + { MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(EVE_CYAN) }, + { MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(EVE_RED) }, + { MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(EVE_MAGENTA) }, + { MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(EVE_YELLOW) }, + { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(EVE_WHITE) }, + { MP_ROM_QSTR(MP_QSTR_ORANGE), MP_ROM_INT(EVE_ORANGE) }, + { MP_ROM_QSTR(MP_QSTR_GREENYELLOW), MP_ROM_INT(EVE_GREENYELLOW) }, + { MP_ROM_QSTR(MP_QSTR_PINK), MP_ROM_INT(EVE_PINK) }, + + // Rotation constants + { MP_ROM_QSTR(MP_QSTR_LANDSCAPE), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_LANDSCAPE_FLIP), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_PORTRAIT), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_PORTRAIT_FLIP), MP_ROM_INT(3) }, + { MP_ROM_QSTR(MP_QSTR_MIRRORED), MP_ROM_INT(4) }, +}; +STATIC MP_DEFINE_CONST_DICT(display_eve_locals_dict, display_eve_locals_dict_table); + + +//====================================== +const mp_obj_type_t display_eve_type = { + { &mp_type_type }, + .name = MP_QSTR_EVE, + .print = display_eve_printinfo, + .make_new = display_eve_make_new, + .locals_dict = (mp_obj_t)&display_eve_locals_dict, +}; + +#endif // CONFIG_MICROPY_USE_EVE diff --git a/MicroPython_BUILD/components/micropython/esp32/moddisplay_tft.c b/MicroPython_BUILD/components/micropython/esp32/moddisplay_tft.c new file mode 100644 index 00000000..dc72b701 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/moddisplay_tft.c @@ -0,0 +1,1968 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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 "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT + +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "rom/ets_sys.h" +#include "esp_system.h" +#include "esp_task_wdt.h" + +#include "driver/gpio.h" + +#include "tft/tftspi.h" +#include "tft/tft.h" +#include "extmod/vfs_native.h" +#include "machine_hw_spi.h" +#include "modmachine.h" +#include "libs/qrcode.h" + + +typedef struct _display_tft_obj_t { + mp_obj_base_t base; + machine_hw_spi_obj_t *spi; + display_config_t dconfig; + exspi_device_handle_t disp_spi_dev; + exspi_device_handle_t ts_spi_dev; + exspi_device_handle_t *disp_spi; + exspi_device_handle_t *ts_spi; + uint32_t tp_calx; + uint32_t tp_caly; + mp_obj_t expwm_handler; +} display_tft_obj_t; + +const mp_obj_type_t display_tft_type; + +extern uint8_t disp_used_spi_host; + +static const char* const display_types[] = { + "ILI9341", + "ILI9488", + "ST7789V", + "ST7735", + "ST7735R", + "ST7735B", + "M5STACK", + "Unknown", +}; + +static const char* const touch_types[] = { + "None", + "xpt2046", + "stmpe610", + "Unknown", +}; + +// constructor(id, ...) +//----------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) +{ + display_tft_obj_t *self = m_new_obj(display_tft_obj_t); //(display_tft_obj_t*)&display_tft_obj; + self->base.type = &display_tft_type; + self->spi = NULL; + self->disp_spi_dev.handle = NULL; + self->disp_spi_dev.cs = -1; + self->disp_spi_dev.dc = -1; + self->disp_spi_dev.selected = 0; + self->ts_spi_dev.handle = NULL; + self->ts_spi_dev.cs = -1; + self->ts_spi_dev.dc = -1; + self->ts_spi_dev.selected = 0; + self->disp_spi = &self->disp_spi_dev; + self->ts_spi = &self->ts_spi_dev; + + //return (mp_obj_t)&display_tft_obj; + return MP_OBJ_FROM_PTR(self); +} + +//----------------------------------------------------------------------------------------------- +STATIC void display_tft_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + display_tft_obj_t *self = self_in; + if (self->disp_spi->handle) { + mp_printf(print, "TFT (%dx%d, Type=%s, Ready: %s, Color mode: %d-bit, Clk=%u Hz, RdClk=%u Hz, Touch: %s)\n", + self->dconfig.width, self->dconfig.height, display_types[self->dconfig.type], ((self->disp_spi->handle) ? "yes" : "no"), self->dconfig.color_bits, self->dconfig.speed, self->dconfig.rdspeed, ((self->ts_spi->handle) ? "yes" : "no")); + mp_printf(print, "Pins (miso=%d, mosi=%d, clk=%d, cs=%d, dc=%d, reset=%d, backlight=%d)", self->dconfig.miso, self->dconfig.mosi, self->dconfig.sck, self->dconfig.cs, self->dconfig.dc, self->dconfig.rst, self->dconfig.bckl); + if (self->ts_spi->handle) { + mp_printf(print, "\nTouch (Enabled, type: %s, cs=%d)", touch_types[self->dconfig.touch], self->dconfig.tcs); + } + } + else { + mp_printf(print, "TFT (Not initialized)"); + } +} + +/* + * tftspi.c low level driver uses some global variables + * Here we set those variables so that multiple displays can be used + */ +//------------------------------------------------- +static int setupDevice(display_tft_obj_t *disp_dev) +{ + if (disp_dev->disp_spi->handle == NULL) return 1; + + if (disp_spi != disp_dev->disp_spi) { + disp_spi = disp_dev->disp_spi; + ts_spi = disp_dev->ts_spi; + TFT_display_setvars(&disp_dev->dconfig); + + tp_calx = disp_dev->tp_calx; + tp_caly = disp_dev->tp_caly; + spi_device_select(disp_spi, 1); + spi_device_deselect(disp_spi); + } + + return 0; +} + +//-------------------------------------- +STATIC color_t intToColor(uint32_t cint) +{ + color_t cl = {0,0,0}; + cl.r = (cint >> 16) & 0xFF; + cl.g = (cint >> 8) & 0xFF; + cl.b = cint & 0xFF; + return cl; +} + +//------------------------------------------------------ +STATIC void spi_deinit_internal(display_tft_obj_t *self) +{ + if (self->disp_spi->handle) { + esp_err_t ret; + // Deinitialize display spi device(s) + if (self->ts_spi->handle) { + ret = remove_extspi_device(self->ts_spi); + if (ret != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Error removing touch device"); + } + } + ret = remove_extspi_device(self->disp_spi); + if (ret != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Error removing display device"); + } + + gpio_pad_select_gpio(self->dconfig.miso); + gpio_pad_select_gpio(self->dconfig.mosi); + gpio_pad_select_gpio(self->dconfig.sck); + } +} + + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_type, ARG_host, ARG_width, ARG_height, ARG_speed, ARG_miso, ARG_mosi, ARG_clk, ARG_cs, + ARG_dc, ARG_tcs, ARG_rst, ARG_bckl, ARG_bcklon, ARG_hastouch, ARG_invrot, ARG_bgr, ARG_cbits, ARG_rot, ARG_splash, ARG_expwm }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_type, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = DISP_TYPE_ST7789V } }, + { MP_QSTR_spihost, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = HSPI_HOST } }, + { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = DEFAULT_TFT_DISPLAY_WIDTH } }, + { MP_QSTR_height, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = DEFAULT_TFT_DISPLAY_HEIGHT } }, + { MP_QSTR_speed, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 10000000 } }, + { MP_QSTR_miso, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_mosi, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_clk, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_cs, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_dc, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_tcs, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_rst_pin, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_backl_pin, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_backl_on, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_hastouch, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = TOUCH_TYPE_NONE } }, + { MP_QSTR_invrot, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_bgr, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_color_bits, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 24 } }, + { MP_QSTR_rot, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_splash, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_expwm, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + display_tft_obj_t *self = pos_args[0]; + esp_err_t ret; + + // === deinitialize display spi device if it was initialized === + if (self->disp_spi->handle) spi_deinit_internal(self); + + // === Get arguments === + if ((args[ARG_host].u_int != HSPI_HOST) && (args[ARG_host].u_int != VSPI_HOST)) { + mp_raise_ValueError("SPI host must be either HSPI(1) or VSPI(2)"); + } + if ((SPIbus_configs[VSPI_HOST] == NULL) && (args[ARG_host].u_int == VSPI_HOST)) { + mp_raise_ValueError("SPI host must be HSPI(1), VSPI(2) used by SPIRAM"); + } + + if ((args[ARG_type].u_int < 0) || (args[ARG_type].u_int >= DISP_TYPE_MAX)) { + mp_raise_ValueError("Unsupported display type"); + } + + if ((args[ARG_cbits].u_int != 16) && (args[ARG_cbits].u_int != 24)) { + mp_raise_ValueError("Unsupported color bits"); + } + + self->dconfig.color_bits = args[ARG_cbits].u_int; + + self->dconfig.type = args[ARG_type].u_int; + + if ((args[ARG_hastouch].u_int == TOUCH_TYPE_XPT2046) || (args[ARG_hastouch].u_int == TOUCH_TYPE_STMPE610)) { + if (args[ARG_tcs].u_int < 0) { + mp_raise_ValueError("Touch selected but no touch cs given"); + } + self->dconfig.touch = args[ARG_hastouch].u_int; + if (args[ARG_hastouch].u_int == TOUCH_TYPE_XPT2046) { + self->tp_calx = TP_CALX_XPT2046; + self->tp_caly = TP_CALY_XPT2046; + } + else { + self->tp_calx = TP_CALX_STMPE610; + self->tp_caly = TP_CALY_STMPE610; + } + self->dconfig.tcs = args[ARG_tcs].u_int; + } + else self->dconfig.touch = TOUCH_TYPE_NONE; + + self->dconfig.host = args[ARG_host].u_int; + self->dconfig.gamma = 0; + self->dconfig.width = args[ARG_width].u_int; // smaller dimension + self->dconfig.height = args[ARG_height].u_int; // larger dimension + self->dconfig.rdspeed = 8000000; + if (args[ARG_invrot].u_int >= 0) self->dconfig.invrot = args[ARG_invrot].u_int; + else { + if ((self->dconfig.type == DISP_TYPE_ST7789V) || + (self->dconfig.type == DISP_TYPE_ST7735) || + (self->dconfig.type == DISP_TYPE_ST7735R) || + (self->dconfig.type == DISP_TYPE_ST7735B)) self->dconfig.invrot = 1; + else if (self->dconfig.type == DISP_TYPE_M5STACK) self->dconfig.invrot = 3; + else self->dconfig.invrot = 0; + } + + if (args[ARG_bgr].u_bool) self->dconfig.bgr = 8; + else self->dconfig.bgr = 0; + + self->dconfig.rst = args[ARG_rst].u_int; + self->dconfig.bckl = args[ARG_bckl].u_int; + self->dconfig.bckl_on = args[ARG_bcklon].u_int & 1; + + self->dconfig.miso = args[ARG_miso].u_int; + self->dconfig.mosi = args[ARG_mosi].u_int; + self->dconfig.sck = args[ARG_clk].u_int; + + self->dconfig.cs = args[ARG_cs].u_int; + self->dconfig.dc = args[ARG_dc].u_int; + + disp_spi = self->disp_spi; + ts_spi = self->ts_spi; + + int orient = args[ARG_rot].u_int; + if (orient < 0) { + if (self->dconfig.type == DISP_TYPE_M5STACK) orient = LANDSCAPE; + else orient = PORTRAIT; + } + else orient &= 3; + + // ================================ + // ==== Initialize the Display ==== + ret = TFT_display_init(&self->dconfig); + if (ret != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Error initializing display"); + } + + disp_used_spi_host = args[ARG_host].u_int; + + if (self->dconfig.type == DISP_TYPE_GENERIC) return mp_const_none; + + // ==== Set SPI clock used for display operations ==== + self->dconfig.speed = spi_set_speed(self->disp_spi, args[ARG_speed].u_int); + + max_rdclock = find_rd_speed(); + self->dconfig.rdspeed = max_rdclock; + + font_rotate = 0; + text_wrap = 1; + font_transparent = 0; + font_forceFixed = 0; + gray_scale = 0; + TFT_setRotation(orient); + self->dconfig.width = _width; + self->dconfig.height = _height; + TFT_setGammaCurve(0); + TFT_setFont(DEFAULT_FONT, NULL); + TFT_resetclipwin(); + if (args[ARG_splash].u_bool) { + int fhight = TFT_getfontheight(); + _fg = intToColor(iTFT_RED); + TFT_print("MicroPython", CENTER, (_height/2) - fhight - (fhight/2)); + _fg = intToColor(iTFT_GREEN); + TFT_print("MicroPython", CENTER, (_height/2) - (fhight/2)); + _fg = intToColor(iTFT_BLUE); + TFT_print("MicroPython", CENTER, (_height/2) + (fhight/2)); + _fg = intToColor(iTFT_GREEN); + } + _fg = intToColor(iTFT_WHITE); + + // Backlight + if (args[ARG_expwm].u_obj != MP_OBJ_NULL) { + self->expwm_handler = args[ARG_expwm].u_obj; + + } else { + bcklOn(&self->dconfig); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_init_obj, 0, display_tft_init); + +//-------------------------------------------------- +STATIC mp_obj_t display_tft_deinit(mp_obj_t self_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self) == 0) { + spi_deinit_internal(self); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_deinit_obj, display_tft_deinit); + +//------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_drawPixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + if (args[2].u_int >= 0) { + color = intToColor(args[2].u_int); + } + TFT_drawPixel(x, y, color, 1); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawPixel_obj, 2, display_tft_drawPixel); + +//------------------------------------------------------------------------------------------------- +// STATIC mp_obj_t display_tft_readPixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + +// const mp_arg_t allowed_args[] = { +// { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, +// { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, +// }; +// display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); +// if (setupDevice(self)) return mp_const_none; + +// mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; +// mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + +// mp_int_t x = args[0].u_int; +// mp_int_t y = args[1].u_int; + +// color_t color = TFT_readPixel(x, y); +// mp_int_t icolor = (int)((color.r << 16) | (color.g << 8) | color.b); + +// return mp_obj_new_int(icolor); +// } +// STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_readPixel_obj, 2, display_tft_readPixel); + +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_drawLine(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x0 = args[0].u_int; + mp_int_t y0 = args[1].u_int; + mp_int_t x1 = args[2].u_int; + mp_int_t y1 = args[3].u_int; + if (args[4].u_int >= 0) { + color = intToColor(args[4].u_int); + } + TFT_drawLine(x0, y0, x1, y1, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawLine_obj, 4, display_tft_drawLine); + +//------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_drawLineByAngle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_start, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_length, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_angle, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t start = args[2].u_int; + mp_int_t len = args[3].u_int; + mp_int_t angle = args[4].u_int; + if (args[5].u_int >= 0) { + color = intToColor(args[5].u_int); + } + TFT_drawLineByAngle(x, y, start, len, angle, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawLineByAngle_obj, 5, display_tft_drawLineByAngle); + +//---------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_drawTriangle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x2, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y2, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x0 = args[0].u_int; + mp_int_t y0 = args[1].u_int; + mp_int_t x1 = args[2].u_int; + mp_int_t y1 = args[3].u_int; + mp_int_t x2 = args[4].u_int; + mp_int_t y2 = args[5].u_int; + if (args[6].u_int >= 0) { + color = intToColor(args[6].u_int); + } + if (args[7].u_int >= 0) { + TFT_fillTriangle(x0, y0, x1, y1, x2, y2, intToColor(args[7].u_int)); + } + TFT_drawTriangle(x0, y0, x1, y1, x2, y2, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawTriangle_obj, 6, display_tft_drawTriangle); + +//---------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_fillTriangle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x2, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y2, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x0 = args[0].u_int; + mp_int_t y0 = args[1].u_int; + mp_int_t x1 = args[2].u_int; + mp_int_t y1 = args[3].u_int; + mp_int_t x2 = args[4].u_int; + mp_int_t y2 = args[5].u_int; + if (args[6].u_int >= 0) { + color = intToColor(args[6].u_int); + } + TFT_fillTriangle(x0, y0, x1, y1, x2, y2, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillTriangle_obj, 6, display_tft_fillTriangle); + +//-------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_drawCircle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t radius = args[2].u_int; + if (args[3].u_int >= 0) { + color = intToColor(args[3].u_int); + } + if (args[4].u_int >= 0) { + TFT_fillCircle(x, y, radius, intToColor(args[4].u_int)); + if (args[3].u_int != args[4].u_int) TFT_drawCircle(x, y, radius, color); + } + else TFT_drawCircle(x, y, radius, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawCircle_obj, 3, display_tft_drawCircle); + +//-------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_fillCircle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t radius = args[2].u_int; + if (args[3].u_int >= 0) { + color = intToColor(args[3].u_int); + } + TFT_fillCircle(x, y, radius, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillCircle_obj, 3, display_tft_fillCircle); + +//--------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_drawEllipse(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_ry, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_opt, MP_ARG_INT, { .u_int = 15 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t rx = args[2].u_int; + mp_int_t ry = args[3].u_int; + mp_int_t opt = args[4].u_int & 0x0F; + if (args[5].u_int >= 0) { + color = intToColor(args[5].u_int); + } + if (args[6].u_int >= 0) { + TFT_fillEllipse(x, y, rx, ry, intToColor(args[6].u_int), opt); + } + TFT_drawEllipse(x, y, rx, ry, color, opt); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawEllipse_obj, 4, display_tft_drawEllipse); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_drawArc(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_thick, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_start, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_end, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 15 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + color_t fill_color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t r = args[2].u_int; + mp_int_t th = args[3].u_int; + mp_int_t start = args[4].u_int; + mp_int_t end = args[5].u_int; + if (args[6].u_int >= 0) { + color = intToColor(args[6].u_int); + } + if (args[7].u_int >= 0) { + fill_color = intToColor(args[7].u_int); + } + TFT_drawArc(x, y, r, th, start, end, color, fill_color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawArc_obj, 6, display_tft_drawArc); + +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_drawPoly(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_sides, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_thick, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 1 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_rotate, MP_ARG_INT, { .u_int = 0 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + color_t fill_color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t r = args[2].u_int; + mp_int_t sides = args[3].u_int; + mp_int_t th = args[4].u_int; + if (args[5].u_int >= 0) { + color = intToColor(args[5].u_int); + } + if (args[6].u_int >= 0) { + fill_color = intToColor(args[6].u_int); + } + TFT_drawPolygon(x, y, sides, r, color, fill_color, args[7].u_int, th); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawPoly_obj, 5, display_tft_drawPoly); + +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_drawRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t w = args[2].u_int; + mp_int_t h = args[3].u_int; + if (args[4].u_int >= 0) { + color = intToColor(args[4].u_int); + } + if (args[5].u_int >= 0) { + TFT_fillRect(x, y, w, h, intToColor(args[5].u_int)); + } + TFT_drawRect(x, y, w, h, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawRect_obj, 4, display_tft_drawRect); + +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_fillRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t w = args[2].u_int; + mp_int_t h = args[3].u_int; + color_t color = _fg; + if (args[4].u_int >= 0) { + color = intToColor(args[4].u_int); + } + TFT_fillRect(x, y, w, h, color); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillRect_obj, 4, display_tft_fillRect); +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_qrcode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_x, MP_ARG_INT, { .u_int = 50 } }, + { MP_QSTR_y, MP_ARG_INT, { .u_int = 10 } }, + { MP_QSTR_width, MP_ARG_INT, { .u_int = 220 } }, + { MP_QSTR_version, MP_ARG_INT, { .u_int = 6 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *text = (char *)mp_obj_str_get_str(args[0].u_obj); + mp_int_t x = args[1].u_int; + mp_int_t y = args[2].u_int; + mp_int_t width = args[3].u_int; + mp_int_t version = args[4].u_int; + + // Create the QR code + QRCode qrcode; + uint8_t qrcodeData[qrcode_getBufferSize(version)]; + qrcode_initText(&qrcode, qrcodeData, version, 0, text); + + // Top quiet zone + uint8_t thickness = width / qrcode.size; + uint16_t lineLength = qrcode.size * thickness; + uint8_t xOffset = x + (width-lineLength)/2; + uint8_t yOffset = y + (width-lineLength)/2; + TFT_fillRect(x, y, width, width, TFT_WHITE); + + for (uint8_t y = 0; y < qrcode.size; y++) { + for (uint8_t x = 0; x < qrcode.size; x++) { + uint8_t q = qrcode_getModule(&qrcode, x, y); + if (q) { + TFT_fillRect(x * thickness + xOffset, y * thickness + yOffset, thickness, thickness, TFT_BLACK); + } + } + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_qrcode_obj, 1, display_tft_qrcode); + +//----------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_drawRoundRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t w = args[2].u_int; + mp_int_t h = args[3].u_int; + mp_int_t r = args[4].u_int; + if (args[5].u_int >= 0) { + color = intToColor(args[5].u_int); + } + if (args[6].u_int >= 0) { + TFT_fillRoundRect(x, y, w, h, r, intToColor(args[6].u_int)); + } + TFT_drawRoundRect(x, y, w, h, r, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_drawRoundRect_obj, 5, display_tft_drawRoundRect); + +//----------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_fillRoundRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_r, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _fg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + mp_int_t w = args[2].u_int; + mp_int_t h = args[3].u_int; + mp_int_t r = args[4].u_int; + if (args[5].u_int >= 0) { + color = intToColor(args[5].u_int); + } + TFT_fillRoundRect(x, y, w, h, r, color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillRoundRect_obj, 5, display_tft_fillRoundRect); + +//-------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_fillScreen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _bg; + if (args[0].u_int >= 0) { + color = intToColor(args[0].u_int); + } + TFT_fillScreen(color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillScreen_obj, 0, display_tft_fillScreen); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_fillWin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t color = _bg; + if (args[0].u_int >= 0) { + color = intToColor(args[0].u_int); + } + TFT_fillWindow(color); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_fillWin_obj, 0, display_tft_fillWin); + +//-------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_7segAttrib(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_dist, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_outline, MP_ARG_REQUIRED | MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_color, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + set_7seg_font_atrib(args[0].u_int, args[1].u_int, (int)args[2].u_bool, intToColor(args[3].u_int)); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_7segAttrib_obj, 4, display_tft_7segAttrib); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_setFont(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_font, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_rotate, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_transparent, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fixedwidth, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_dist, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 8 } }, + { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 2 } }, + { MP_QSTR_outline, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_color, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const char *font_file = NULL; + char fullname[128] = {'\0'}; + mp_int_t font = DEFAULT_FONT; + + if (MP_OBJ_IS_STR(args[0].u_obj)) { + font_file = mp_obj_str_get_str(args[0].u_obj); + + if (physicalPath(font_file, fullname) == 0) { + font = USER_FONT; + font_file = fullname; + } + } + else { + font = mp_obj_get_int(args[0].u_obj); + } + TFT_setFont(font, font_file); + + if (args[1].u_int >= 0) font_rotate = args[1].u_int; + if (args[2].u_int >= 0) font_transparent = args[2].u_int & 1; + if (args[3].u_int >= 0) font_forceFixed = args[3].u_int & 1; + + if (font == FONT_7SEG) { + set_7seg_font_atrib(args[4].u_int, args[5].u_int, (int)args[6].u_bool, intToColor(args[7].u_int)); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setFont_obj, 1, display_tft_setFont); + +//------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_getFontSize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + int width, height; + TFT_getfontsize(&width, &height); + + mp_obj_t tuple[2]; + + tuple[0] = mp_obj_new_int(width); + tuple[1] = mp_obj_new_int(height); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getFontSize_obj, 0, display_tft_getFontSize); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_setRot(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_rot, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = PORTRAIT } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t rot = args[0].u_int; + if ((rot < 0) || (rot > 3)) rot = 0; + + TFT_setRotation(rot); + self->dconfig.width = _width; + self->dconfig.height = _height; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setRot_obj, 1, display_tft_setRot); + +//--------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_rotate, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_transparent, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_fixedwidth, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_bgcolor, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t old_fg = _fg; + color_t old_bg = _bg; + int old_rot = font_rotate; + int old_transp = font_transparent; + int old_fixed = font_forceFixed; + int old_wrap = text_wrap; + + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + char *st = (char *)mp_obj_str_get_str(args[2].u_obj); + + if (args[3].u_int >= 0) _fg = intToColor(args[3].u_int); + if (args[4].u_int >= 0) font_rotate = args[4].u_int; + if (args[5].u_int >= 0) font_transparent = args[5].u_int & 1; + if (args[6].u_int >= 0) font_forceFixed = args[6].u_int & 1; + if (args[7].u_int >= 0) text_wrap = args[7].u_int & 1; + if (args[8].u_int >= 0) _bg = intToColor(args[8].u_int); + + TFT_print(st, x, y); + + _fg = old_fg; + _bg = old_bg; + font_rotate = old_rot; + font_transparent = old_transp; + font_forceFixed = old_fixed; + text_wrap = old_wrap; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_text_obj, 3, display_tft_text); + +//--------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_x, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_rotate, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_transparent, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_fixedwidth, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t old_fg = _fg; + mp_int_t x; + mp_int_t y; + if (n_args > 2) { + x = args[1].u_int; + y = args[2].u_int; + } else { + x = TFT_X; + y = TFT_Y; + } + if (args[3].u_int >= 0) { + _fg = intToColor(args[3].u_int); + } + if (args[4].u_int >= 0) font_rotate = args[4].u_int; + if (mp_obj_is_integer(args[5].u_obj)) font_transparent = args[5].u_int; + if (mp_obj_is_integer(args[6].u_obj)) font_forceFixed = args[6].u_int; + if (mp_obj_is_integer(args[7].u_obj)) text_wrap = args[7].u_int; + + if (MP_OBJ_IS_STR(args[0].u_obj)) { + char *st = (char *)mp_obj_str_get_str(args[0].u_obj); + TFT_print(st, x, y); + } else { + char strbuf[32]; + if (mp_obj_is_integer(args[0].u_obj)) { + int num = mp_obj_get_int(args[0].u_obj); + sprintf(strbuf, "%d", num); + } else if (mp_obj_is_float(args[0].u_obj)) { + float f = mp_obj_float_get(args[0].u_obj); + sprintf(strbuf, "%f", f); + } + TFT_print(strbuf, x, y); + } + + _fg = old_fg; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_print_obj, 1, display_tft_print); + +//--------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_println(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + display_tft_print(n_args, pos_args, kw_args); + TFT_print("\r\n", TFT_X, TFT_Y); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_println_obj, 1, display_tft_println); + +//--------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_stringWidth(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *st = (char *)mp_obj_str_get_str(args[0].u_obj); + + mp_int_t w = TFT_getStringWidth(st); + + return mp_obj_new_int(w); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_stringWidth_obj, 1, display_tft_stringWidth); + +//------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_clearStringRect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + color_t old_bg = _bg; + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + char *st = (char *)mp_obj_str_get_str(args[2].u_obj); + + if (args[3].u_int >= 0) _bg = intToColor(args[3].u_int); + + TFT_clearStringRect(x, y, st); + + _bg = old_bg; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_clearStringRect_obj, 3, display_tft_clearStringRect); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_Image(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_scale, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_type, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_debug, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *fname = NULL; + char fullname[128] = {'\0'}; + int img_type = args[4].u_int; + + fname = (char *)mp_obj_str_get_str(args[2].u_obj); + + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + + if (img_type < 0) { + // try to determine image type + char upr_fname[128]; + strcpy(upr_fname, fname); + for (int i=0; i < strlen(upr_fname); i++) { + upr_fname[i] = toupper((unsigned char) upr_fname[i]); + } + if (strstr(upr_fname, ".JPG") != NULL) img_type = IMAGE_TYPE_JPG; + else if (strstr(upr_fname, ".BMP") != NULL) img_type = IMAGE_TYPE_BMP; + else { + FILE *fhndl = fopen(fullname, "r"); + if (fhndl != NULL) { + uint8_t buf[16]; + if (fread(buf, 1, 11, fhndl) == 11) { + buf[10] = 0; + if (strstr((char *)(buf+6), "JFIF") != NULL) img_type = IMAGE_TYPE_JPG; + else if ((buf[0] = 0x42) && (buf[1] = 0x4d)) img_type = IMAGE_TYPE_BMP; + } + fclose(fhndl); + } + } + if (img_type < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Cannot determine image type")); + } + } + + image_debug = (uint8_t)args[5].u_bool; + if (img_type == IMAGE_TYPE_BMP) { + TFT_bmp_image(args[0].u_int, args[1].u_int, args[3].u_int, fullname, NULL, 0); + } + else if (img_type == IMAGE_TYPE_JPG) { + TFT_jpg_image(args[0].u_int, args[1].u_int, args[3].u_int, fullname, NULL, 0); + } + else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported image type")); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_Image_obj, 3, display_tft_Image); + +#if 0 +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_getTouch(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + const mp_arg_t allowed_args[] = { + { MP_QSTR_raw, MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 0 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + if (setupDevice(self)) return mp_const_none; + if (self->ts_spi->handle == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch not configured")); + } + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + int x = 0; + int y = 0; + uint8_t raw = 0; + if (args[0].u_bool) raw = 1; + int wait = args[1].u_int; + if ((wait < 5) || (wait > 60000)) wait = 0; + + int res = TFT_read_touch(&x, &y, raw); + if (wait) { + #ifdef CONFIG_MICROPY_USE_TASK_WDT + esp_task_wdt_reset(); + #endif + struct timeval tv; + gettimeofday(&tv, NULL); + uint32_t tstart = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); + uint32_t tend = tstart; + uint32_t nres = tstart; + + // wait until not touched + while ((tend-tstart) < wait) { + res = TFT_read_touch(&x, &y, raw); + if (res == 0) break; + vTaskDelay(2); + gettimeofday(&tv, NULL); + tend = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); + #ifdef CONFIG_MICROPY_USE_TASK_WDT + if ((tend-nres) > (CONFIG_TASK_WDT_TIMEOUT_S*500)) { + esp_task_wdt_reset(); + nres = tend; + } + #endif + } + // wait until touched + while ((tend-tstart) < wait) { + res = TFT_read_touch(&x, &y, raw); + if (res) break; + vTaskDelay(2); + gettimeofday(&tv, NULL); + tend = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); + #ifdef CONFIG_MICROPY_USE_TASK_WDT + if ((tend-nres) > (CONFIG_TASK_WDT_TIMEOUT_S*500)) { + esp_task_wdt_reset(); + nres = tend; + } + #endif + } + } + + mp_obj_t tuple[3]; + tuple[0] = mp_obj_new_bool(res); + tuple[1] = mp_obj_new_int(x); + tuple[2] = mp_obj_new_int(y); + + return mp_obj_new_tuple(3, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getTouch_obj, 0, display_tft_getTouch); +#endif + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_compileFont(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_debug, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, + }; + //display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + //if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *fname = NULL; + char fullname[128] = {'\0'}; + uint8_t debug = (uint8_t)args[1].u_bool; + + fname = (char *)mp_obj_str_get_str(args[0].u_obj); + + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + + res = compile_font_file(fullname, debug); + if (res) return mp_const_false; + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_compileFont_obj, 1, display_tft_compileFont); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_HSBtoRGB(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + const mp_arg_t allowed_args[] = { + { MP_QSTR_hue, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_saturation, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_brightness, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_float_t hue = mp_obj_get_float(args[0].u_obj); + mp_float_t sat = mp_obj_get_float(args[1].u_obj); + mp_float_t bri = mp_obj_get_float(args[2].u_obj); + + color_t color = HSBtoRGB(hue, sat, bri); + mp_int_t icolor = (int)((color.r << 16) | (color.g << 8) | color.b); + + return mp_obj_new_int(icolor); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_HSBtoRGB_obj, 3, display_tft_HSBtoRGB); + +//-------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_setclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_fillcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t x0 = args[0].u_int; + mp_int_t y0 = args[1].u_int; + mp_int_t x1 = args[2].u_int; + mp_int_t y1 = args[3].u_int; + + TFT_setclipwin(x0, y0, x1, y1); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setclipwin_obj, 4, display_tft_setclipwin); + +//---------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_resetclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + TFT_resetclipwin(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_resetclipwin_obj, 0, display_tft_resetclipwin); + +//--------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_saveclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + TFT_saveClipWin(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_saveclipwin_obj, 0, display_tft_saveclipwin); + +//------------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_restoreclipwin(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + TFT_restoreClipWin(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_restoreclipwin_obj, 0, display_tft_restoreclipwin); + +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_getSize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_int(_width); + tuple[1] = mp_obj_new_int(_height); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getSize_obj, 0, display_tft_getSize); + +//-------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_getWinSize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_int(dispWin.x2 - dispWin.x1 + 1); + tuple[1] = mp_obj_new_int(dispWin.y2 - dispWin.y1 + 1); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getWinSize_obj, 0, display_tft_getWinSize); +#if 0 +//------------------------------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_setCalib(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + const mp_arg_t allowed_args[] = { + { MP_QSTR_calx, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_caly, MP_ARG_INT, { .u_int = 0 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (self->tp_type == TOUCH_TYPE_NONE) { + return mp_const_none; + } + + if (args[0].u_int == 0) { + if (self->tp_type == TOUCH_TYPE_XPT2046) self->tp_calx = TP_CALX_XPT2046; + else self->tp_calx = TP_CALX_STMPE610; + } + else self->tp_calx = args[0].u_int; + + if (args[0].u_int == 0) { + if (self->tp_type == TOUCH_TYPE_XPT2046) self->tp_caly = TP_CALY_XPT2046; + else self->tp_caly = TP_CALY_STMPE610; + } + else self->tp_caly = args[1].u_int; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setCalib_obj, 0, display_tft_setCalib); +#endif +//------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_setColor(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_color, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_bcolor, MP_ARG_INT, { .u_int = -1 } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[0].u_int >= 0) { + _fg = intToColor(args[0].u_int); + } else { + _fg = intToColor(iTFT_WHITE); + } + + if (args[1].u_int >= 0) { + _bg = intToColor(args[1].u_int); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setColor_obj, 0, display_tft_setColor); + +//----------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_setCursor(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (setupDevice(self)) return mp_const_none; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t x = args[0].u_int; + mp_int_t y = args[1].u_int; + TFT_X = x; + TFT_Y = y; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setCursor_obj, 2, display_tft_setCursor); + +//------------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_getCursor(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + mp_obj_t tuple[2]; + + tuple[0] = mp_obj_new_int(TFT_X); + tuple[1] = mp_obj_new_int(TFT_Y); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getCursor_obj, 0, display_tft_getCursor); + +//----------------------------------------------------------------------------------------------- +#include "driver/ledc.h" +STATIC mp_obj_t display_tft_setBrightness(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + const mp_arg_t allowed_args[] = { + { MP_QSTR_duty, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + }; + display_tft_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t dperc = args[0].u_int; + if (self->expwm_handler) { + esp32_pwm_obj_t * pwm_obj = MP_OBJ_TO_PTR(self->expwm_handler); + int duty = ((int)(dperc * 100.0) * (1 << LEDC_TIMER_12_BIT)) / 10000; + ledc_set_duty(LEDC_HIGH_SPEED_MODE, pwm_obj->channel, duty); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, pwm_obj->channel); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_setBrightness_obj, 0, display_tft_setBrightness); + +//---------------------------------------------------- +STATIC mp_obj_t display_tft_getCalib(mp_obj_t self_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + if (self->ts_spi->handle == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch not configured")); + } + mp_obj_t tuple[2]; + + tuple[0] = mp_obj_new_int(self->tp_calx); + tuple[1] = mp_obj_new_int(self->tp_caly); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_getCalib_obj, display_tft_getCalib); + + +//------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_backlight(mp_obj_t self_in, mp_obj_t onoff_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + int onoff = mp_obj_get_int(onoff_in); + if (onoff) bcklOn(&self->dconfig); + else bcklOff(&self->dconfig); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_backlight_obj, display_tft_backlight); + +//------------------------------------------------------ +STATIC mp_obj_t display_tft_touch_type(mp_obj_t self_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + return mp_obj_new_int(self->dconfig.touch); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_touch_type_obj, display_tft_touch_type); + + +// ==== Low level functions ====================================== + +//------------------------------------------------------------------------ +STATIC mp_obj_t display_tft_set_speed(mp_obj_t self_in, mp_obj_t speed_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + int speed = mp_obj_get_int(speed_in); + + // Set SPI clock used for display operations + self->dconfig.speed = spi_set_speed(self->disp_spi, speed); + + max_rdclock = find_rd_speed(); + self->dconfig.rdspeed = max_rdclock; + + mp_obj_t tuple[2]; + + tuple[0] = mp_obj_new_int(self->dconfig.speed); + tuple[1] = mp_obj_new_int(self->dconfig.rdspeed); + + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_set_speed_obj, display_tft_set_speed); + +//-------------------------------------------------- +STATIC mp_obj_t display_tft_select(mp_obj_t self_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + disp_select(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_select_obj, display_tft_select); + +//---------------------------------------------------- +STATIC mp_obj_t display_tft_deselect(mp_obj_t self_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + disp_deselect(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_deselect_obj, display_tft_deselect); + +//-------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_cmd_read(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t len_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + uint8_t cmd = (uint8_t)mp_obj_get_int(cmd_in); + uint8_t len = (uint8_t)mp_obj_get_int(len_in); + if ((len < 1) || (len > 4)) len = 1; + + uint32_t res = read_cmd(cmd, len); + + return mp_obj_new_int_from_uint(res); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(display_tft_cmd_read_obj, display_tft_cmd_read); + +//------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_send_command(mp_obj_t self_in, mp_obj_t cmd_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + uint8_t cmd = (uint8_t)mp_obj_get_int(cmd_in); + + disp_select(); + disp_spi_transfer_cmd(cmd); + wait_trans_finish(0); + disp_deselect(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_send_command_obj, display_tft_send_command); + +//-------------------------------------------------------------------------------------------- +STATIC mp_obj_t display_tft_send_cmd_data(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t data_in) +{ + display_tft_obj_t *self = self_in; + if (setupDevice(self)) return mp_const_none; + + uint8_t cmd = (uint8_t)mp_obj_get_int(cmd_in); + mp_buffer_info_t data; + mp_get_buffer_raise(data_in, &data, MP_BUFFER_READ); + + disp_select(); + disp_spi_transfer_cmd_data(cmd, data.buf, data.len); + wait_trans_finish(0); + disp_deselect(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(display_tft_send_cmd_data_obj, display_tft_send_cmd_data); + +//-------------------------------------------------- +STATIC mp_obj_t display_tft_get_bg(mp_obj_t self_in) +{ + int icolor = (int)((_bg.r << 16) | (_bg.g << 8) | _bg.b); + return mp_obj_new_int(icolor); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_get_bg_obj, display_tft_get_bg); + +//-------------------------------------------------- +STATIC mp_obj_t display_tft_get_fg(mp_obj_t self_in) +{ + int icolor = (int)((_fg.r << 16) | (_fg.g << 8) | _fg.b); + return mp_obj_new_int(icolor); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_get_fg_obj, display_tft_get_fg); + +//--------------------------------------------------------------------- +STATIC mp_obj_t display_tft_set_bg(mp_obj_t self_in, mp_obj_t color_in) +{ + color_t color = intToColor(mp_obj_get_int(color_in)); + _bg = color; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_set_bg_obj, display_tft_set_bg); + +//--------------------------------------------------------------------- +STATIC mp_obj_t display_tft_set_fg(mp_obj_t self_in, mp_obj_t color_in) +{ + color_t color = intToColor(mp_obj_get_int(color_in)); + _fg = color; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(display_tft_set_fg_obj, display_tft_set_fg); + +//------------------------------------------------- +STATIC mp_obj_t display_tft_get_X(mp_obj_t self_in) +{ + int x = TFT_X; + return mp_obj_new_int(x); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_get_X_obj, display_tft_get_X); + +//------------------------------------------------- +STATIC mp_obj_t display_tft_get_Y(mp_obj_t self_in) +{ + int y = TFT_Y; + return mp_obj_new_int(y); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(display_tft_get_Y_obj, display_tft_get_Y); + + +//================================================================ +STATIC const mp_rom_map_elem_t display_tft_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&display_tft_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&display_tft_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&display_tft_drawPixel_obj) }, + // { MP_ROM_QSTR(MP_QSTR_readPixel), MP_ROM_PTR(&display_tft_readPixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&display_tft_drawLine_obj) }, + { MP_ROM_QSTR(MP_QSTR_lineByAngle), MP_ROM_PTR(&display_tft_drawLineByAngle_obj) }, + { MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&display_tft_drawTriangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&display_tft_drawCircle_obj) }, + { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&display_tft_drawEllipse_obj) }, + { MP_ROM_QSTR(MP_QSTR_arc), MP_ROM_PTR(&display_tft_drawArc_obj) }, + { MP_ROM_QSTR(MP_QSTR_polygon), MP_ROM_PTR(&display_tft_drawPoly_obj) }, + { MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&display_tft_drawRect_obj) }, + // { MP_ROM_QSTR(MP_QSTR_readScreen), MP_ROM_PTR(&display_tft_readScreen_obj) }, + { MP_ROM_QSTR(MP_QSTR_roundrect), MP_ROM_PTR(&display_tft_drawRoundRect_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&display_tft_fillScreen_obj) }, + { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&display_tft_fillScreen_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearwin), MP_ROM_PTR(&display_tft_fillWin_obj) }, + { MP_ROM_QSTR(MP_QSTR_font), MP_ROM_PTR(&display_tft_setFont_obj) }, + { MP_ROM_QSTR(MP_QSTR_fontSize), MP_ROM_PTR(&display_tft_getFontSize_obj) }, + { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&display_tft_text_obj) }, + { MP_ROM_QSTR(MP_QSTR_orient), MP_ROM_PTR(&display_tft_setRot_obj) }, + { MP_ROM_QSTR(MP_QSTR_textWidth), MP_ROM_PTR(&display_tft_stringWidth_obj) }, + { MP_ROM_QSTR(MP_QSTR_textClear), MP_ROM_PTR(&display_tft_clearStringRect_obj) }, + { MP_ROM_QSTR(MP_QSTR_attrib7seg), MP_ROM_PTR(&display_tft_7segAttrib_obj) }, + { MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&display_tft_Image_obj) }, + // { MP_ROM_QSTR(MP_QSTR_gettouch), MP_ROM_PTR(&display_tft_getTouch_obj) }, + { MP_ROM_QSTR(MP_QSTR_compileFont), MP_ROM_PTR(&display_tft_compileFont_obj) }, + { MP_ROM_QSTR(MP_QSTR_hsb2rgb), MP_ROM_PTR(&display_tft_HSBtoRGB_obj) }, + { MP_ROM_QSTR(MP_QSTR_setwin), MP_ROM_PTR(&display_tft_setclipwin_obj) }, + { MP_ROM_QSTR(MP_QSTR_resetwin), MP_ROM_PTR(&display_tft_resetclipwin_obj) }, + { MP_ROM_QSTR(MP_QSTR_savewin), MP_ROM_PTR(&display_tft_saveclipwin_obj) }, + { MP_ROM_QSTR(MP_QSTR_restorewin), MP_ROM_PTR(&display_tft_restoreclipwin_obj) }, + { MP_ROM_QSTR(MP_QSTR_screensize), MP_ROM_PTR(&display_tft_getSize_obj) }, + { MP_ROM_QSTR(MP_QSTR_winsize), MP_ROM_PTR(&display_tft_getWinSize_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_fg), MP_ROM_PTR(&display_tft_get_fg_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_bg), MP_ROM_PTR(&display_tft_get_bg_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_fg), MP_ROM_PTR(&display_tft_set_fg_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_bg), MP_ROM_PTR(&display_tft_set_bg_obj) }, + { MP_ROM_QSTR(MP_QSTR_text_x), MP_ROM_PTR(&display_tft_get_X_obj) }, + { MP_ROM_QSTR(MP_QSTR_text_y), MP_ROM_PTR(&display_tft_get_Y_obj) }, + { MP_ROM_QSTR(MP_QSTR_setColor), MP_ROM_PTR(&display_tft_setColor_obj) }, + // { MP_ROM_QSTR(MP_QSTR_setCalib), MP_ROM_PTR(&display_tft_setCalib_obj) }, + // { MP_ROM_QSTR(MP_QSTR_getCalib), MP_ROM_PTR(&display_tft_getCalib_obj) }, + // { MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&display_tft_backlight_obj) }, + // { MP_ROM_QSTR(MP_QSTR_getTouchType), MP_ROM_PTR(&display_tft_touch_type_obj) }, + + // Adafruit API + { MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&display_tft_print_obj) }, + { MP_ROM_QSTR(MP_QSTR_println), MP_ROM_PTR(&display_tft_println_obj) }, + { MP_ROM_QSTR(MP_QSTR_setRotation), MP_ROM_PTR(&display_tft_setRot_obj) }, + { MP_ROM_QSTR(MP_QSTR_setTextColor), MP_ROM_PTR(&display_tft_setColor_obj) }, + { MP_ROM_QSTR(MP_QSTR_setCursor), MP_ROM_PTR(&display_tft_setCursor_obj) }, + { MP_ROM_QSTR(MP_QSTR_getCursor), MP_ROM_PTR(&display_tft_getCursor_obj) }, + { MP_ROM_QSTR(MP_QSTR_fillScreen), MP_ROM_PTR(&display_tft_fillScreen_obj) }, + { MP_ROM_QSTR(MP_QSTR_drawPixel), MP_ROM_PTR(&display_tft_drawPixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_drawLine), MP_ROM_PTR(&display_tft_drawLine_obj) }, + { MP_ROM_QSTR(MP_QSTR_drawRect), MP_ROM_PTR(&display_tft_drawRect_obj) }, + { MP_ROM_QSTR(MP_QSTR_fillRect), MP_ROM_PTR(&display_tft_fillRect_obj) }, + { MP_ROM_QSTR(MP_QSTR_drawCircle), MP_ROM_PTR(&display_tft_drawCircle_obj) }, + { MP_ROM_QSTR(MP_QSTR_fillCircle), MP_ROM_PTR(&display_tft_fillCircle_obj) }, + { MP_ROM_QSTR(MP_QSTR_drawTriangle), MP_ROM_PTR(&display_tft_drawTriangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_fillTriangle), MP_ROM_PTR(&display_tft_fillTriangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_drawRoundRect), MP_ROM_PTR(&display_tft_drawRoundRect_obj) }, + { MP_ROM_QSTR(MP_QSTR_fillRoundRect), MP_ROM_PTR(&display_tft_fillRoundRect_obj) }, + + { MP_ROM_QSTR(MP_QSTR_setBrightness), MP_ROM_PTR(&display_tft_setBrightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&display_tft_setBrightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_qrcode), MP_ROM_PTR(&display_tft_qrcode_obj) }, + + { MP_ROM_QSTR(MP_QSTR_tft_setspeed), MP_ROM_PTR(&display_tft_set_speed_obj) }, + { MP_ROM_QSTR(MP_QSTR_tft_select), MP_ROM_PTR(&display_tft_select_obj) }, + { MP_ROM_QSTR(MP_QSTR_tft_deselect), MP_ROM_PTR(&display_tft_deselect_obj) }, + { MP_ROM_QSTR(MP_QSTR_tft_writecmd), MP_ROM_PTR(&display_tft_send_command_obj) }, + { MP_ROM_QSTR(MP_QSTR_tft_writecmddata), MP_ROM_PTR(&display_tft_send_cmd_data_obj) }, + { MP_ROM_QSTR(MP_QSTR_tft_readcmd), MP_ROM_PTR(&display_tft_cmd_read_obj) }, + + // class constants + // { MP_ROM_QSTR(MP_QSTR_ST7789), MP_ROM_INT(DISP_TYPE_ST7789V) }, + // { MP_ROM_QSTR(MP_QSTR_ILI9341), MP_ROM_INT(DISP_TYPE_ILI9341) }, + // { MP_ROM_QSTR(MP_QSTR_ILI9488), MP_ROM_INT(DISP_TYPE_ILI9488) }, + // { MP_ROM_QSTR(MP_QSTR_ST7735), MP_ROM_INT(DISP_TYPE_ST7735) }, + // { MP_ROM_QSTR(MP_QSTR_ST7735R), MP_ROM_INT(DISP_TYPE_ST7735R) }, + // { MP_ROM_QSTR(MP_QSTR_ST7735B), MP_ROM_INT(DISP_TYPE_ST7735B) }, + { MP_ROM_QSTR(MP_QSTR_M5STACK), MP_ROM_INT(DISP_TYPE_M5STACK) }, + // { MP_ROM_QSTR(MP_QSTR_GENERIC), MP_ROM_INT(DISP_TYPE_GENERIC) }, + + { MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(CENTER) }, + { MP_ROM_QSTR(MP_QSTR_RIGHT), MP_ROM_INT(RIGHT) }, + { MP_ROM_QSTR(MP_QSTR_BOTTOM), MP_ROM_INT(BOTTOM) }, + { MP_ROM_QSTR(MP_QSTR_LASTX), MP_ROM_INT(LASTX) }, + { MP_ROM_QSTR(MP_QSTR_LASTY), MP_ROM_INT(LASTY) }, + + { MP_ROM_QSTR(MP_QSTR_PORTRAIT), MP_ROM_INT(PORTRAIT) }, + { MP_ROM_QSTR(MP_QSTR_LANDSCAPE), MP_ROM_INT(LANDSCAPE) }, + { MP_ROM_QSTR(MP_QSTR_PORTRAIT_FLIP), MP_ROM_INT(PORTRAIT_FLIP) }, + { MP_ROM_QSTR(MP_QSTR_LANDSCAPE_FLIP), MP_ROM_INT(LANDSCAPE_FLIP) }, + + { MP_ROM_QSTR(MP_QSTR_FONT_Default), MP_ROM_INT(DEFAULT_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_DejaVu18), MP_ROM_INT(DEJAVU18_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_DejaVu24), MP_ROM_INT(DEJAVU24_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Ubuntu), MP_ROM_INT(UBUNTU16_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Comic), MP_ROM_INT(COMIC24_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Minya), MP_ROM_INT(MINYA24_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Tooney), MP_ROM_INT(TOONEY32_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_Small), MP_ROM_INT(SMALL_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_DefaultSmall), MP_ROM_INT(DEF_SMALL_FONT) }, + { MP_ROM_QSTR(MP_QSTR_FONT_7seg), MP_ROM_INT(FONT_7SEG) }, + + { MP_ROM_QSTR(MP_QSTR_BLACK), MP_ROM_INT(iTFT_BLACK) }, + { MP_ROM_QSTR(MP_QSTR_NAVY), MP_ROM_INT(iTFT_NAVY) }, + { MP_ROM_QSTR(MP_QSTR_DARKGREEN), MP_ROM_INT(iTFT_DARKGREEN) }, + { MP_ROM_QSTR(MP_QSTR_DARKCYAN), MP_ROM_INT(iTFT_DARKCYAN) }, + { MP_ROM_QSTR(MP_QSTR_MAROON), MP_ROM_INT(iTFT_MAROON) }, + { MP_ROM_QSTR(MP_QSTR_PURPLE), MP_ROM_INT(iTFT_PURPLE) }, + { MP_ROM_QSTR(MP_QSTR_OLIVE), MP_ROM_INT(iTFT_OLIVE) }, + { MP_ROM_QSTR(MP_QSTR_LIGHTGREY), MP_ROM_INT(iTFT_LIGHTGREY) }, + { MP_ROM_QSTR(MP_QSTR_DARKGREY), MP_ROM_INT(iTFT_DARKGREY) }, + { MP_ROM_QSTR(MP_QSTR_BLUE), MP_ROM_INT(iTFT_BLUE) }, + { MP_ROM_QSTR(MP_QSTR_GREEN), MP_ROM_INT(iTFT_GREEN) }, + { MP_ROM_QSTR(MP_QSTR_CYAN), MP_ROM_INT(iTFT_CYAN) }, + { MP_ROM_QSTR(MP_QSTR_RED), MP_ROM_INT(iTFT_RED) }, + { MP_ROM_QSTR(MP_QSTR_MAGENTA), MP_ROM_INT(iTFT_MAGENTA) }, + { MP_ROM_QSTR(MP_QSTR_YELLOW), MP_ROM_INT(iTFT_YELLOW) }, + { MP_ROM_QSTR(MP_QSTR_WHITE), MP_ROM_INT(iTFT_WHITE) }, + { MP_ROM_QSTR(MP_QSTR_ORANGE), MP_ROM_INT(iTFT_ORANGE) }, + { MP_ROM_QSTR(MP_QSTR_GREENYELLOW), MP_ROM_INT(iTFT_GREENYELLOW) }, + { MP_ROM_QSTR(MP_QSTR_PINK), MP_ROM_INT(iTFT_PINK) }, + + { MP_ROM_QSTR(MP_QSTR_COLOR_BITS16), MP_ROM_INT(16) }, + { MP_ROM_QSTR(MP_QSTR_COLOR_BITS24), MP_ROM_INT(24) }, + + { MP_ROM_QSTR(MP_QSTR_JPG), MP_ROM_INT(IMAGE_TYPE_JPG) }, + { MP_ROM_QSTR(MP_QSTR_BMP), MP_ROM_INT(IMAGE_TYPE_BMP) }, + + { MP_ROM_QSTR(MP_QSTR_HSPI), MP_ROM_INT(HSPI_HOST) }, + { MP_ROM_QSTR(MP_QSTR_VSPI), MP_ROM_INT(VSPI_HOST) }, + + // { MP_ROM_QSTR(MP_QSTR_TOUCH_NONE), MP_ROM_INT(TOUCH_TYPE_NONE) }, + // { MP_ROM_QSTR(MP_QSTR_TOUCH_XPT), MP_ROM_INT(TOUCH_TYPE_XPT2046) }, + // { MP_ROM_QSTR(MP_QSTR_TOUCH_STMPE), MP_ROM_INT(TOUCH_TYPE_STMPE610) }, +}; +STATIC MP_DEFINE_CONST_DICT(display_tft_locals_dict, display_tft_locals_dict_table); + +//====================================== +const mp_obj_type_t display_tft_type = { + { &mp_type_type }, + .name = MP_QSTR_TFT, + .print = display_tft_printinfo, + .make_new = display_tft_make_new, + .locals_dict = (mp_obj_t)&display_tft_locals_dict, +}; + +#endif // CONFIG_MICROPY_USE_TFT + diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_pin.h b/MicroPython_BUILD/components/micropython/esp32/moddisplay_tft.h similarity index 55% rename from MicroPython_BUILD/components/micropython/esp32/machine_pin.h rename to MicroPython_BUILD/components/micropython/esp32/moddisplay_tft.h index 4ffa1119..3d9f1b83 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_pin.h +++ b/MicroPython_BUILD/components/micropython/esp32/moddisplay_tft.h @@ -1,11 +1,8 @@ /* * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * - * Development of the code in this file was sponsored by Microbric Pty Ltd - * * The MIT License (MIT) * - * Copyright (c) 2016 Damien P. George * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -27,20 +24,32 @@ * THE SOFTWARE. */ -#include "driver/gpio.h" +#ifndef _MODDISPLAY_TFT_H_ +#define _MODDISPLAY_TFT_H_ + +#include "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_TFT -#include "py/mphal.h" -#include "modmachine.h" -#include "extmod/virtpin.h" +#include "py/obj.h" -typedef struct _machine_pin_obj_t { - mp_obj_base_t base; - gpio_num_t id; -} machine_pin_obj_t; +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawPixel_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawCircle_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawLine_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawLineByAngle_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawTriangle_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawEllipse_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawArc_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawPoly_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawRect_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_drawRoundRect_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_setFont_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_getFontSize_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_print_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_getSize_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_setclipwin_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(display_tft_resetclipwin_obj); -typedef struct _machine_pin_irq_obj_t { - mp_obj_base_t base; - gpio_num_t id; -} machine_pin_irq_obj_t; +#endif -int machine_pin_get_gpio(mp_obj_t pin_in); +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/modgsm.c b/MicroPython_BUILD/components/micropython/esp32/modgsm.c index db810894..dc975391 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modgsm.c +++ b/MicroPython_BUILD/components/micropython/esp32/modgsm.c @@ -32,7 +32,12 @@ #include #include +#include "tcpip_adapter.h" + #include "py/runtime.h" +#include "py/obj.h" +#include "netutils.h" +#include "mphalport.h" #include "libs/libGSM.h" //------------------------------------------------------------------------------------------------- @@ -49,6 +54,7 @@ STATIC mp_obj_t mod_gsm_startGSM(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ { MP_QSTR_wait, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_roaming, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -81,10 +87,8 @@ STATIC mp_obj_t mod_gsm_startGSM(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ err = -11; goto exit; } - uint8_t wait = args[7].u_bool; - if (args[6].u_bool == false) wait = 0; - int res = ppposInit(tx, rx, args[8].u_int, args[9].u_int, bdr, user, pass, apn, args[7].u_bool, args[6].u_bool); + int res = ppposInit(tx, rx, args[8].u_int, args[9].u_int, bdr, user, pass, apn, args[7].u_bool, args[6].u_bool, args[10].u_bool); if (res == 0) return mp_const_true; @@ -97,9 +101,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_gsm_startGSM_obj, 0, mod_gsm_startGSM); //------------------------------- STATIC mp_obj_t mod_gsm_stopGSM() { - ppposDisconnect(1, 0); - - return mp_const_none; + if (ppposDisconnect(1, 0) == 0) return mp_const_true; + return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_gsm_stopGSM_obj, mod_gsm_stopGSM); @@ -108,7 +111,7 @@ STATIC mp_obj_t mod_gsm_stateGSM() { mp_obj_t tuple[2]; char state[20] = {'\0'}; - int gsm_state = ppposStatus(); + int gsm_state = ppposStatus(NULL, NULL, NULL); tuple[0] = mp_obj_new_int(gsm_state); @@ -117,15 +120,32 @@ STATIC mp_obj_t mod_gsm_stateGSM() else if (gsm_state == GSM_STATE_IDLE) sprintf(state, "Idle"); else if (gsm_state == GSM_STATE_FIRSTINIT) sprintf(state, "Not started"); else sprintf(state, "Unknown"); - tuple[1] = mp_obj_new_str(state, strlen(state), false); + tuple[1] = mp_obj_new_str(state, strlen(state)); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_gsm_stateGSM_obj, mod_gsm_stateGSM); +//-------------------------------- +STATIC mp_obj_t mod_gsm_ifconfig() +{ + uint32_t ip, netmask, gw; + ppposStatus(&ip, &netmask, &gw); + + mp_obj_t tuple[3] = { + (mp_obj_t)netutils_format_ipv4_addr((uint8_t*)&ip, NETUTILS_BIG), + (mp_obj_t)netutils_format_ipv4_addr((uint8_t*)&netmask, NETUTILS_BIG), + (mp_obj_t)netutils_format_ipv4_addr((uint8_t*)&gw, NETUTILS_BIG) + }; + // Return tuple: (ip, netmask, gateway) + return mp_obj_new_tuple(3, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_gsm_ifconfig_obj, mod_gsm_ifconfig); + //-------------------------------------- STATIC mp_obj_t mod_gsm_connectGSM() { + mp_hal_reset_wdt(); int res = ppposConnect(); if (res == 0) return mp_const_true; @@ -143,9 +163,8 @@ STATIC mp_obj_t mod_gsm_disconnectGSM(mp_uint_t n_args, const mp_obj_t *pos_args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - ppposDisconnect(args[0].u_bool, args[1].u_bool); - - return mp_const_none; + if (ppposDisconnect(args[0].u_bool, args[1].u_bool) == 0) return mp_const_true; + return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_gsm_disconnectGSM_obj, 0, mod_gsm_disconnectGSM); @@ -219,7 +238,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_gsm_deleteSMS_obj, mod_gsm_deleteSMS); STATIC mp_obj_t mod_gsm_readSMS(size_t n_args, const mp_obj_t *args) { mp_obj_t msg = mp_const_none; - SMS_indexes indexes; SMS_Msg smsmsg; int idx = mp_obj_get_int(args[0]); int delsms = 0; @@ -229,14 +247,14 @@ STATIC mp_obj_t mod_gsm_readSMS(size_t n_args, const mp_obj_t *args) if (nmsg > 0) { mp_obj_t sms_tuple[7]; sms_tuple[0] = mp_obj_new_int(smsmsg.idx); - sms_tuple[1] = mp_obj_new_str(smsmsg.stat, strlen(smsmsg.stat), false); - sms_tuple[2] = mp_obj_new_str(smsmsg.from, strlen(smsmsg.from), false); - sms_tuple[3] = mp_obj_new_str(smsmsg.time, strlen(smsmsg.time), false); + sms_tuple[1] = mp_obj_new_str(smsmsg.stat, strlen(smsmsg.stat)); + sms_tuple[2] = mp_obj_new_str(smsmsg.from, strlen(smsmsg.from)); + sms_tuple[3] = mp_obj_new_str(smsmsg.time, strlen(smsmsg.time)); sms_tuple[4] = mp_obj_new_int(smsmsg.time_value); sms_tuple[5] = mp_obj_new_int(smsmsg.tz); if (smsmsg.msg) { - sms_tuple[6] = mp_obj_new_str(smsmsg.msg, strlen(smsmsg.msg), false); + sms_tuple[6] = mp_obj_new_str(smsmsg.msg, strlen(smsmsg.msg)); free(smsmsg.msg); } else sms_tuple[6] = mp_const_none; @@ -329,7 +347,7 @@ STATIC mp_obj_t mod_gsm_atCmd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map char **pbuffer = &buffer; int res = at_Cmd(atcmd, resp, pbuffer, 1024, tmo, cmddata); if (res == 0) { - mp_obj_t response = mp_obj_new_str("", 0, false); + mp_obj_t response = mp_obj_new_str("", 0); free(*pbuffer); return response; } @@ -341,7 +359,7 @@ STATIC mp_obj_t mod_gsm_atCmd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map } } } - mp_obj_t response = mp_obj_new_str(buffer, strlen(buffer), false); + mp_obj_t response = mp_obj_new_str(buffer, strlen(buffer)); free(*pbuffer); return response; } @@ -353,6 +371,7 @@ STATIC const mp_rom_map_elem_t gsm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_gsm_startGSM_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_gsm_stopGSM_obj) }, { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&mod_gsm_stateGSM_obj) }, + { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&mod_gsm_ifconfig_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&mod_gsm_disconnectGSM_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&mod_gsm_connectGSM_obj) }, { MP_ROM_QSTR(MP_QSTR_sendSMS), MP_ROM_PTR(&mod_gsm_sendSMS_obj) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modmachine.c b/MicroPython_BUILD/components/micropython/esp32/modmachine.c index 5c591950..b7f1036c 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmachine.c +++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.c @@ -32,17 +32,30 @@ #include #include +#include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" +#include "esp_task_wdt.h" #include "rom/ets_sys.h" +#include "rom/rtc.h" +#include "rom/gpio.h" +#include "soc/rtc.h" +#include "soc/uart_reg.h" +#include "soc/timer_group_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/sens_reg.h" #include "esp_system.h" #include "soc/dport_reg.h" #include "soc/rtc_cntl_reg.h" #include "rom/uart.h" -#include "esp_deep_sleep.h" +#include "esp_sleep.h" #include "esp_heap_caps.h" #include "esp_log.h" +#include "esp_err.h" +#include "esp_pm.h" +#include "esp_wifi.h" +#include "driver/uart.h" #include "py/obj.h" #include "py/runtime.h" @@ -54,49 +67,285 @@ #include "mpsleep.h" #include "machine_rtc.h" #include "uart.h" +#include "modnetwork.h" #if MICROPY_PY_MACHINE +//extern uint8_t temprature_sens_read(); +extern uint16_t rom_phy_get_vdd33(); + +// === Global variables === +bool mpy_use_spiram = false; nvs_handle mpy_nvs_handle = 0; +machine_rtc_config_t RTC_DATA_ATTR machine_rtc_config = {0}; +bool i2s_driver_installed = false; +int mpy_heap_size = CONFIG_MICROPY_HEAP_SIZE * 1024; +int MPY_DEFAULT_STACK_SIZE = 16*1024; +int MPY_MAX_STACK_SIZE = 32*1024; +int MPY_DEFAULT_HEAP_SIZE = 80*1024; +int MPY_MIN_HEAP_SIZE = 48*1024; +int MPY_MAX_HEAP_SIZE = 96*1024; +int hdr_maxlen = 512; +int body_maxlen = 1024; +int ssh2_hdr_maxlen = 512; +int ssh2_body_maxlen = 1024; + +// === Variables stored in RTC_SLOW_MEM === +static uint64_t RTC_DATA_ATTR s_t_wake; +static uint64_t RTC_DATA_ATTR stub_timeout; +static uint64_t RTC_DATA_ATTR stub_timer; +static uint32_t RTC_DATA_ATTR stub_temp; +static uint32_t RTC_DATA_ATTR stub_flag; +static uint16_t RTC_DATA_ATTR stub_timer_inc; +static const char RTC_RODATA_ATTR wake_fmt_str[] = "[%u] info=%u\n"; + +//----------------------------------- +static void RTC_IRAM_ATTR wake_stub() +{ + // Clear MMU for CPU 0 + _DPORT_REG_WRITE(DPORT_PRO_CACHE_CTRL1_REG, _DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG) | DPORT_PRO_CACHE_MMU_IA_CLR); + _DPORT_REG_WRITE(DPORT_PRO_CACHE_CTRL1_REG, _DPORT_REG_READ(DPORT_PRO_CACHE_CTRL1_REG) & (~DPORT_PRO_CACHE_MMU_IA_CLR)); + + // ROM code has not started yet, so we need to set delay factor used by ets_delay_us first. + ets_update_cpu_frequency_rom(ets_get_detected_xtal_freq() / 1000000); + + // Update time + SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE); + while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) { + ; + } + SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR); + // Get current time + const uint64_t s_t_now = (uint64_t)READ_PERI_REG(RTC_CNTL_TIME0_REG) | (((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32); + + // Check reset reason + if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET) { + // Not a deepsleep reset, continue booting + goto do_wakeup; + } + // Check wake up cause + if (REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE) & RTC_EXT0_TRIG_EN) { + // === EXT0 wake up === + if ((machine_rtc_config.ext0_pin >= 0) && (machine_rtc_config.ext0_count > 0)) { + if (machine_rtc_config.pulse_count == 0) machine_rtc_config.ext0_last_time = s_t_now; + else { + if ((s_t_now - machine_rtc_config.ext0_last_time) > stub_timeout) { + machine_rtc_config.pulse_count = 0; + } + machine_rtc_config.ext0_last_time = s_t_now; + } + // Wait inactive ext0 pin level + while(1) { + while (1) { + if (machine_rtc_config.ext0_level) stub_flag = (REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(machine_rtc_config.ext0_rtcpin)) != 0; + else stub_flag = (REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(machine_rtc_config.ext0_rtcpin)) == 0; + if (!stub_flag) break; + REG_WRITE(TIMG_WDTFEED_REG(0), 1); + } + // Debounce, 10 ms + ets_delay_us(10000); + REG_WRITE(TIMG_WDTFEED_REG(0), 1); + if (machine_rtc_config.ext0_level) stub_flag = (REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(machine_rtc_config.ext0_rtcpin)) != 0; + else stub_flag = (REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & BIT(machine_rtc_config.ext0_rtcpin)) == 0; + if (stub_flag) break; + } + machine_rtc_config.pulse_count++; + ets_printf(wake_fmt_str, 0, machine_rtc_config.pulse_count); + if (machine_rtc_config.pulse_count >= machine_rtc_config.ext0_count) goto do_wakeup; + ets_delay_us(1000); + REG_WRITE(TIMG_WDTFEED_REG(0), 1); + goto do_sleep; + } + else goto do_wakeup; + } + + if (REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE) & RTC_EXT1_TRIG_EN) { + // === EXT1 wake up === + if (machine_rtc_config.ext1_level == EXT1_WAKEUP_ALL_HIGH) { + // some of the pins is high, but we want ALL to be high + stub_flag = 0; + for(stub_temp = 0; stub_temp < EXT1_WAKEUP_MAX_PINS; stub_temp++) { + if (machine_rtc_config.ext1_pins[stub_temp] >= 0) stub_flag |= BIT(machine_rtc_config.ext1_rtcpins[stub_temp]); + } + + if (stub_flag) { + // Wait for all high + stub_temp = 0; + while ((REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & stub_flag) != stub_flag) { + ets_delay_us(1000); + REG_WRITE(TIMG_WDTFEED_REG(0), 1); + if ((REG_GET_FIELD(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT) & stub_flag) == 0) goto do_sleep; + stub_temp++; + if (stub_temp > 2000) goto do_sleep; + } + goto do_wakeup; + } + else goto do_wakeup; + } + goto do_wakeup; + } + + if (!(REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE) & RTC_TIMER_TRIG_EN)) { + // Not a timer wake up, continue booting + goto do_wakeup; + } + + // === Reset reason: DEEPSLEEP_RESET & Wake up cause: Timer === + if ((machine_rtc_config.deepsleep_time) && (machine_rtc_config.deepsleep_interval)) { + // == Set the out pin to active level if configured + if (machine_rtc_config.stub_outpin >= 0) { + gpio_pad_select_gpio(machine_rtc_config.stub_outpin); + if (machine_rtc_config.stub_outpin < 32) + gpio_output_set(machine_rtc_config.stub_outpin_level << machine_rtc_config.stub_outpin, + (machine_rtc_config.stub_outpin_level ? 0 : 1) << machine_rtc_config.stub_outpin, + 1< machine_rtc_config.deepsleep_interval) { + machine_rtc_config.deepsleep_time -= machine_rtc_config.deepsleep_interval; + s_t_wake = s_t_now + machine_rtc_config.wakeup_delay_ticks; + // Set the pointer of the wake stub function. + REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&wake_stub); + } + else { + if (machine_rtc_config.wakeup_delay_ticks_last) { + s_t_wake = s_t_now + machine_rtc_config.wakeup_delay_ticks_last; + // Next time use the default wake stab + REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&esp_wake_deep_sleep); + } + else { + REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&esp_wake_deep_sleep); + return; + } + } + + // == Check if we need to wait in wake stub + if (machine_rtc_config.stub_wait) { + if (machine_rtc_config.stub_wait < 1000) { + ets_delay_us(machine_rtc_config.stub_wait); + REG_WRITE(TIMG_WDTFEED_REG(0), 1); + } + else { + stub_timer = 0; + while (stub_timer < machine_rtc_config.stub_wait) { + ets_delay_us(stub_timer_inc); + REG_WRITE(TIMG_WDTFEED_REG(0), 1); + stub_timer += stub_timer_inc; + } + } + } + + // == Reset the led pin if configured + if (machine_rtc_config.stub_outpin >= 0) { + if (machine_rtc_config.stub_outpin < 32) + gpio_output_set(machine_rtc_config.stub_outpin_level << machine_rtc_config.stub_outpin, + (machine_rtc_config.stub_outpin_level ? 1 : 0) << machine_rtc_config.stub_outpin, + 1<> 32); + + do_sleep: + ets_printf(wake_fmt_str, 88, 88); + // Wait for UART to end transmitting. + while (REG_GET_FIELD(UART_STATUS_REG(0), UART_ST_UTX_OUT)) { + REG_WRITE(TIMG_WDTFEED_REG(0), 1); // feed the watchdog + } + + REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&wake_stub); + // Go to sleep. + CLEAR_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN); + SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN); + + // A few CPU cycles may be necessary for the sleep to start... + while (true) { + ; + } + // never reaches here. + + do_wakeup: + ets_printf(wake_fmt_str, 99, 99); + // Wait for UART to end transmitting. + while (REG_GET_FIELD(UART_STATUS_REG(0), UART_ST_UTX_OUT)) { + REG_WRITE(TIMG_WDTFEED_REG(0), 1); // feed the watchdog + } + REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&wake_stub); + return; +} -extern machine_rtc_config_t machine_rtc_config; //--------------------------------------------- void prepareSleepReset(uint8_t hrst, char *msg) { // Umount external & internal fs - externalUmount(); - internalUmount(); - - if (!hrst) { - mp_thread_deinit(); + externalUmount(); + internalUmount(); - if (msg) mp_hal_stdout_tx_str(msg); - - // deinitialise peripherals - machine_pins_deinit(); + if (!hrst) { + if (msg) mp_hal_stdout_tx_str(msg); + /* + // stop and deinitialize WiFi + if (wifi_network_state == WIFI_STATE_STARTED) { + wifi_network_state = WIFI_STATE_STOPPED; + wifi_sta_isconnected = false; + wifi_sta_has_ipaddress = false; + wifi_sta_changed_ipaddress = false; + wifi_ap_isconnected = false; + wifi_ap_sta_isconnected = false; + esp_wifi_stop(); + esp_wifi_deinit(); + } + */ + // deinitialise peripherals + //ToDo: deinitialize other peripherals, threads, services, ... + machine_pins_deinit(); - mp_deinit(); - fflush(stdout); - } + mp_deinit(); + fflush(stdout); + } } //----------------------------------------------------------------- STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { - // get - return mp_obj_new_int(ets_get_cpu_frequency() * 1000000); + // get CPU frequency + return mp_obj_new_int(rtc_clk_cpu_freq_value(rtc_clk_cpu_freq_get())); } else { - // set - mp_int_t freq = mp_obj_get_int(args[0]) / 1000000; - if (freq != 80 && freq != 160 && freq != 240) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "frequency can only be either 80Mhz, 160MHz or 240MHz")); + // set CPU frequency + int freq = mp_obj_get_int(args[0]); + if (freq > 240) freq /= 1000000; + rtc_cpu_freq_t max_freq; + if (!rtc_clk_cpu_freq_from_mhz(freq, &max_freq)) { + char msg[128]; + sprintf(msg, "Available frequencies: 2MHz, 80Mhz, 160MHz, 240MHz or %uMHz (XTAL)", rtc_clk_xtal_freq_get()); + mp_raise_ValueError(msg); } - /* - system_update_cpu_freq(freq); - */ +#ifdef CONFIG_PM_ENABLE + esp_pm_config_esp32_t pm_config; + pm_config.max_cpu_freq = max_freq; + pm_config.min_cpu_freq = RTC_CPU_FREQ_XTAL; + pm_config.light_sleep_enable = false; + if (esp_pm_configure(&pm_config) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "Error configuring frequency"); + } +#endif + rtc_clk_cpu_freq_set(max_freq); + uart_set_baudrate(UART_NUM_0, CONFIG_CONSOLE_UART_BAUDRATE); return mp_const_none; } } @@ -145,56 +394,95 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); //-------------------------------------------------- static void print_heap_info(multi_heap_info_t *info) { - mp_printf(&mp_plat_print, " Free: %u\n", info->total_free_bytes); - mp_printf(&mp_plat_print, " Allocated: %u\n", info->total_allocated_bytes); - mp_printf(&mp_plat_print, " Minimum free: %u\n", info->minimum_free_bytes); - mp_printf(&mp_plat_print, " Total blocks: %u\n", info->total_blocks); - mp_printf(&mp_plat_print, "Largest free block: %u\n", info->largest_free_block); - mp_printf(&mp_plat_print, " Allocated blocks: %u\n", info->allocated_blocks); - mp_printf(&mp_plat_print, " Free blocks: %u\n", info->free_blocks); + mp_printf(&mp_plat_print, " Free: %u\n", info->total_free_bytes); + mp_printf(&mp_plat_print, " Allocated: %u\n", info->total_allocated_bytes); + mp_printf(&mp_plat_print, " Minimum free: %u\n", info->minimum_free_bytes); + mp_printf(&mp_plat_print, " Total blocks: %u\n", info->total_blocks); + mp_printf(&mp_plat_print, "Largest free block: %u\n", info->largest_free_block); + mp_printf(&mp_plat_print, " Allocated blocks: %u\n", info->allocated_blocks); + mp_printf(&mp_plat_print, " Free blocks: %u\n", info->free_blocks); } //--------------------------------------- STATIC mp_obj_t machine_heap_info(void) { - multi_heap_info_t info; + multi_heap_info_t info; mp_printf(&mp_plat_print, "Heap outside of MicroPython heap:\n---------------------------------\n"); - heap_caps_get_info(&info, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); - print_heap_info(&info); - - #if CONFIG_SPIRAM_SUPPORT - #if SPIRAM_USE_MEMMAP - mp_printf(&mp_plat_print, "\nSPIRAM info (MEMMAP used):\n--------------------------\n"); - mp_printf(&mp_plat_print, "Total: %u\n", CONFIG_SPIRAM_SIZE); - mp_printf(&mp_plat_print, " Free: %u\n", CONFIG_SPIRAM_SIZE - (CONFIG_MICROPY_HEAP_SIZE * 1024); - #else - mp_printf(&mp_plat_print, "\nSPIRAM info:\n------------\n"); - heap_caps_get_info(&info, MALLOC_CAP_SPIRAM); - print_heap_info(&info); - #endif - #endif + heap_caps_get_info(&info, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_DMA); + print_heap_info(&info); + + if (mpy_use_spiram) { +#if CONFIG_SPIRAM_USE_MEMMAP + mp_printf(&mp_plat_print, "\nSPIRAM info (MEMMAP used):\n--------------------------\n"); + mp_printf(&mp_plat_print, " Total: %u\n", CONFIG_SPIRAM_SIZE); + mp_printf(&mp_plat_print, "Used for MPy heap: %u\n", mpy_heap_size); + mp_printf(&mp_plat_print, " Free (not used): %u\n", CONFIG_SPIRAM_SIZE - mpy_heap_size); +#else + mp_printf(&mp_plat_print, "\nSPIRAM info:\n------------\n"); + heap_caps_get_info(&info, MALLOC_CAP_SPIRAM); + print_heap_info(&info); +#endif + } - return mp_const_none; + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(machine_heap_info_obj, machine_heap_info); //--------------------------------------------------------------------------------------------- STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum {ARG_sleep_ms}; + enum {ARG_sleep_ms, ARG_stub_ms, ARG_stub_led, ARG_stub_ledlevel, ARG_stub_wait}; const mp_arg_t allowed_args[] = { - { MP_QSTR_sleep_ms, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_sleep_ms, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_stub_ms, MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_stub_led, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_stub_ledlevel, MP_ARG_BOOL, { .u_bool = false } }, + { MP_QSTR_stub_wait, MP_ARG_INT, { .u_int = 0 } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + esp_set_deep_sleep_wake_stub(&esp_wake_deep_sleep); + //REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)&esp_wake_deep_sleep); + machine_rtc_config.stub_outpin = -1; + machine_rtc_config.pulse_count = 0; + machine_rtc_config.deepsleep_interval = 0; + machine_rtc_config.stub_wait = 0; + + uint32_t s_rtc_clk_cal = (uint64_t)REG_READ(RTC_SLOW_CLK_CAL_REG); + stub_timeout = (uint64_t)(2000000) * (1 << RTC_CLK_CAL_FRACT) / s_rtc_clk_cal; + + int64_t stub_sleep = 0; + int64_t sleep_time = args[ARG_sleep_ms].u_int; + if (sleep_time < 0) sleep_time = 0; + if (sleep_time > 0) { + stub_sleep = args[ARG_stub_ms].u_int; + if (stub_sleep < 0) stub_sleep = 0; + if (stub_sleep >= sleep_time) stub_sleep = 0; + } - mp_int_t expiry = args[ARG_sleep_ms].u_int; + int led_pin = args[ARG_stub_led].u_int; + if ((led_pin < -1) || (led_pin > 34)) { + mp_raise_ValueError("Wrong led pin !"); + } - if (expiry > 0) { - esp_deep_sleep_enable_timer_wakeup((uint64_t)(expiry * 1000)); + int64_t wait_in_stub = 0; + if (stub_sleep > 0) { + wait_in_stub = (int64_t)args[ARG_stub_wait].u_int; + if (wait_in_stub < 0) wait_in_stub = 0; + if (wait_in_stub > (stub_sleep*1000)) wait_in_stub = stub_sleep*1000; + machine_rtc_config.stub_wait = wait_in_stub; + stub_timer_inc = 1; + if (wait_in_stub > 100000) stub_timer_inc = 100; + else stub_timer_inc = 10; + } + + if (sleep_time > 0) { + if (stub_sleep) esp_sleep_enable_timer_wakeup(stub_sleep * 1000); + else esp_sleep_enable_timer_wakeup(sleep_time * 1000); + machine_rtc_config.deepsleep_time = sleep_time; } else { if ((machine_rtc_config.ext0_pin < 0) && (machine_rtc_config.ext1_pins == 0) && (!machine_rtc_config.wake_on_touch)) { @@ -202,21 +490,57 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_ma } } - if (machine_rtc_config.ext0_pin != -1) { - esp_deep_sleep_enable_ext0_wakeup(machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0); + if (machine_rtc_config.ext0_pin >= 0) { + ESP_LOGD("DEEP SLEEP", "EXT0=%d\n", machine_rtc_config.ext0_pin); + esp_sleep_enable_ext0_wakeup((gpio_num_t)machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0); + esp_set_deep_sleep_wake_stub(&wake_stub); } - if (machine_rtc_config.ext1_pins != 0) { - esp_deep_sleep_enable_ext1_wakeup( - machine_rtc_config.ext1_pins, - machine_rtc_config.ext1_level ? ESP_EXT1_WAKEUP_ANY_HIGH : ESP_EXT1_WAKEUP_ALL_LOW); + uint64_t ext1_pins = 0; + for (int i = 0; i < EXT1_WAKEUP_MAX_PINS; i++) { + if (machine_rtc_config.ext1_pins[i] >= 0) { + uint64_t pin_bit = (1ll << machine_rtc_config.ext1_pins[i]); + ext1_pins |= pin_bit; + } + } + if (ext1_pins != 0) { + ESP_LOGD("DEEP SLEEP", "EXT1 = [%llx]\n", ext1_pins); + //esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + uint8_t ext1_level = machine_rtc_config.ext1_level; + if (machine_rtc_config.ext1_level == EXT1_WAKEUP_ALL_HIGH) ext1_level = ESP_EXT1_WAKEUP_ANY_HIGH; + esp_sleep_enable_ext1_wakeup(ext1_pins, ext1_level); + esp_set_deep_sleep_wake_stub(&wake_stub); } if (machine_rtc_config.wake_on_touch) { - esp_deep_sleep_enable_touchpad_wakeup(); + esp_sleep_enable_touchpad_wakeup(); } - prepareSleepReset(0, "ESP32: DEEP SLEEP\n"); + ESP_LOGD("DEEP SLEEP", "Sleep time: time=%llu, interval=%llu, pin=%d, level=%d, wait=%llu\n", + sleep_time, stub_sleep, led_pin, args[ARG_stub_ledlevel].u_bool, wait_in_stub); + prepareSleepReset(0, NULL); + + if ((stub_sleep) || (led_pin >= 0)) { + if (led_pin >= 0) { + gpio_pad_select_gpio(led_pin); + gpio_set_direction(led_pin, GPIO_MODE_OUTPUT); + gpio_set_level(led_pin, (uint8_t)args[ARG_stub_ledlevel].u_bool ^ 1); + machine_rtc_config.stub_outpin = (uint8_t)led_pin; + machine_rtc_config.stub_outpin_level = (uint8_t)args[ARG_stub_ledlevel].u_bool; + } + else machine_rtc_config.stub_outpin = -1; + + if (stub_sleep) { + // Get number of microseconds per RTC clock tick (scaled by 2^19) + // Calculate RTC clock value for wakeup + machine_rtc_config.wakeup_delay_ticks = (stub_sleep * 1000) * (1 << RTC_CLK_CAL_FRACT) / s_rtc_clk_cal; + machine_rtc_config.wakeup_delay_ticks_last = ((sleep_time % stub_sleep) * 1000) * (1 << RTC_CLK_CAL_FRACT) / s_rtc_clk_cal;; + + // Set the wake stub function + machine_rtc_config.deepsleep_interval = stub_sleep; + } + esp_set_deep_sleep_wake_stub(&wake_stub); + } esp_deep_sleep_start(); // This function does not return. @@ -242,9 +566,9 @@ STATIC mp_obj_t machine_wake_desc (void) { mp_obj_t tuple[2]; mpsleep_get_reset_desc(reason); - tuple[0] = mp_obj_new_str(reason, strlen(reason), 0); + tuple[0] = mp_obj_new_str(reason, strlen(reason)); mpsleep_get_wake_desc(reason); - tuple[1] = mp_obj_new_str(reason, strlen(reason), 0); + tuple[1] = mp_obj_new_str(reason, strlen(reason)); return mp_obj_new_tuple(2, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_wake_desc_obj, machine_wake_desc); @@ -263,23 +587,23 @@ STATIC mp_obj_t machine_stdin_get (mp_obj_t sz_in, mp_obj_t timeout_in) { vstr_init_len(&vstr, sz); - xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); - uart0_raw_input = 1; - xSemaphoreGive(uart0_mutex); + xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); + uart0_raw_input = 1; + xSemaphoreGive(uart0_mutex); - while (recv < sz) { - c = mp_hal_stdin_rx_chr(timeout); - if (c < 0) break; - vstr.buf[recv++] = (byte)c; + while (recv < sz) { + c = mp_hal_stdin_rx_chr(timeout); + if (c < 0) break; + vstr.buf[recv++] = (byte)c; } xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); - uart0_raw_input = 0; - xSemaphoreGive(uart0_mutex); + uart0_raw_input = 0; + xSemaphoreGive(uart0_mutex); - if (recv == 0) { + if (recv == 0) { return mp_const_none; - } + } return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_stdin_get_obj, machine_stdin_get); @@ -291,15 +615,15 @@ STATIC mp_obj_t machine_stdout_put (mp_obj_t buf_in) { mp_int_t len = bufinfo.len; char *buf = bufinfo.buf; - xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); - uart0_raw_input = 1; - xSemaphoreGive(uart0_mutex); + xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); + uart0_raw_input = 1; + xSemaphoreGive(uart0_mutex); - mp_hal_stdout_tx_strn(buf, len); + mp_hal_stdout_tx_strn(buf, len); - xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); - uart0_raw_input = 0; - xSemaphoreGive(uart0_mutex); + xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); + uart0_raw_input = 0; + xSemaphoreGive(uart0_mutex); return mp_obj_new_int_from_uint(bufinfo.len); } @@ -309,33 +633,33 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_stdout_put_obj, machine_stdout_put); // Assumes 0 <= max <= RAND_MAX // Returns in the closed interval [0, max] //-------------------------------------------- -STATIC uint64_t random_at_most(uint32_t max) { - uint64_t // max <= RAND_MAX < ULONG_MAX, so this is okay. - num_bins = (uint64_t) max + 1, - num_rand = (uint64_t) 0xFFFFFFFF + 1, - bin_size = num_rand / num_bins, - defect = num_rand % num_bins; - - uint32_t x; - do { - x = esp_random(); - } - while (num_rand - defect <= (uint64_t)x); // This is carefully written not to overflow +uint64_t random_at_most(uint32_t max) { + uint64_t // max <= RAND_MAX < ULONG_MAX, so this is okay. + num_bins = (uint64_t) max + 1, + num_rand = (uint64_t) 0xFFFFFFFF + 1, + bin_size = num_rand / num_bins, + defect = num_rand % num_bins; + + uint32_t x; + do { + x = esp_random(); + } + while (num_rand - defect <= (uint64_t)x); // This is carefully written not to overflow - // Truncated division is intentional - return x/bin_size; + // Truncated division is intentional + return x/bin_size; } //----------------------------------------------------------------- STATIC mp_obj_t machine_random(size_t n_args, const mp_obj_t *args) { - if (n_args == 1) { - uint32_t rmax = mp_obj_get_int(args[0]); - return mp_obj_new_int_from_uint(random_at_most(rmax)); - } - uint32_t rmin = mp_obj_get_int(args[0]); - uint32_t rmax = mp_obj_get_int(args[1]); - return mp_obj_new_int_from_uint(rmin + random_at_most(rmax - rmin)); + if (n_args == 1) { + uint32_t rmax = mp_obj_get_int(args[0]); + return mp_obj_new_int_from_uint(random_at_most(rmax)); + } + uint32_t rmin = mp_obj_get_int(args[0]); + uint32_t rmax = mp_obj_get_int(args[1]); + return mp_obj_new_int_from_uint(rmin + random_at_most(rmax - rmin)); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_random_obj, 1, 2, machine_random); @@ -345,15 +669,15 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_random_obj, 1, 2, machine_random); static void checkNVS() { if (mpy_nvs_handle == 0) { - mp_raise_msg(&mp_type_OSError, "NVS not available!"); + mp_raise_msg(&mp_type_OSError, "NVS not available!"); } } //------------------------------------------------------------------------ STATIC mp_obj_t mod_machine_nvs_set_int (mp_obj_t _key, mp_obj_t _value) { - checkNVS(); + checkNVS(); - const char *key = mp_obj_str_get_str(_key); + const char *key = mp_obj_str_get_str(_key); uint32_t value = mp_obj_get_int_truncated(_value); esp_err_t esp_err = nvs_set_i32(mpy_nvs_handle, key, value); @@ -361,10 +685,10 @@ STATIC mp_obj_t mod_machine_nvs_set_int (mp_obj_t _key, mp_obj_t _value) { nvs_commit(mpy_nvs_handle); } else if (ESP_ERR_NVS_NOT_ENOUGH_SPACE == esp_err || ESP_ERR_NVS_PAGE_FULL == esp_err || ESP_ERR_NVS_NO_FREE_PAGES == esp_err) { - mp_raise_msg(&mp_type_OSError, "No space available."); + mp_raise_msg(&mp_type_OSError, "No space available."); } else if (ESP_ERR_NVS_INVALID_NAME == esp_err || ESP_ERR_NVS_KEY_TOO_LONG == esp_err) { - mp_raise_msg(&mp_type_OSError, "Key invalid or too long"); + mp_raise_msg(&mp_type_OSError, "Key invalid or too long"); } return mp_const_none; } @@ -372,7 +696,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_machine_nvs_set_int_obj, mod_machine_nvs_se //------------------------------------------------------- STATIC mp_obj_t mod_machine_nvs_get_int (mp_obj_t _key) { - checkNVS(); + checkNVS(); const char *key = mp_obj_str_get_str(_key); int value = 0; @@ -386,20 +710,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_machine_nvs_get_int_obj, mod_machine_nvs_ge //------------------------------------------------------------------------ STATIC mp_obj_t mod_machine_nvs_set_str (mp_obj_t _key, mp_obj_t _value) { - checkNVS(); + checkNVS(); - const char *key = mp_obj_str_get_str(_key); - const char *value = mp_obj_str_get_str(_value); + const char *key = mp_obj_str_get_str(_key); + const char *value = mp_obj_str_get_str(_value); esp_err_t esp_err = nvs_set_str(mpy_nvs_handle, key, value); if (ESP_OK == esp_err) { nvs_commit(mpy_nvs_handle); } else if (ESP_ERR_NVS_NOT_ENOUGH_SPACE == esp_err || ESP_ERR_NVS_PAGE_FULL == esp_err || ESP_ERR_NVS_NO_FREE_PAGES == esp_err) { - mp_raise_msg(&mp_type_OSError, "No space available."); + mp_raise_msg(&mp_type_OSError, "No space available."); } else if (ESP_ERR_NVS_INVALID_NAME == esp_err || ESP_ERR_NVS_KEY_TOO_LONG == esp_err) { - mp_raise_msg(&mp_type_OSError, "Key invalid or too long"); + mp_raise_msg(&mp_type_OSError, "Key invalid or too long"); } return mp_const_none; } @@ -407,7 +731,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_machine_nvs_set_str_obj, mod_machine_nvs_se //------------------------------------------------------- STATIC mp_obj_t mod_machine_nvs_get_str (mp_obj_t _key) { - checkNVS(); + checkNVS(); const char *key = mp_obj_str_get_str(_key); size_t len = 0; @@ -419,7 +743,7 @@ STATIC mp_obj_t mod_machine_nvs_get_str (mp_obj_t _key) { if (value) { esp_err_t ret = nvs_get_str(mpy_nvs_handle, key, value, &len); if ((ret == ESP_OK ) && (len > 0)) { - strval = mp_obj_new_str(value, strlen(value), 0); + strval = mp_obj_new_str(value, strlen(value)); free(value); } } @@ -430,7 +754,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_machine_nvs_get_str_obj, mod_machine_nvs_ge //----------------------------------------------------- STATIC mp_obj_t mod_machine_nvs_erase (mp_obj_t _key) { - checkNVS(); + checkNVS(); const char *key = mp_obj_str_get_str(_key); @@ -443,10 +767,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_machine_nvs_erase_obj, mod_machine_nvs_eras //------------------------------------------------ STATIC mp_obj_t mod_machine_nvs_erase_all (void) { - checkNVS(); + checkNVS(); if (ESP_OK != nvs_erase_all(mpy_nvs_handle)) { - mp_raise_msg(&mp_type_OSError, "Operation failed."); + mp_raise_msg(&mp_type_OSError, "Operation failed."); } return mp_const_none; } @@ -455,8 +779,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_nvs_erase_all_obj, mod_machine_nvs_ // ==== ESP32 log level =================================================================== -static vprintf_like_t orig_log_func = NULL; - //-------------------------------------------------------- static int vprintf_redirected(const char *fmt, va_list ap) { @@ -464,47 +786,49 @@ static int vprintf_redirected(const char *fmt, va_list ap) return ret; } +static vprintf_like_t orig_log_func = NULL; +static vprintf_like_t prev_log_func = NULL; static vprintf_like_t mp_log_func = &vprintf_redirected; //-------------------------------------------------------------------------- STATIC mp_obj_t mod_machine_log_level (mp_obj_t tag_in, mp_obj_t level_in) { - const char *tag = mp_obj_str_get_str(tag_in); + const char *tag = mp_obj_str_get_str(tag_in); int32_t level = mp_obj_get_int(level_in); if ((level < 0) || (level > 5)) { - mp_raise_ValueError("Log level 0~5 expected"); + mp_raise_ValueError("Log level 0~5 expected"); } - esp_log_level_set(tag, level); + esp_log_level_set(tag, level); - return mp_const_none; + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_machine_log_level_obj, mod_machine_log_level); //--------------------------------------- STATIC mp_obj_t mod_machine_logto_mp () { - if (orig_log_func == NULL) { - orig_log_func = esp_log_set_vprintf(mp_log_func); - } - return mp_const_none; + if (orig_log_func == NULL) { + orig_log_func = esp_log_set_vprintf(mp_log_func); + } + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_logto_mp_obj, mod_machine_logto_mp); //---------------------------------------- STATIC mp_obj_t mod_machine_logto_esp () { - if (orig_log_func != NULL) { - vprintf_like_t prev_func = esp_log_set_vprintf(orig_log_func); - orig_log_func = NULL; - } - return mp_const_none; + if (orig_log_func != NULL) { + prev_log_func = esp_log_set_vprintf(orig_log_func); + orig_log_func = NULL; + } + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_logto_esp_obj, mod_machine_logto_esp); -extern uint8_t temprature_sens_read(); - //----------------------------------- STATIC mp_obj_t mod_machine_tsens() { -/* - SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); + int temper = 0; + + // --- Using code from esp-idf/components/esp32/test/test_tsens.c --- + SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S); CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP); CLEAR_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT); @@ -516,15 +840,15 @@ STATIC mp_obj_t mod_machine_tsens() { //while(REG_GET_FIELD(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_RDY_OUT) == 0) { // ; //} - int res = GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT, SENS_TSENS_OUT_S); + temper = GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT, SENS_TSENS_OUT_S); + + // --- Using function from esp-idf/components/esp32/lib/librtc.a --- + //temper = temprature_sens_read(); - // (res - 32) / 1.8 --> temperature in C - return MP_OBJ_NEW_SMALL_INT(res); -*/ - int temper = temprature_sens_read(); - float ftemper = (float)(temper -32) / 1.8; + // The returned temperature is in Fahrenheit, convert to Celsius + float ftemper = (float)(temper - 32) / 1.8; - mp_obj_t tuple[2]; + mp_obj_t tuple[2]; tuple[0] = mp_obj_new_int_from_uint(temper); tuple[1] = mp_obj_new_float(ftemper); @@ -532,84 +856,194 @@ STATIC mp_obj_t mod_machine_tsens() { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_tsens_obj, mod_machine_tsens); +//------------------------------------ +STATIC mp_obj_t mod_machine_vdd33() { + uint16_t val = rom_phy_get_vdd33(); + + return mp_obj_new_int(val); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_vdd33_obj, mod_machine_vdd33); + //-------------------------------------------------------------- STATIC mp_obj_t mod_machine_stdin_disable(mp_obj_t pattern_in) { - const char *pattern = mp_obj_str_get_str(pattern_in); - if (strlen(pattern) >= 16) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "pattern string too long (15 chars allowed)")); - } - disableStdin(pattern); + bool has_pattern = false; + mp_buffer_info_t pattern_buff; + mp_obj_type_t *type = mp_obj_get_type(pattern_in); + char pattern[16] = {'\0'}; + if (type->buffer_p.get_buffer != NULL) { + int ret = type->buffer_p.get_buffer(pattern_in, &pattern_buff, MP_BUFFER_READ); + if (ret == 0) { + if ((pattern_buff.len > 0) && (pattern_buff.len < 16)) has_pattern = true; + } + } + if (!has_pattern) { + mp_raise_ValueError("invalid pattern (15 chars allowed)"); + } + + memcpy(pattern, pattern_buff.buf, pattern_buff.len); + disableStdin(pattern); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_stdin_disable_obj, mod_machine_stdin_disable); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_machine_stdin_disable_obj, mod_machine_stdin_disable); + +//--------------------------------------- +STATIC mp_obj_t mod_machine_reset_wdt() { + mp_hal_reset_wdt(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_reset_wdt_obj, mod_machine_reset_wdt); + +//------------------------------------- +STATIC mp_obj_t mod_machine_set_wdt() { + mp_hal_set_wdt_tmo(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_set_wdt_obj, mod_machine_set_wdt); + +//-------------------------------------------------------------------- +STATIC mp_obj_t mod_machine_wdt(size_t n_args, const mp_obj_t *args) { + #ifdef CONFIG_MICROPY_USE_TASK_WDT + esp_err_t res; + res = esp_task_wdt_status(NULL); + if (n_args > 0) { + if ((mp_obj_is_true(args[0])) && (res != ESP_OK)) esp_task_wdt_add(NULL); + else if ((!mp_obj_is_true(args[0])) && (res == ESP_OK)) esp_task_wdt_delete(NULL); + } + res = esp_task_wdt_status(NULL); + if (res == ESP_OK) return mp_const_true; + return mp_const_false; + #else + return mp_const_false; + #endif +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_machine_wdt_obj, 0, 1, mod_machine_wdt); + +//----------------------------------------------------------------------- +static void _set_stack_heap(char *key, int value, int valmin, int valmax) +{ + checkNVS(); + + if ((value != 0) && ((value < valmin) || (value > valmax))) { + mp_raise_msg(&mp_type_OSError, "Invalid size"); + } + + esp_err_t esp_err = nvs_set_i32(mpy_nvs_handle, key, value); + if (ESP_OK == esp_err) { + nvs_commit(mpy_nvs_handle); + } + else if (ESP_ERR_NVS_NOT_ENOUGH_SPACE == esp_err || ESP_ERR_NVS_PAGE_FULL == esp_err || ESP_ERR_NVS_NO_FREE_PAGES == esp_err) { + mp_raise_msg(&mp_type_OSError, "No space available for NVS variable."); + } + else if (ESP_ERR_NVS_INVALID_NAME == esp_err || ESP_ERR_NVS_KEY_TOO_LONG == esp_err) { + mp_raise_msg(&mp_type_OSError, "NVS Key invalid or too long"); + } +} + +//---------------------------------------------------------- +STATIC mp_obj_t mod_machine_set_stack_size (mp_obj_t _value) +{ + int value = mp_obj_get_int_truncated(_value); + value &= 0x7FFFFFFC; + _set_stack_heap("MPY_StackSize", value, MPY_MIN_STACK_SIZE, MPY_MAX_STACK_SIZE); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_machine_set_stack_size_obj, mod_machine_set_stack_size); + +//----------------------------------------------------------- +STATIC mp_obj_t mod_machine_set_heap_size (mp_obj_t _value) +{ + int value = mp_obj_get_int_truncated(_value); + value &= 0x7FFFFFFC; + _set_stack_heap("MPY_HeapSize", value, MPY_MIN_HEAP_SIZE, MPY_MAX_HEAP_SIZE); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_machine_set_heap_size_obj, mod_machine_set_heap_size); + //=============================================================== STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, - - { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, - - { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, - { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, - { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, - { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), MP_ROM_PTR(&machine_wake_reason_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_wake_description), MP_ROM_PTR(&machine_wake_desc_obj) }, - { MP_ROM_QSTR(MP_QSTR_heap_info), MP_ROM_PTR(&machine_heap_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_stdin_disable), MP_ROM_PTR(&mod_machine_stdin_disable_obj) }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_setint), MP_ROM_PTR(&mod_machine_nvs_set_int_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_getint), MP_ROM_PTR(&mod_machine_nvs_get_int_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_setstr), MP_ROM_PTR(&mod_machine_nvs_set_str_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_getstr), MP_ROM_PTR(&mod_machine_nvs_get_str_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_erase), MP_ROM_PTR(&mod_machine_nvs_erase_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_erase_all), MP_ROM_PTR(&mod_machine_nvs_erase_all_obj) }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_loglevel), MP_ROM_PTR(&mod_machine_log_level_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_redirectlog), MP_ROM_PTR(&mod_machine_logto_mp_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_restorelog), MP_ROM_PTR(&mod_machine_logto_esp_obj) }, - { MP_ROM_QSTR(MP_QSTR_LOG_NONE), MP_ROM_INT(ESP_LOG_NONE) }, - { MP_ROM_QSTR(MP_QSTR_LOG_ERROR), MP_ROM_INT(ESP_LOG_ERROR) }, - { MP_ROM_QSTR(MP_QSTR_LOG_WARN), MP_ROM_INT(ESP_LOG_WARN) }, - { MP_ROM_QSTR(MP_QSTR_LOG_INFO), MP_ROM_INT(ESP_LOG_INFO) }, - { MP_ROM_QSTR(MP_QSTR_LOG_DEBUG), MP_ROM_INT(ESP_LOG_DEBUG) }, - { MP_ROM_QSTR(MP_QSTR_LOG_VERBOSE), MP_ROM_INT(ESP_LOG_VERBOSE) }, - - { MP_ROM_QSTR(MP_QSTR_stdin_get), MP_ROM_PTR(&machine_stdin_get_obj) }, - { MP_ROM_QSTR(MP_QSTR_stdout_put), MP_ROM_PTR(&machine_stdout_put_obj) }, - - { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, - { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, - - { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, - - { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&machine_random_obj) }, - { MP_ROM_QSTR(MP_QSTR_internal_temp), MP_ROM_PTR(&mod_machine_tsens_obj) }, - - { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, - { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, - { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, - { MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) }, - { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, - { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, - { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) }, - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&mach_rtc_type) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_Neopixel), MP_ROM_PTR(&machine_neopixel_type) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_DHT), MP_ROM_PTR(&machine_dht_type) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_Onewire), MP_ROM_PTR(&machine_onewire_type) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, + + { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, + { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, + { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, + + { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_resetWDT), MP_ROM_PTR(&mod_machine_reset_wdt_obj) }, + { MP_ROM_QSTR(MP_QSTR_setWDT), MP_ROM_PTR(&mod_machine_set_wdt_obj) }, + { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&mod_machine_wdt_obj) }, + { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, + { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), MP_ROM_PTR(&machine_wake_reason_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_wake_description), MP_ROM_PTR(&machine_wake_desc_obj) }, + { MP_ROM_QSTR(MP_QSTR_heap_info), MP_ROM_PTR(&machine_heap_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_stdin_disable), MP_ROM_PTR(&mod_machine_stdin_disable_obj) }, + { MP_ROM_QSTR(MP_QSTR_SetStackSize), MP_ROM_PTR(&mod_machine_set_stack_size_obj) }, + { MP_ROM_QSTR(MP_QSTR_SetHeapSize), MP_ROM_PTR(&mod_machine_set_heap_size_obj) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_setint), MP_ROM_PTR(&mod_machine_nvs_set_int_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_getint), MP_ROM_PTR(&mod_machine_nvs_get_int_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_setstr), MP_ROM_PTR(&mod_machine_nvs_set_str_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_getstr), MP_ROM_PTR(&mod_machine_nvs_get_str_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_erase), MP_ROM_PTR(&mod_machine_nvs_erase_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_nvs_erase_all), MP_ROM_PTR(&mod_machine_nvs_erase_all_obj) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_loglevel), MP_ROM_PTR(&mod_machine_log_level_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_redirectlog), MP_ROM_PTR(&mod_machine_logto_mp_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_restorelog), MP_ROM_PTR(&mod_machine_logto_esp_obj) }, + + { MP_ROM_QSTR(MP_QSTR_stdin_get), MP_ROM_PTR(&machine_stdin_get_obj) }, + { MP_ROM_QSTR(MP_QSTR_stdout_put), MP_ROM_PTR(&machine_stdout_put_obj) }, + + { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, + + { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, + + { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&machine_random_obj) }, + { MP_ROM_QSTR(MP_QSTR_internal_temp), MP_ROM_PTR(&mod_machine_tsens_obj) }, + { MP_ROM_QSTR(MP_QSTR_internal_vdd), MP_ROM_PTR(&mod_machine_vdd33_obj) }, + + { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, + { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, + { MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) }, + { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, + { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&mach_rtc_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_Neopixel), MP_ROM_PTR(&machine_neopixel_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_DHT), MP_ROM_PTR(&machine_dht_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_Onewire), MP_ROM_PTR(&machine_onewire_type) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) }, +#ifdef CONFIG_MICROPY_USE_GPS + { MP_OBJ_NEW_QSTR(MP_QSTR_GPS), MP_ROM_PTR(&machine_gps_type) }, +#endif +#ifdef CONFIG_MICROPY_USE_RFCOMM + { MP_OBJ_NEW_QSTR(MP_QSTR_RFCOMM), MP_ROM_PTR(&machine_rfcomm_type) }, +#endif + // Constants + { MP_ROM_QSTR(MP_QSTR_LOG_NONE), MP_ROM_INT(ESP_LOG_NONE) }, + { MP_ROM_QSTR(MP_QSTR_LOG_ERROR), MP_ROM_INT(ESP_LOG_ERROR) }, + { MP_ROM_QSTR(MP_QSTR_LOG_WARN), MP_ROM_INT(ESP_LOG_WARN) }, + { MP_ROM_QSTR(MP_QSTR_LOG_INFO), MP_ROM_INT(ESP_LOG_INFO) }, + { MP_ROM_QSTR(MP_QSTR_LOG_DEBUG), MP_ROM_INT(ESP_LOG_DEBUG) }, + { MP_ROM_QSTR(MP_QSTR_LOG_VERBOSE), MP_ROM_INT(ESP_LOG_VERBOSE) }, + { MP_ROM_QSTR(MP_QSTR_EXT1_ANYHIGH), MP_ROM_INT(ESP_EXT1_WAKEUP_ANY_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_EXT1_ALLLOW), MP_ROM_INT(ESP_EXT1_WAKEUP_ALL_LOW) }, + { MP_ROM_QSTR(MP_QSTR_EXT1_ANYLOW), MP_ROM_INT(EXT1_WAKEUP_ALL_HIGH) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); //========================================= const mp_obj_module_t mp_module_machine = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&machine_module_globals, + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&machine_module_globals, }; #endif // MICROPY_PY_MACHINE diff --git a/MicroPython_BUILD/components/micropython/esp32/modmachine.h b/MicroPython_BUILD/components/micropython/esp32/modmachine.h index 8fe4b6f9..8fac8c6b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmachine.h +++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.h @@ -31,10 +31,92 @@ #ifndef MICROPY_INCLUDED_ESP32_MODMACHINE_H #define MICROPY_INCLUDED_ESP32_MODMACHINE_H +#include "sdkconfig.h" #include "nvs_flash.h" #include "nvs.h" - #include "py/obj.h" +#include "driver/rtc_io.h" + +#define MPY_MIN_STACK_SIZE (6*1024) +#define EXT1_WAKEUP_ALL_HIGH 2 //!< Wake the chip when all selected GPIOs go high +#define EXT1_WAKEUP_MAX_PINS 4 +#define ADC_TIMER_NUM 3 // Timer used in ADC module +#define ADC_TIMER_DIVIDER 8 // 0.1 us per tick, 10 MHz +#define ADC_TIMER_FREQ 10000000.0 //Timer frequency + +typedef struct { + int8_t ext1_pins[EXT1_WAKEUP_MAX_PINS]; + uint8_t ext1_rtcpins[EXT1_WAKEUP_MAX_PINS]; + uint8_t ext1_level; + int8_t ext0_pin; + int8_t ext0_rtcpin; + uint8_t ext0_level; + size_t ext0_count; + uint64_t ext0_last_time; + uint8_t wake_on_touch; + size_t pulse_count; + uint32_t deepsleep_time; + uint32_t deepsleep_interval; + uint64_t stub_wait; + uint64_t wakeup_delay_ticks; + uint64_t wakeup_delay_ticks_last; + int8_t stub_outpin; + uint8_t stub_outpin_level; +} machine_rtc_config_t; + +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; + gpio_num_t id; + uint8_t mode; + uint8_t pull; + uint8_t irq_type; + int8_t irq_retvalue; + uint8_t irq_any_level; + int32_t irq_debounce; + int32_t irq_active_time; + mp_obj_t irq_handler; +} machine_pin_obj_t; + +typedef struct _machine_timer_obj_t { + mp_obj_base_t base; + uint8_t id; + uint8_t state; + uint8_t type; + int8_t debug_pin; + int8_t debug_pin_mode; + mp_uint_t repeat; + mp_uint_t period; + uint64_t event_num; + uint64_t cb_num; + mp_obj_t callback; + intr_handle_t handle; + uint64_t counter; + uint64_t alarm; +} machine_timer_obj_t; + +typedef struct _esp32_pwm_obj_t { + mp_obj_base_t base; + gpio_num_t pin; + uint8_t active; + uint8_t channel; + uint8_t timer; +} esp32_pwm_obj_t; + +extern bool mpy_use_spiram; +extern int MPY_DEFAULT_STACK_SIZE; +extern int MPY_MAX_STACK_SIZE; +extern int MPY_DEFAULT_HEAP_SIZE; +extern int MPY_MIN_HEAP_SIZE; +extern int MPY_MAX_HEAP_SIZE; +extern int hdr_maxlen; +extern int body_maxlen; +extern int ssh2_hdr_maxlen; +extern int ssh2_body_maxlen; + +extern machine_rtc_config_t machine_rtc_config; +extern machine_timer_obj_t * mpy_timers_used[4]; +extern bool adc_timer_active; +extern bool i2s_driver_installed; extern const mp_obj_type_t machine_timer_type; extern const mp_obj_type_t machine_pin_type; @@ -49,11 +131,20 @@ extern const mp_obj_type_t machine_neopixel_type; extern const mp_obj_type_t machine_dht_type; extern const mp_obj_type_t machine_onewire_type; extern const mp_obj_type_t machine_ds18x20_type; - +extern const mp_obj_type_t machine_i2s_type; +#ifdef CONFIG_MICROPY_USE_RFCOMM +extern const mp_obj_type_t machine_rfcomm_type; +#endif +#ifdef CONFIG_MICROPY_USE_GPS +extern const mp_obj_type_t machine_gps_type; +#endif extern nvs_handle mpy_nvs_handle; +extern int mpy_heap_size; void machine_pins_init(void); void machine_pins_deinit(void); void prepareSleepReset(uint8_t hrst, char *msg); +int machine_pin_get_gpio(mp_obj_t pin_in); +uint64_t random_at_most(uint32_t max); #endif // MICROPY_INCLUDED_ESP32_MODMACHINE_H diff --git a/MicroPython_BUILD/components/micropython/esp32/modmqtt.c b/MicroPython_BUILD/components/micropython/esp32/modmqtt.c index a34108bc..91b83428 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmqtt.c +++ b/MicroPython_BUILD/components/micropython/esp32/modmqtt.c @@ -32,169 +32,160 @@ */ #include "sdkconfig.h" - +#define CONFIG_MICROPY_USE_MQTT #ifdef CONFIG_MICROPY_USE_MQTT #include #include #include -#include "mqtt.h" +#include "mqtt_client.h" +#include "http_parser.h" #include "py/nlr.h" #include "py/runtime.h" #include "modmachine.h" #include "mphalport.h" +#include "extmod/vfs_native.h" +#define CONFIG_MQTT_MAX_TASKNAME_LEN 16 typedef struct _mqtt_obj_t { mp_obj_base_t base; - mqtt_client *client; + esp_mqtt_client_handle_t client; + esp_mqtt_client_config_t mqtt_cfg; char name[CONFIG_MQTT_MAX_TASKNAME_LEN]; + void *mpy_connected_cb; + void *mpy_disconnected_cb; + void *mpy_subscribed_cb; + void *mpy_unsubscribed_cb; + void *mpy_published_cb; + void *mpy_data_cb; + uint8_t *msgbuf; + uint8_t *topicbuf; + char *certbuf; + uint8_t subs_flag; + uint8_t unsubs_flag; + uint8_t publish_flag; } mqtt_obj_t; const mp_obj_type_t mqtt_type; -//-------------------------------------- -STATIC int checkClient(mqtt_obj_t *self) +//------------------------------------------ +STATIC int checkClient(mqtt_obj_t *mqtt_obj) { - if (self->client == NULL) { + if (mqtt_obj->client == NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Mqtt client destroyed")); } - if (self->client->status == MQTT_STATUS_DISCONNECTED) { - //nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Mqtt client disconnected")); - return 1; - } - if (self->client->status == MQTT_STATUS_STOPPING) { - //nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Mqtt client stopping")); - return 2; - } - if (self->client->status == MQTT_STATUS_STOPPED) { - //nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Mqtt client stopped")); - return 3; - } - return 0; + return mqtt_obj->client->state; } -//------------------------------------------------ -STATIC void connected_cb(void *self, void *params) +//---------------------------------------- +STATIC void connected_cb(mqtt_obj_t *self) { - mqtt_client *client = (mqtt_client *)self; - - if (client->settings->mpy_connected_cb) { + if (self->mpy_connected_cb) { mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_SINGLE); if (!carg) return; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(client->name), (const uint8_t *)client->name, NULL)) return; - mp_sched_schedule(client->settings->mpy_connected_cb, mp_const_none, carg); + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(self->name), (const uint8_t *)self->name, NULL)) return; + mp_sched_schedule(self->mpy_connected_cb, mp_const_none, carg); } } -//--------------------------------------------------- -STATIC void disconnected_cb(void *self, void *params) +//------------------------------------------- +STATIC void disconnected_cb(mqtt_obj_t *self) { - mqtt_client *client = (mqtt_client *)self; - - if (client->settings->mpy_disconnected_cb) { + if (self->mpy_disconnected_cb) { mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_SINGLE); if (!carg) return; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(client->name), (const uint8_t *)client->name, NULL)) return; - mp_sched_schedule(client->settings->mpy_disconnected_cb, mp_const_none, carg); + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(self->name), (const uint8_t *)self->name, NULL)) return; + mp_sched_schedule(self->mpy_disconnected_cb, mp_const_none, carg); } } -//------------------------------------------------- -STATIC void subscribed_cb(void *self, void *params) +//------------------------------------------------------------ +STATIC void subscribed_cb(mqtt_obj_t *self, const char *topic) { - mqtt_client *client = (mqtt_client *)self; - const char *topic = (const char *)params; - - if (client->settings->mpy_subscribed_cb) { + if (self->mpy_subscribed_cb) { mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); if (carg == NULL) return; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(client->name), (const uint8_t *)client->name, NULL)) return; + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(self->name), (const uint8_t *)self->name, NULL)) return; if (topic) { if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, strlen(topic), (const uint8_t *)topic, NULL)) return; } else { if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, 1, (const uint8_t *)"?", NULL)) return; } - mp_sched_schedule(client->settings->mpy_subscribed_cb, mp_const_none, carg); + mp_sched_schedule(self->mpy_subscribed_cb, mp_const_none, carg); } } -//--------------------------------------------------- -STATIC void unsubscribed_cb(void *self, void *params) +//-------------------------------------------------------------- +STATIC void unsubscribed_cb(mqtt_obj_t *self, const char *topic) { - mqtt_client *client = (mqtt_client *)self; - const char *topic = (const char *)params; - - if (client->settings->mpy_unsubscribed_cb) { + if (self->mpy_unsubscribed_cb) { mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); if (carg == NULL) return; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(client->name), (const uint8_t *)client->name, NULL)) return; + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(self->name), (const uint8_t *)self->name, NULL)) return; if (topic) { if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, strlen(topic), (const uint8_t *)topic, NULL)) return; } else { if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, 1, (const uint8_t *)"?", NULL)) return; } - mp_sched_schedule(client->settings->mpy_unsubscribed_cb, mp_const_none, carg); + mp_sched_schedule(self->mpy_unsubscribed_cb, mp_const_none, carg); } } -//------------------------------------------------ -STATIC void published_cb(void *self, void *params) +//--------------------------------------------------------------------- +STATIC void published_cb(mqtt_obj_t *self, const char *topic, int type) { - mqtt_client *client = (mqtt_client *)self; - const char *type = (const char *)params; - - if (client->settings->mpy_published_cb) { + if (self->mpy_published_cb) { mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); if (carg == NULL) return; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(client->name), (const uint8_t *)client->name, NULL)) return; - if (type) { - if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, strlen(type), (const uint8_t *)type, NULL)) return; + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(self->name), (const uint8_t *)self->name, NULL)) return; + if (topic) { + if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, strlen(topic), (const uint8_t *)topic, NULL)) return; } else { if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, 1, (const uint8_t *)"?", NULL)) return; } - mp_sched_schedule(client->settings->mpy_published_cb, mp_const_none, carg); + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_INT, type, NULL, NULL)) return; + mp_sched_schedule(self->mpy_published_cb, mp_const_none, carg); } } -//------------------------------------------- -STATIC void data_cb(void *self, void *params) +//------------------------------------------------- +STATIC void data_cb(mqtt_obj_t *self, void *params) { - mqtt_client *client = (mqtt_client *)self; - if (!client->settings->mpy_data_cb) return; + if (!self->mpy_data_cb) return; - mqtt_event_data_t *event_data = (mqtt_event_data_t *)params; + esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t)params; - if (event_data->data_offset == 0) { + if (event->current_data_offset == 0) { // *** First block of data - if (client->msgbuf != NULL) free(client->msgbuf); - if (client->topicbuf != NULL) free(client->topicbuf); - client->msgbuf = NULL; - client->topicbuf = NULL; - if (event_data->data_length < event_data->data_total_length) { + if (self->msgbuf != NULL) free(self->msgbuf); + if (self->topicbuf != NULL) free(self->topicbuf); + self->msgbuf = NULL; + self->topicbuf = NULL; + if (event->data_len < event->total_data_len) { // === more data will follow, allocate the data buffer and copy the first part === - client->topicbuf = malloc(event_data->topic_length + 1); - if (client->topicbuf) { - memcpy(client->topicbuf, event_data->topic, event_data->topic_length); - client->topicbuf[event_data->topic_length] = 0; - - int buf_len = event_data->data_total_length + 1; - client->msgbuf = malloc(buf_len + 1); - if (client->msgbuf) { - memcpy(client->msgbuf, event_data->data, event_data->data_length); - client->msgbuf[event_data->data_length] = 0; + self->topicbuf = malloc(event->topic_len + 1); + if (self->topicbuf) { + memcpy(self->topicbuf, event->topic, event->topic_len); + self->topicbuf[event->topic_len] = 0; + + int buf_len = event->total_data_len + 1; + self->msgbuf = malloc(buf_len + 1); + if (self->msgbuf) { + memcpy(self->msgbuf, event->data, event->data_len); + self->msgbuf[event->data_len] = 0; } else { - free(client->topicbuf); - client->msgbuf = NULL; - client->topicbuf = NULL; + free(self->topicbuf); + self->msgbuf = NULL; + self->topicbuf = NULL; } } } @@ -202,44 +193,111 @@ STATIC void data_cb(void *self, void *params) // === all data received, we can schedule the callback function now === mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); if (!carg) return; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(client->name), (const uint8_t *)client->name, NULL)) return; - if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, event_data->topic_length, (const uint8_t *)event_data->topic, NULL)) return; - if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, event_data->data_length, (const uint8_t *)event_data->data, NULL)) return; - mp_sched_schedule(client->settings->mpy_data_cb, mp_const_none, carg); + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(self->name), (const uint8_t *)self->name, NULL)) return; + if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, event->topic_len, (const uint8_t *)event->topic, NULL)) return; + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, event->data_len, (const uint8_t *)event->data, NULL)) return; + mp_sched_schedule(self->mpy_data_cb, mp_const_none, carg); } } else { - if ((client->topicbuf) && (client->msgbuf)) { + if ((self->topicbuf) && (self->msgbuf)) { // === more payload data arrived, add to buffer === - int new_len = event_data->data_offset + event_data->data_length; - memcpy(client->msgbuf + event_data->data_offset, event_data->data, event_data->data_length); - client->msgbuf[new_len] = 0; - if (new_len >= event_data->data_total_length) { + int new_len = event->current_data_offset + event->data_len; + memcpy(self->msgbuf + event->current_data_offset, event->data, event->data_len); + self->msgbuf[new_len] = 0; + if (new_len >= event->total_data_len) { // === all data received, we can schedule the callback function now === mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_TUPLE); if (!carg) goto freebufs; - if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(client->name), (const uint8_t *)client->name, NULL)) goto freebufs; - if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, strlen((const char *)client->topicbuf), client->topicbuf, NULL)) goto freebufs; - if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, event_data->data_total_length, client->msgbuf, NULL)) goto freebufs; - mp_sched_schedule(client->settings->mpy_data_cb, mp_const_none, carg); + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_STR, strlen(self->name), (const uint8_t *)self->name, NULL)) goto freebufs; + if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, strlen((const char *)self->topicbuf), self->topicbuf, NULL)) goto freebufs; + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, event->total_data_len, self->msgbuf, NULL)) goto freebufs; + mp_sched_schedule(self->mpy_data_cb, mp_const_none, carg); freebufs: // Free the buffers - free(client->msgbuf); - free(client->topicbuf); - client->msgbuf = NULL; - client->topicbuf = NULL; + free(self->msgbuf); + free(self->topicbuf); + self->msgbuf = NULL; + self->topicbuf = NULL; } } else { // more payload data arrived, but there is no data buffers allocated (!?) - if (client->msgbuf != NULL) free(client->msgbuf); - if (client->topicbuf != NULL) free(client->topicbuf); - client->msgbuf = NULL; - client->topicbuf = NULL; + if (self->msgbuf != NULL) free(self->msgbuf); + if (self->topicbuf != NULL) free(self->topicbuf); + self->msgbuf = NULL; + self->topicbuf = NULL; } } } +//---------------------------------------------------------------- +static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) +{ + esp_mqtt_client_handle_t client = event->client; + mqtt_obj_t *mpy_client = (mqtt_obj_t *)client->mpy_mqtt_obj; + const char *topic = NULL; + // your_context_t *context = event->context; + switch (event->event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(MQTT_TAG, "Connected"); + connected_cb(mpy_client); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGI(MQTT_TAG, "Disconnected"); + disconnected_cb(mpy_client); + break; + + case MQTT_EVENT_SUBSCRIBED: + if (client->config->user_context) { + topic = (const char *)client->config->user_context; + ESP_LOGI(MQTT_TAG, "Subscribed to '%s'", topic); + } + else { + ESP_LOGI(MQTT_TAG, "Subscribed"); + } + subscribed_cb(mpy_client, topic); + mpy_client->subs_flag = 1; + break; + case MQTT_EVENT_UNSUBSCRIBED: + if (client->config->user_context) { + topic = (const char *)client->config->user_context; + ESP_LOGI(MQTT_TAG, "Unsubscribed from '%s'", topic); + } + else { + ESP_LOGI(MQTT_TAG, "Unsubscribed"); + } + unsubscribed_cb(mpy_client, topic); + mpy_client->unsubs_flag = 1; + break; + case MQTT_EVENT_PUBLISHED: + if (client->config->user_context) { + topic = (const char *)client->config->user_context; + ESP_LOGI(MQTT_TAG, "Published to '%s'", topic); + } + else { + ESP_LOGI(MQTT_TAG, "Published"); + } + published_cb(mpy_client, topic, event->type); + mpy_client->publish_flag = 1; + break; + case MQTT_EVENT_DATA: + if (mpy_client->mpy_data_cb == NULL) { + ESP_LOGI(MQTT_TAG, "TOPIC: %.*s\r\n", event->topic_len, event->topic); + ESP_LOGI(MQTT_TAG, " DATA: %.*s\r\n", event->data_len, event->data); + } + else { + ESP_LOGI(MQTT_TAG, "Data received"); + } + data_cb(mpy_client, event); + break; + case MQTT_EVENT_ERROR: + ESP_LOGI(MQTT_TAG, "Mqtt Error"); + break; + } + return ESP_OK; +} + //------------------------------------------------------------------------------------- STATIC void mqtt_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) @@ -251,23 +309,33 @@ STATIC void mqtt_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ return; } char sstat[16]; - if (self->client->status == MQTT_STATUS_CONNECTED) sprintf(sstat, "Connected"); - else if (self->client->status == MQTT_STATUS_DISCONNECTED) sprintf(sstat, "Disconnected"); - else if (self->client->status == MQTT_STATUS_STOPPING) sprintf(sstat, "Stopping"); - else if (self->client->status == MQTT_STATUS_STOPPED) sprintf(sstat, "Stopped"); - else sprintf(sstat, "Unknown"); - - mp_printf(print, "Mqtt[%s](Server: %s:%u, Status: %s\n", self->name, self->client->settings->host, self->client->settings->port, sstat); - if ((self->client->status != MQTT_STATUS_STOPPING) && (self->client->status != MQTT_STATUS_STOPPED)) { - mp_printf(print, " Client ID: %s, Clean session=%s, Keepalive=%d sec, QoS=%d, Retain=%s, Secure=%s\n", - self->client->settings->client_id, (self->client->settings->clean_session ? "True" : "False"), self->client->settings->keepalive, self->client->settings->lwt_qos, - (self->client->settings->lwt_retain ? "True" : "False"), (self->client->settings->use_ssl ? "True" : "False")); + if (self->client->state == MQTT_STATE_CONNECTED) sprintf(sstat, "Connected"); + else if (self->client->state == MQTT_STATE_INIT) sprintf(sstat, "Initialized"); + else if (self->client->state == MQTT_STATE_WAIT_TIMEOUT) sprintf(sstat, "Wait timeout"); + else if (self->client->state == MQTT_STATE_UNKNOWN) sprintf(sstat, "Unknown"); + else sprintf(sstat, "Error"); + + const char *server_uri = "Unknown"; + if (self->client->config->uri) server_uri = self->client->config->uri; + else if (self->client->config->host) server_uri = self->client->config->host; + + mp_printf(print, "Mqtt[%s]\n (Server: %s:%u, Status: %s\n", self->name, server_uri, self->client->config->port, sstat); + if ((self->client->state == MQTT_STATE_CONNECTED) || (self->client->state == MQTT_STATE_INIT)) { + mp_printf(print, " Client ID: %s, Clean session=%s, Keepalive=%ds\n LWT(", + self->client->connect_info.client_id, (self->client->connect_info.clean_session ? "True" : "False"), self->client->connect_info.keepalive); + if (self->client->connect_info.will_topic) { + mp_printf(print, "QoS=%d, Retain=%s, Topic='%s', Msg='%s')\n", + self->client->connect_info.will_qos, (self->client->connect_info.will_retain ? "True" : "False"), self->client->connect_info.will_topic, self->client->connect_info.will_message); + } + else mp_printf(print, "not set)\n"); } + /* if ((self->client->settings->xMqttTask) && (self->client->settings->xMqttSendingTask)) { mp_printf(print, " Used stack: %u/%u + %u/%u\n", self->client->settings->xMqttTask_stacksize - uxTaskGetStackHighWaterMark(self->client->settings->xMqttTask), self->client->settings->xMqttTask_stacksize, self->client->settings->xMqttSendingTask_stacksize - uxTaskGetStackHighWaterMark(self->client->settings->xMqttSendingTask), self->client->settings->xMqttSendingTask_stacksize); } + */ mp_printf(print, " )\n"); } @@ -275,8 +343,8 @@ STATIC void mqtt_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ //------------------------------------------------------------------------------------------------------------ STATIC mp_obj_t mqtt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_name, ARG_host, ARG_user, ARG_pass, ARG_port, ARG_reconnect, ARG_clientid, ARG_cleansess, ARG_keepalive, ARG_qos, ARG_retain, ARG_secure, - ARG_datacb, ARG_connected, ARG_disconnected, ARG_subscribed, ARG_unsubscribed, ARG_published }; + enum { ARG_name, ARG_server, ARG_user, ARG_pass, ARG_port, ARG_reconnect, ARG_clientid, ARG_cleansess, ARG_keepalive, ARG_cert, + ARG_lwt_topic, ARG_lwt_msg, ARG_lwt_qos, ARG_lwt_retain, ARG_datacb, ARG_connected, ARG_disconnected, ARG_subscribed, ARG_unsubscribed, ARG_published }; const mp_arg_t mqtt_init_allowed_args[] = { { MP_QSTR_name, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -287,10 +355,12 @@ STATIC mp_obj_t mqtt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n { MP_QSTR_autoreconnect, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_clientid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_cleansession, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_keepalive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 120} }, - { MP_QSTR_qos, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_retain, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_secure, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_keepalive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MQTT_KEEPALIVE_TICK} }, + { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_lwt_topic, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_lwt_msg, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_lwt_qos, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_lwt_retain, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_data_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_connected_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_disconnected_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -301,93 +371,165 @@ STATIC mp_obj_t mqtt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n mp_arg_val_t args[MP_ARRAY_SIZE(mqtt_init_allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(mqtt_init_allowed_args), mqtt_init_allowed_args, args); - // Setup the mqtt object + const char *tstr = NULL; + + // Create the mqtt object mqtt_obj_t *self = m_new_obj(mqtt_obj_t ); + memset(self, 0 , sizeof(mqtt_obj_t)); - // === allocate client memory === - self->client = malloc(sizeof(mqtt_client)); - if (self->client == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Error allocating client memory")); - } - memset(self->client, 0, sizeof(mqtt_client)); + // Populate settings + esp_mqtt_client_config_t mqtt_cfg = {0}; - self->client->settings = malloc(sizeof(mqtt_settings)); - if (self->client->settings == NULL) { - free(self->client); - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Error allocating client memory")); - } - memset(self->client->settings, 0, sizeof(mqtt_settings)); + // Event handle + mqtt_cfg.event_handle = mqtt_event_handler; - // Populate settings - self->client->settings->use_ssl = args[ARG_secure].u_bool; + // Object name + tstr = mp_obj_str_get_str(args[ARG_name].u_obj); + if (strlen(tstr) >= CONFIG_MQTT_MAX_TASKNAME_LEN) { + mp_raise_ValueError("Name too long"); + } + sprintf(self->name, "%s", tstr); - snprintf(self->name, CONFIG_MQTT_MAX_TASKNAME_LEN, mp_obj_str_get_str(args[ARG_name].u_obj)); - self->client->name = self->name; - snprintf(self->client->settings->host, CONFIG_MQTT_MAX_HOST_LEN, mp_obj_str_get_str(args[ARG_host].u_obj)); + // Port + if (args[ARG_port].u_int > 0) mqtt_cfg.port = args[ARG_port].u_int; - if (args[ARG_port].u_int > 0) self->client->settings->port = args[ARG_port].u_int; - else if (args[ARG_secure].u_bool) self->client->settings->port = 8883; - else self->client->settings->port = 1883; + // Get URI or server domain + tstr = mp_obj_str_get_str(args[ARG_server].u_obj); + if (strlen(tstr) >= MQTT_MAX_HOST_LEN) { + mp_raise_ValueError("URI too long"); + } + struct http_parser_url puri; + http_parser_url_init(&puri); + int parser_status = http_parser_parse_url(tstr, strlen(tstr), 0, &puri); + if (parser_status != 0) { + sprintf(mqtt_cfg.host, "%s", tstr); + } + else sprintf(mqtt_cfg.uri, "%s", tstr); + // User name if (MP_OBJ_IS_STR(args[ARG_user].u_obj)) { - snprintf(self->client->settings->username, CONFIG_MQTT_MAX_USERNAME_LEN, mp_obj_str_get_str(args[ARG_user].u_obj)); + tstr = mp_obj_str_get_str(args[ARG_user].u_obj); + if (strlen(tstr) >= MQTT_MAX_USERNAME_LEN) { + mp_raise_ValueError("User name too long"); + } + sprintf(mqtt_cfg.username, "%s", tstr); } + // Password if (MP_OBJ_IS_STR(args[ARG_pass].u_obj)) { - snprintf(self->client->settings->password, CONFIG_MQTT_MAX_PASSWORD_LEN, mp_obj_str_get_str(args[ARG_pass].u_obj)); + tstr = mp_obj_str_get_str(args[ARG_pass].u_obj); + if (strlen(tstr) >= MQTT_MAX_PASSWORD_LEN) { + mp_raise_ValueError("Password too long"); + } + sprintf(mqtt_cfg.password, "%s", tstr); } + // Client ID if (MP_OBJ_IS_STR(args[ARG_clientid].u_obj)) { - snprintf(self->client->settings->client_id, CONFIG_MQTT_MAX_CLIENT_LEN, mp_obj_str_get_str(args[ARG_clientid].u_obj)); + tstr = mp_obj_str_get_str(args[ARG_clientid].u_obj); + if (strlen(tstr) >= MQTT_MAX_CLIENT_LEN) { + mp_raise_ValueError("Client ID too long"); + } + sprintf(mqtt_cfg.client_id, "%s", tstr); + } + else sprintf(mqtt_cfg.client_id, "mpy_mqtt_client"); + + mqtt_cfg.disable_auto_reconnect = args[ARG_reconnect].u_int ? false : true; + mqtt_cfg.keepalive = args[ARG_keepalive].u_int; + mqtt_cfg.disable_clean_session = args[ARG_cleansess].u_int ? false : true; + + // LWT options + if (MP_OBJ_IS_STR(args[ARG_lwt_topic].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_lwt_topic].u_obj); + if (strlen(tstr) >= MQTT_MAX_LWT_TOPIC) { + mp_raise_ValueError("LWT topic too long"); + } + sprintf(mqtt_cfg.lwt_topic, "%s", tstr); + if (MP_OBJ_IS_STR(args[ARG_lwt_msg].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_lwt_msg].u_obj); + if (strlen(tstr) >= MQTT_MAX_LWT_MSG) { + mp_raise_ValueError("LWT message too long"); + } + sprintf(mqtt_cfg.lwt_msg, "%s", tstr); + } + else sprintf(mqtt_cfg.lwt_msg, "offline"); + mqtt_cfg.lwt_qos = args[ARG_lwt_qos].u_int; + mqtt_cfg.lwt_retain = args[ARG_lwt_retain].u_int; } - else sprintf(self->client->settings->client_id, "mpy_mqtt_client"); - self->client->settings->auto_reconnect = args[ARG_reconnect].u_int; - self->client->settings->keepalive = args[ARG_keepalive].u_int; - self->client->settings->clean_session = args[ARG_cleansess].u_int; - sprintf(self->client->settings->lwt_topic, "/lwt"); - sprintf(self->client->settings->lwt_msg, "offline"); - self->client->settings->lwt_qos = args[ARG_qos].u_int; - self->client->settings->lwt_retain = args[ARG_retain].u_int; + // Get Certificate from file + if (MP_OBJ_IS_STR(args[ARG_cert].u_obj)) { + char *fname = NULL; + char fullname[128] = {'\0'}; + + fname = (char *)mp_obj_str_get_str(args[ARG_cert].u_obj); + + int res = physicalPath(fname, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + mp_raise_ValueError("Certificate file not found"); + } + struct stat sb; + if (stat(fullname, &sb) != 0) { + mp_raise_ValueError("Error opening certificate file"); + } + int size = sb.st_size; + FILE *fhndl = fopen(fullname, "rb"); + if (fhndl != NULL) { + if (self->certbuf) { + free(self->certbuf); + self->certbuf = NULL; + } + self->certbuf = malloc(size); + if (self->certbuf == NULL) { + fclose(fhndl); + mp_raise_ValueError("Error allocating certification buffer"); + } + int len = fread(self->certbuf, 1, size, fhndl); // read cert file + fclose(fhndl); + if (len != size) { + free(self->certbuf); + self->certbuf = NULL; + mp_raise_ValueError("Error reading certificate file"); + } + mqtt_cfg.cert_pem = (const char *)self->certbuf; + } + else { + mp_raise_ValueError("Error opening certificate file"); + } + } - // set callbacks + // Set callbacks if ((MP_OBJ_IS_FUN(args[ARG_datacb].u_obj)) || (MP_OBJ_IS_METH(args[ARG_datacb].u_obj))) { - self->client->settings->data_cb = (void*)data_cb; - self->client->settings->mpy_data_cb = args[ARG_datacb].u_obj; + self->mpy_data_cb = args[ARG_datacb].u_obj; } if ((MP_OBJ_IS_FUN(args[ARG_connected].u_obj)) || (MP_OBJ_IS_METH(args[ARG_connected].u_obj))) { - self->client->settings->connected_cb = (void*)connected_cb; - self->client->settings->mpy_connected_cb = args[ARG_connected].u_obj; + self->mpy_connected_cb = args[ARG_connected].u_obj; } if ((MP_OBJ_IS_FUN(args[ARG_disconnected].u_obj)) || (MP_OBJ_IS_METH(args[ARG_disconnected].u_obj))) { - self->client->settings->disconnected_cb = (void*)disconnected_cb; - self->client->settings->mpy_disconnected_cb = args[ARG_disconnected].u_obj; + self->mpy_disconnected_cb = args[ARG_disconnected].u_obj; } if ((MP_OBJ_IS_FUN(args[ARG_subscribed].u_obj)) || (MP_OBJ_IS_METH(args[ARG_subscribed].u_obj))) { - self->client->settings->subscribe_cb = (void*)subscribed_cb; - self->client->settings->mpy_subscribed_cb = args[ARG_subscribed].u_obj; + self->mpy_subscribed_cb = args[ARG_subscribed].u_obj; } if ((MP_OBJ_IS_FUN(args[ARG_unsubscribed].u_obj)) || (MP_OBJ_IS_METH(args[ARG_unsubscribed].u_obj))) { - self->client->settings->unsubscribe_cb = (void*)unsubscribed_cb; - self->client->settings->mpy_unsubscribed_cb = args[ARG_unsubscribed].u_obj; + self->mpy_unsubscribed_cb = args[ARG_unsubscribed].u_obj; } if ((MP_OBJ_IS_FUN(args[ARG_published].u_obj)) || (MP_OBJ_IS_METH(args[ARG_published].u_obj))) { - self->client->settings->publish_cb = (void*)published_cb; - self->client->settings->mpy_published_cb = args[ARG_published].u_obj; + self->mpy_published_cb = args[ARG_published].u_obj; } - // Start the mqtt task - int res = mqtt_start(self->client); - if (res != 0) { - free(self->client->settings); - free(self->client); - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Error starting client")); + self->base.type = &mqtt_type; + + self->client = esp_mqtt_client_init(&mqtt_cfg); + if (self->client == NULL) { + mp_raise_ValueError("Error initializing mqtt client"); } - self->base.type = &mqtt_type; + self->client->mpy_mqtt_obj = self; + //esp_mqtt_client_start(self->client); return MP_OBJ_FROM_PTR(self); } @@ -395,131 +537,257 @@ STATIC mp_obj_t mqtt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n //------------------------------------------------------------------------------------------ STATIC mp_obj_t mqtt_op_config(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_clientid, ARG_reconnect, ARG_cleansess, ARG_keepalive, ARG_qos, ARG_retain, ARG_secure, - ARG_datacb, ARG_connected, ARG_disconnected, ARG_subscribed, ARG_unsubscribed, ARG_published }; - mqtt_obj_t *self = pos_args[0]; - if (checkClient(self)) return mp_const_none; - - const mp_arg_t mqtt_config_allowed_args[] = { - { MP_QSTR_clientid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_autoreconnect, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_cleansession, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_keepalive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_qos, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_retain, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_secure, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_data_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_connected_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_disconnected_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_subscribed_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_unsubscribed_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_published_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + enum { ARG_server, ARG_user, ARG_pass, ARG_port, ARG_reconnect, ARG_clientid, ARG_cleansess, ARG_keepalive, ARG_lwt_topic, ARG_lwt_msg, + ARG_lwt_qos, ARG_lwt_retain, ARG_datacb, ARG_connected, ARG_disconnected, ARG_subscribed, ARG_unsubscribed, ARG_published }; + + const mp_arg_t mqtt_config_allowed_args[] = { + { MP_QSTR_server, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_user, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_password, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_autoreconnect, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_clientid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cleansession, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_keepalive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_lwt_topic, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_lwt_msg, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_lwt_qos, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_lwt_retain, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_data_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_connected_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_disconnected_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_subscribed_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_unsubscribed_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_published_cb, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; - mp_arg_val_t args[MP_ARRAY_SIZE(mqtt_config_allowed_args)]; + + mqtt_obj_t *self = pos_args[0]; + if (!self->client) { + mp_raise_ValueError("Destroyed"); + } + if (self->client->state < MQTT_STATE_INIT) { + mp_raise_ValueError("Not initialized"); + } + + mp_arg_val_t args[MP_ARRAY_SIZE(mqtt_config_allowed_args)]; mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(mqtt_config_allowed_args), mqtt_config_allowed_args, args); - if (args[ARG_secure].u_int >= 0) self->client->settings->use_ssl = args[ARG_secure].u_bool; - if (MP_OBJ_IS_STR(args[ARG_clientid].u_obj)) { - snprintf(self->client->settings->client_id, CONFIG_MQTT_MAX_CLIENT_LEN, mp_obj_str_get_str(args[ARG_clientid].u_obj)); + const char *tstr = NULL; + bool has_conn_arg = false; + if ((MP_OBJ_IS_STR(args[ARG_server].u_obj)) || (args[ARG_port].u_int > 0) || (MP_OBJ_IS_STR(args[ARG_user].u_obj)) || + (MP_OBJ_IS_STR(args[ARG_pass].u_obj)) || (MP_OBJ_IS_STR(args[ARG_clientid].u_obj)) || + (args[ARG_reconnect].u_int >= 0) || (args[ARG_keepalive].u_int > 0) || (args[ARG_cleansess].u_int >= 0) || + (MP_OBJ_IS_STR(args[ARG_lwt_topic].u_obj)) ) has_conn_arg = true; + + if ((has_conn_arg) && (self->client->state < MQTT_STATE_CONNECTED)) { + // not started, we can change all parameters + // URI + if (MP_OBJ_IS_STR(args[ARG_server].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_server].u_obj); + if (strlen(tstr) >= MQTT_MAX_HOST_LEN) { + mp_raise_ValueError("URI too long"); + } + sprintf(self->client->config->uri, "%s", tstr); + } + + // Port + if (args[ARG_port].u_int > 0) self->client->config->port = args[ARG_port].u_int; + + // User name + if (MP_OBJ_IS_STR(args[ARG_user].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_user].u_obj); + if (strlen(tstr) >= MQTT_MAX_USERNAME_LEN) { + mp_raise_ValueError("User name too long"); + } + sprintf(self->client->connect_info.username, "%s", tstr); + } + // Password + if (MP_OBJ_IS_STR(args[ARG_pass].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_pass].u_obj); + if (strlen(tstr) >= MQTT_MAX_PASSWORD_LEN) { + mp_raise_ValueError("Password too long"); + } + sprintf(self->client->connect_info.password, "%s", tstr); + } + // Client ID + if (MP_OBJ_IS_STR(args[ARG_clientid].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_clientid].u_obj); + if (strlen(tstr) >= MQTT_MAX_CLIENT_LEN) { + mp_raise_ValueError("Client ID too long"); + } + sprintf(self->client->connect_info.client_id, "%s", tstr); + } + else sprintf(self->client->connect_info.client_id, "mpy_mqtt_client"); + + if (args[ARG_reconnect].u_int >= 0) self->client->config->auto_reconnect = args[ARG_reconnect].u_int ? true : false; + if (args[ARG_keepalive].u_int > 0) self->client->connect_info.keepalive = args[ARG_keepalive].u_int; + if (args[ARG_cleansess].u_int >= 0) self->client->connect_info.clean_session = args[ARG_cleansess].u_int ? true : false; + + // LWT options + if (MP_OBJ_IS_STR(args[ARG_lwt_topic].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_lwt_topic].u_obj); + if (strlen(tstr) >= MQTT_MAX_LWT_TOPIC) { + mp_raise_ValueError("LWT topic too long"); + } + sprintf(self->client->connect_info.will_topic, "%s", tstr); + if (MP_OBJ_IS_STR(args[ARG_lwt_msg].u_obj)) { + tstr = mp_obj_str_get_str(args[ARG_lwt_msg].u_obj); + if (strlen(tstr) >= MQTT_MAX_LWT_MSG) { + mp_raise_ValueError("LWT message too long"); + } + sprintf(self->client->connect_info.will_topic, "%s", tstr); + } + if (args[ARG_lwt_qos].u_int >= 0) self->client->connect_info.will_qos = args[ARG_lwt_qos].u_int; + if (args[ARG_lwt_retain].u_int >= 0) self->client->connect_info.will_retain = args[ARG_lwt_retain].u_int; + } } - if (args[ARG_reconnect].u_int >= 0) self->client->settings->auto_reconnect = args[ARG_reconnect].u_int; - if (args[ARG_keepalive].u_int >= 0) self->client->settings->keepalive = args[ARG_keepalive].u_int; - if (args[ARG_qos].u_int >= 0) self->client->settings->lwt_qos = args[ARG_qos].u_int; - if (args[ARG_retain].u_int >= 0) self->client->settings->lwt_retain = args[ARG_retain].u_int; - if (args[ARG_cleansess].u_int >= 0) self->client->settings->clean_session = args[ARG_cleansess].u_int; + // Callbacks if ((MP_OBJ_IS_FUN(args[ARG_datacb].u_obj)) || (MP_OBJ_IS_METH(args[ARG_datacb].u_obj))) { - self->client->settings->data_cb = NULL; - self->client->settings->mpy_data_cb = args[ARG_datacb].u_obj; - self->client->settings->data_cb = (void*)data_cb; + self->mpy_data_cb = NULL; + self->mpy_data_cb = args[ARG_datacb].u_obj; } + else if (args[ARG_datacb].u_obj == mp_const_false) self->mpy_data_cb = NULL; + if ((MP_OBJ_IS_FUN(args[ARG_connected].u_obj)) || (MP_OBJ_IS_METH(args[ARG_connected].u_obj))) { - self->client->settings->connected_cb = NULL; - self->client->settings->mpy_connected_cb = args[ARG_connected].u_obj; - self->client->settings->connected_cb = (void*)connected_cb; + self->mpy_connected_cb = NULL; + self->mpy_connected_cb = args[ARG_connected].u_obj; } + else if (args[ARG_connected].u_obj == mp_const_false) self->mpy_connected_cb = NULL; + if ((MP_OBJ_IS_FUN(args[ARG_disconnected].u_obj)) || (MP_OBJ_IS_METH(args[ARG_disconnected].u_obj))) { - self->client->settings->disconnected_cb = NULL; - self->client->settings->mpy_disconnected_cb = args[ARG_disconnected].u_obj; - self->client->settings->disconnected_cb = (void*)disconnected_cb; + self->mpy_disconnected_cb = NULL; + self->mpy_disconnected_cb = args[ARG_disconnected].u_obj; } + else if (args[ARG_disconnected].u_obj == mp_const_false) self->mpy_disconnected_cb = NULL; + if ((MP_OBJ_IS_FUN(args[ARG_subscribed].u_obj)) || (MP_OBJ_IS_METH(args[ARG_subscribed].u_obj))) { - self->client->settings->subscribe_cb = NULL; - self->client->settings->mpy_subscribed_cb = args[ARG_subscribed].u_obj; - self->client->settings->subscribe_cb = (void*)subscribed_cb; + self->mpy_subscribed_cb = NULL; + self->mpy_subscribed_cb = args[ARG_subscribed].u_obj; } + else if (args[ARG_subscribed].u_obj == mp_const_false) self->mpy_subscribed_cb = NULL; + if ((MP_OBJ_IS_FUN(args[ARG_unsubscribed].u_obj)) || (MP_OBJ_IS_METH(args[ARG_unsubscribed].u_obj))) { - self->client->settings->unsubscribe_cb = NULL; - self->client->settings->mpy_unsubscribed_cb = args[ARG_unsubscribed].u_obj; - self->client->settings->unsubscribe_cb = (void*)unsubscribed_cb; + self->mpy_unsubscribed_cb = NULL; + self->mpy_unsubscribed_cb = args[ARG_unsubscribed].u_obj; } + else if (args[ARG_unsubscribed].u_obj == mp_const_false) self->mpy_unsubscribed_cb = NULL; + if ((MP_OBJ_IS_FUN(args[ARG_published].u_obj)) || (MP_OBJ_IS_METH(args[ARG_published].u_obj))) { - self->client->settings->publish_cb = NULL; - self->client->settings->mpy_published_cb = args[ARG_published].u_obj; - self->client->settings->publish_cb = (void*)published_cb; + self->mpy_published_cb = NULL; + self->mpy_published_cb = args[ARG_published].u_obj; } + else if (args[ARG_published].u_obj == mp_const_false) self->mpy_published_cb = NULL; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mqtt_config_obj, 1, mqtt_op_config); -//-------------------------------------------------------------------- -STATIC mp_obj_t mqtt_op_subscribe(mp_obj_t self_in, mp_obj_t topic_in) +//----------------------------------------------------------------------- +STATIC mp_obj_t mqtt_op_subscribe(mp_uint_t n_args, const mp_obj_t *args) { - mqtt_obj_t *self = self_in; - if (checkClient(self)) return mp_const_false; + mqtt_obj_t *self = args[0]; + if (checkClient(self) != MQTT_STATE_CONNECTED) return mp_const_false; - const char *topic = mp_obj_str_get_str(topic_in); + const char *topic = mp_obj_str_get_str(args[1]); int wait = 2000; - mqtt_subscribe(self->client, topic, self->client->settings->lwt_qos); - while ((wait > 0) && (self->client->subs_flag == 0)) { + int qos = 0; + if (n_args == 3) { + qos = mp_obj_get_int(args[2]); + if ((qos < 0) || (qos > 2)) { + mp_raise_ValueError("Wrong QoS value"); + } + } + + self->subs_flag = 0; + self->client->config->user_context = (void *)topic; + + int res = esp_mqtt_client_subscribe(self->client, topic, qos); + if (res < 0) { + self->client->config->user_context = NULL; + return mp_const_false; + } + while ((wait > 0) && (self->subs_flag == 0)) { vTaskDelay(10 / portTICK_PERIOD_MS); wait -= 10; } + self->client->config->user_context = NULL; if (wait) return mp_const_true; else return mp_const_false; } -MP_DEFINE_CONST_FUN_OBJ_2(mqtt_subscribe_obj, mqtt_op_subscribe); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mqtt_subscribe_obj, 2, 3, mqtt_op_subscribe); //---------------------------------------------------------------------- STATIC mp_obj_t mqtt_op_unsubscribe(mp_obj_t self_in, mp_obj_t topic_in) { mqtt_obj_t *self = self_in; - if (checkClient(self)) return mp_const_false; + if (checkClient(self) != MQTT_STATE_CONNECTED) return mp_const_false; const char *topic = mp_obj_str_get_str(topic_in); int wait = 2000; - mqtt_unsubscribe(self->client, topic); - while ((wait > 0) && (self->client->unsubs_flag == 0)) { + self->unsubs_flag = 0; + self->client->config->user_context = (void *)topic; + + int res = esp_mqtt_client_unsubscribe(self->client, topic); + if (res < 0) { + self->client->config->user_context = NULL; + return mp_const_false; + } + while ((wait > 0) && (self->unsubs_flag == 0)) { vTaskDelay(10 / portTICK_PERIOD_MS); wait -= 10; } + self->client->config->user_context = NULL; if (wait) return mp_const_true; else return mp_const_false; } MP_DEFINE_CONST_FUN_OBJ_2(mqtt_unsubscribe_obj, mqtt_op_unsubscribe); -//----------------------------------------------------------------------------------- -STATIC mp_obj_t mqtt_op_publish(mp_obj_t self_in, mp_obj_t topic_in, mp_obj_t msg_in) +//--------------------------------------------------------------------- +STATIC mp_obj_t mqtt_op_publish(mp_uint_t n_args, const mp_obj_t *args) { - mqtt_obj_t *self = self_in; - if (checkClient(self)) return mp_const_false; + mqtt_obj_t *self = args[0]; + if (checkClient(self) != MQTT_STATE_CONNECTED) return mp_const_false; size_t len; - const char *topic = mp_obj_str_get_str(topic_in); - const char *msg = mp_obj_str_get_data(msg_in, &len); - int res = mqtt_publish(self->client, topic, msg, len, self->client->settings->lwt_qos, self->client->settings->lwt_retain); + const char *topic = mp_obj_str_get_str(args[1]); + const char *msg = mp_obj_str_get_data(args[2], &len); + + int wait = 2000; + int qos = 0; + if (n_args == 4) { + qos = mp_obj_get_int(args[3]); + if ((qos < 0) || (qos > 2)) { + mp_raise_ValueError("Wrong QoS value"); + } + } + if (qos == 0) wait = 0; + + int retain = 0; + if (n_args == 5) retain = mp_obj_is_true(args[4]); + + self->publish_flag = 0; + self->client->config->user_context = (void *)topic; + + int res = esp_mqtt_client_publish(self->client, topic, msg, len, qos, retain); + if (res < 0) { + self->client->config->user_context = NULL; + return mp_const_false; + } + while ((wait > 0) && (self->publish_flag == 0)) { + vTaskDelay(10 / portTICK_PERIOD_MS); + wait -= 10; + } + self->client->config->user_context = NULL; - if (res < 0) return mp_const_false; return mp_const_true; } -MP_DEFINE_CONST_FUN_OBJ_3(mqtt_publish_obj, mqtt_op_publish); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mqtt_publish_obj, 3, 5, mqtt_op_publish); //---------------------------------------------- STATIC mp_obj_t mqtt_op_status(mp_obj_t self_in) { mqtt_obj_t *self = self_in; - checkClient(self); char sstat[16]; mp_obj_t tuple[2]; @@ -529,14 +797,14 @@ STATIC mp_obj_t mqtt_op_status(mp_obj_t self_in) sprintf(sstat, "Destroyed"); } else { - tuple[0] = mp_obj_new_int(self->client->status); - if (self->client->status == MQTT_STATUS_CONNECTED) sprintf(sstat, "Connected"); - else if (self->client->status == MQTT_STATUS_DISCONNECTED) sprintf(sstat, "Disconnected"); - else if (self->client->status == MQTT_STATUS_STOPPING) sprintf(sstat, "Stopping"); - else if (self->client->status == MQTT_STATUS_STOPPED) sprintf(sstat, "Stopped"); - else sprintf(sstat, "Unknown"); + tuple[0] = mp_obj_new_int(self->client->state); + if (self->client->state == MQTT_STATE_CONNECTED) sprintf(sstat, "Connected"); + else if (self->client->state == MQTT_STATE_INIT) sprintf(sstat, "Initialized"); + else if (self->client->state == MQTT_STATE_WAIT_TIMEOUT) sprintf(sstat, "Wait timeout"); + else if (self->client->state == MQTT_STATE_UNKNOWN) sprintf(sstat, "Unknown"); + else sprintf(sstat, "Error"); } - tuple[1] = mp_obj_new_str(sstat, strlen(sstat), 0); + tuple[1] = mp_obj_new_str(sstat, strlen(sstat)); return mp_obj_new_tuple(2, tuple); } @@ -546,11 +814,13 @@ MP_DEFINE_CONST_FUN_OBJ_1(mqtt_status_obj, mqtt_op_status); STATIC mp_obj_t mqtt_op_stop(mp_obj_t self_in) { mqtt_obj_t *self = self_in; - int status = checkClient(self); - if (status < 2) { - mqtt_stop(self->client); - vTaskDelay(100 / portTICK_RATE_MS); + if ((self->client) && (self->client->state >= MQTT_STATE_INIT)) { + esp_mqtt_client_stop(self->client); + int status = 0; + while ((status < 20) && ((xEventGroupGetBits(self->client->status_bits) & 1) == 0)) { + vTaskDelay(100 / portTICK_RATE_MS); + } } return mp_const_none; } @@ -561,15 +831,12 @@ STATIC mp_obj_t mqtt_op_start(mp_obj_t self_in) { mqtt_obj_t *self = self_in; - if ((self->client) && (self->client->status == MQTT_STATUS_STOPPED) && (self->client->settings->xMqttTask == NULL)) { - int res = mqtt_start(self->client); - if (res != 0) { - free(self->client->settings); - free(self->client); + if ((self->client) && (self->client->state < MQTT_STATE_INIT)) { + int res = esp_mqtt_client_start(self->client); + if (res != ESP_OK) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Error starting client")); } } - return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(mqtt_start_obj, mqtt_op_start); @@ -578,11 +845,32 @@ MP_DEFINE_CONST_FUN_OBJ_1(mqtt_start_obj, mqtt_op_start); STATIC mp_obj_t mqtt_op_free(mp_obj_t self_in) { mqtt_obj_t *self = self_in; - if ((self->client) && (self->client->status == MQTT_STATUS_STOPPED) && (self->client->settings->xMqttTask == NULL)) { - free(self->client->settings); - free(self->client); + + if (self->client) { + self->mpy_data_cb = NULL; + self->mpy_connected_cb = NULL; + self->mpy_disconnected_cb = NULL; + self->mpy_subscribed_cb = NULL; + self->mpy_unsubscribed_cb = NULL; + self->mpy_published_cb = NULL; + + esp_mqtt_client_destroy(self->client); self->client = NULL; - return mp_const_true; + + if (self->msgbuf) { + free(self->msgbuf); + self->msgbuf = NULL; + } + if (self->topicbuf) { + free(self->topicbuf); + self->topicbuf = NULL; + } + if (self->certbuf) { + free(self->certbuf); + self->certbuf = NULL; + } + + return mp_const_true; } return mp_const_false; } diff --git a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c index 2424de72..55b6956e 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c +++ b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c @@ -40,20 +40,18 @@ #include "freertos/task.h" #include "sdkconfig.h" +#include "libs/libGSM.h" #include "py/nlr.h" #include "py/objlist.h" #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" -#include "py/obj.h" #include "netutils.h" #include "esp_wifi.h" -#include "esp_wifi_types.h" #include "esp_log.h" #include "esp_event_loop.h" #include "esp_log.h" #include "lwip/dns.h" -#include "tcpip_adapter.h" #ifdef CONFIG_MICROPY_USE_MDNS #include "mdns.h" #endif @@ -61,10 +59,14 @@ #include "modnetwork.h" #define MODNETWORK_INCLUDE_CONSTANTS (1) +//#define MPY_WIFI_USED_STORAGE WIFI_STORAGE_FLASH +#define MPY_WIFI_USED_STORAGE WIFI_STORAGE_RAM + +static const char *MODNETTWORK_TAG = "[modnetwork]"; NORETURN void _esp_exceptions(esp_err_t e) { switch (e) { - case ESP_ERR_WIFI_NOT_INIT: + case ESP_ERR_WIFI_NOT_INIT: mp_raise_msg(&mp_type_OSError, "Wifi Not Initialized"); break; case ESP_ERR_WIFI_NOT_STARTED: @@ -76,7 +78,7 @@ NORETURN void _esp_exceptions(esp_err_t e) { case ESP_ERR_WIFI_SSID: mp_raise_msg(&mp_type_OSError, "Wifi SSID Invalid"); break; - case ESP_ERR_WIFI_FAIL: + case ESP_FAIL: mp_raise_msg(&mp_type_OSError, "Wifi Internal Failure"); break; case ESP_ERR_WIFI_IF: @@ -85,7 +87,7 @@ NORETURN void _esp_exceptions(esp_err_t e) { case ESP_ERR_WIFI_MAC: mp_raise_msg(&mp_type_OSError, "Wifi Invalid MAC Address"); break; - case ESP_ERR_WIFI_ARG: + case ESP_ERR_INVALID_ARG: mp_raise_msg(&mp_type_OSError, "Wifi Invalid Argument"); break; case ESP_ERR_WIFI_MODE: @@ -110,8 +112,8 @@ NORETURN void _esp_exceptions(esp_err_t e) { mp_raise_OSError(MP_ETIMEDOUT); break; case ESP_ERR_TCPIP_ADAPTER_NO_MEM: - case ESP_ERR_WIFI_NO_MEM: - mp_raise_OSError(MP_ENOMEM); + case ESP_ERR_NO_MEM: + mp_raise_OSError(MP_ENOMEM); break; default: nlr_raise(mp_obj_new_exception_msg_varg( @@ -138,6 +140,7 @@ static const char* const wifi_events[] = { "Soft-AP stop", "Station connected to soft-AP", "Station disconnected from ESP32 soft-AP", + "Soft-AP assigned an IP to a connected station", "Receive probe request packet in soft-AP interface", "Station or ap or ethernet interface v6IP addr is preferred", "Ethernet start", @@ -147,6 +150,27 @@ static const char* const wifi_events[] = { "Ethernet got IP from connected AP", }; +/* +static const char* const wifi_cyphers[] = { + "NONE", + "WEP40", + "WEP104", + "TKIP", + "CCMP", + "TKIP_CCMP", + "UNKNOWN", +}; +*/ + +static const char* const wifi_auth_modes[] = { + "OPEN", + "WEP", + "WPA_PSK", + "WPA2_PSK", + "WPA_WPA2_PSK", + "WPA2_ENTERPRISE", +}; + static inline void esp_exceptions(esp_err_t e) { if (e != ESP_OK) _esp_exceptions(e); } @@ -154,23 +178,24 @@ static inline void esp_exceptions(esp_err_t e) { #define ESP_EXCEPTIONS(x) do { esp_exceptions(x); } while (0); // global variables +int wifi_network_state = WIFI_STATE_NOTINIT; bool wifi_sta_isconnected = false; bool wifi_sta_has_ipaddress = false; bool wifi_sta_changed_ipaddress = false; bool wifi_ap_isconnected = false; +bool wifi_ap_sta_isconnected = false; +tcpip_adapter_if_t tcpip_if[MAX_ACTIVE_INTERFACES] = {TCPIP_ADAPTER_IF_MAX}; const mp_obj_type_t wlan_if_type; -const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA}; -const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP}; +const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA, WIFI_MODE_STA}; +const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP, WIFI_MODE_AP}; //static wifi_config_t wifi_ap_config = { 0 }; static wifi_config_t wifi_sta_config = { 0 }; -// Set to "true" if the STA interface is requested to be connected by the -// user, used for automatic reconnect. -static bool wifi_sta_connected = false; - -static uint8_t _isConnected = 0; +// Set to "true" if the STA interface is requested to be automatically reconnected. +static bool wifi_sta_reconnect = false; +static bool sta_isStarted = false; static mp_obj_t event_callback = NULL; static mp_obj_t probereq_callback = NULL; @@ -241,9 +266,11 @@ static void processEvent_callback(system_event_t *event) } case SYSTEM_EVENT_AP_STOP: { wifi_ap_isconnected = false; + wifi_ap_sta_isconnected = false; break; } case SYSTEM_EVENT_AP_STACONNECTED: { + wifi_ap_sta_isconnected = true; system_event_ap_staconnected_t *info = (system_event_ap_staconnected_t *)&event->event_info; if (event_callback) { mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); @@ -255,6 +282,7 @@ static void processEvent_callback(system_event_t *event) break; } case SYSTEM_EVENT_AP_STADISCONNECTED: { + wifi_ap_sta_isconnected = false; system_event_ap_stadisconnected_t *info = (system_event_ap_stadisconnected_t *)&event->event_info; if (event_callback) { mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); @@ -295,7 +323,6 @@ static void processEvent_callback(system_event_t *event) break; } case SYSTEM_EVENT_STA_LOST_IP: { - system_event_sta_got_ip_t *info = (system_event_sta_got_ip_t *)&event->event_info; wifi_sta_has_ipaddress = false; wifi_sta_changed_ipaddress = true; break; @@ -335,60 +362,60 @@ static void processEvent_callback(system_event_t *event) } } +//------------------------ +static void tryReconnect() +{ + if (wifi_sta_reconnect) { + wifi_mode_t mode; + if (esp_wifi_get_mode(&mode) == ESP_OK) { + if (mode & WIFI_MODE_STA) { + if (sta_isStarted) { + // STA is active and started, attempt to reconnect. + esp_err_t res = esp_wifi_connect(); + if (res != ESP_OK) { + ESP_LOGD(MODNETTWORK_TAG, "error attempting to reconnect: (%d)", res-ESP_ERR_WIFI_BASE); + } + } + } + } + } +} // This function is called by the system-event task and so runs in a different // thread to the main MicroPython task. It must not raise any Python exceptions. //-------------------------------------------------------------- static esp_err_t event_handler(void *ctx, system_event_t *event) { if (wifi_mutex) xSemaphoreTake(wifi_mutex, 1000); - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_LOGI("wifi", "STA_START"); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI("network", "GOT_IP"); - _isConnected = 1; - break; - case SYSTEM_EVENT_STA_DISCONNECTED: { - // This is a workaround as ESP32 WiFi libs don't currently - // auto-reassociate. - _isConnected = 0; - system_event_sta_disconnected_t *disconn = &event->event_info.disconnected; - ESP_LOGI("wifi", "STA_DISCONNECTED, reason:%d", disconn->reason); - switch (disconn->reason) { - case WIFI_REASON_BEACON_TIMEOUT: - mp_printf(MP_PYTHON_PRINTER, "beacon timeout\n"); - // AP has dropped out; try to reconnect. - break; - case WIFI_REASON_NO_AP_FOUND: - mp_printf(MP_PYTHON_PRINTER, "no AP found\n"); - // AP may not exist, or it may have momentarily dropped out; try to reconnect. - break; - case WIFI_REASON_AUTH_FAIL: - mp_printf(MP_PYTHON_PRINTER, "authentication failed\n"); - wifi_sta_connected = false; - break; - default: - // Let other errors through and try to reconnect. - break; - } - if (wifi_sta_connected) { - wifi_mode_t mode; - if (esp_wifi_get_mode(&mode) == ESP_OK) { - if (mode & WIFI_MODE_STA) { - // STA is active so attempt to reconnect. - esp_err_t e = esp_wifi_connect(); - if (e != ESP_OK) { - mp_printf(MP_PYTHON_PRINTER, "error attempting to reconnect: 0x%04x", e); - } - } + + if (wifi_network_state == WIFI_STATE_STARTED) { + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + sta_isStarted = true; + tryReconnect(); + break; + case SYSTEM_EVENT_STA_STOP: + sta_isStarted = false; + break; + case SYSTEM_EVENT_STA_DISCONNECTED: { + // This is a workaround as ESP32 WiFi library doesn't currently auto-reconnect. + system_event_sta_disconnected_t *disconn = &event->event_info.disconnected; + switch (disconn->reason) { + case WIFI_REASON_AUTH_FAIL: + wifi_sta_reconnect = false; + break; + case WIFI_REASON_ASSOC_LEAVE: + sta_isStarted = false; + break; + default: + // Let other errors through and try to reconnect. + break; } + tryReconnect(); + break; + } + default: + break; } - break; - } - default: - ESP_LOGI("network", "event %d", event->event_id); - break; } #ifdef CONFIG_MICROPY_USE_MDNS @@ -396,19 +423,12 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) #endif // === Handle events callbacks === - processEvent_callback(event); + if (wifi_network_state == WIFI_STATE_STARTED) processEvent_callback(event); if (wifi_mutex) xSemaphoreGive(wifi_mutex); return ESP_OK; } -/*void error_check(bool status, const char *msg) { - if (!status) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg)); - } -} -*/ - //--------------------------------------------------- STATIC void require_if(mp_obj_t wlan_if, int if_no) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if); @@ -417,43 +437,15 @@ STATIC void require_if(mp_obj_t wlan_if, int if_no) { } } -//------------------------------------------------------------- -STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) { - static int initialized = 0; - if (!initialized) { - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_LOGD("modnetwork", "Initializing WiFi"); - ESP_EXCEPTIONS( esp_wifi_init(&cfg) ); - ESP_EXCEPTIONS( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); - ESP_LOGD("modnetwork", "Initialized"); - ESP_EXCEPTIONS( esp_wifi_set_mode(0) ); - ESP_EXCEPTIONS( esp_wifi_start() ); - ESP_LOGD("modnetwork", "Started"); - - initialized = 1; - } - - int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : WIFI_IF_STA; - if (idx == WIFI_IF_STA) { - return MP_OBJ_FROM_PTR(&wlan_sta_obj); - } else if (idx == WIFI_IF_AP) { - return MP_OBJ_FROM_PTR(&wlan_ap_obj); - } else { - mp_raise_ValueError("invalid WLAN interface identifier"); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan); - //-------------------------------- STATIC mp_obj_t esp_initialize() { - static int initialized = 0; - if (!initialized) { - ESP_LOGD("modnetwork", "Initializing TCP/IP"); + if (wifi_network_state < WIFI_STATE_INIT) { + // This is executed only once + ESP_LOGD(MODNETTWORK_TAG, "Initializing TCP/IP"); tcpip_adapter_init(); - ESP_LOGD("modnetwork", "Initializing Event Loop"); + ESP_LOGD(MODNETTWORK_TAG, "Initializing Event Loop"); ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) ); - ESP_LOGD("modnetwork", "esp_event_loop_init done"); + ESP_LOGD(MODNETTWORK_TAG, "Event loop initialized"); // create mutex's if (wifi_mutex == NULL) wifi_mutex = xSemaphoreCreateMutex(); @@ -461,7 +453,7 @@ STATIC mp_obj_t esp_initialize() { // add probe requests handler esp_wifi_set_sta_rx_probe_req(processPROBEREQRECVED); - initialized = 1; + wifi_network_state = WIFI_STATE_INIT; } return mp_const_none; } @@ -471,46 +463,262 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_initialize_obj, esp_initialize); #error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields! #endif -//--------------------------------------------------------------- -STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) { - wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); - wifi_mode_t mode; - ESP_EXCEPTIONS( esp_wifi_get_mode(&mode) ); - int bit = (self->if_id == WIFI_IF_STA) ? WIFI_MODE_STA : WIFI_MODE_AP; +// Return WLAN object for given WiFi mode (default: STA) +// Does not start WiFi if not started ! +//------------------------------------------------------------- +STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) { + if (wifi_network_state < WIFI_STATE_INIT) { + mp_raise_ValueError("TCT/IP Adapter not initialized"); + } - if (n_args > 1) { - bool active = mp_obj_is_true(args[1]); - mode = active ? (mode | bit) : (mode & ~bit); - ESP_EXCEPTIONS( esp_wifi_set_mode(mode) ); + // Default mode + int if_id = WIFI_IF_STA; + + if (n_args > 0) { + // Get required WiFi mode + if_id = mp_obj_get_int(args[0]); + if ((if_id != WIFI_IF_STA) && (if_id != WIFI_IF_AP)) { + mp_raise_ValueError("invalid WLAN interface identifier"); + } + } + + // Return the WLAN object + if (if_id == WIFI_IF_STA) return MP_OBJ_FROM_PTR(&wlan_sta_obj); + return MP_OBJ_FROM_PTR(&wlan_ap_obj); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan); + + +//---------------------- +static void _init_wifi() +{ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t ret = esp_wifi_init(&cfg); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error initializing WiFi (%d)", ret); + mp_raise_OSError(ret); + } + ret = esp_wifi_set_storage(MPY_WIFI_USED_STORAGE); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error initializing WiFi storage (%d)", ret); + mp_raise_OSError(ret); + } + ESP_LOGD(MODNETTWORK_TAG, "WiFi Initialized"); + wifi_network_state = WIFI_STATE_STOPPED; +} + +// Initialize WiFi if needed, set the requested mode and start WiFi +//------------------------------------------------------ +static void _wifi_init(wifi_mode_t mode, bool reconnect) +{ + if (wifi_network_state < WIFI_STATE_STOPPED) _init_wifi(); + + esp_err_t ret = 0; + if (wifi_network_state == WIFI_STATE_STARTED) { + // Stop WiFi + wifi_network_state = WIFI_STATE_STOPPED; + wifi_sta_isconnected = false; + wifi_sta_has_ipaddress = false; + wifi_sta_changed_ipaddress = false; + wifi_ap_isconnected = false; + wifi_ap_sta_isconnected = false; + ret = esp_wifi_stop(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error stopping WiFi (%d)", ret); + goto exit_error; + } + ESP_LOGD(MODNETTWORK_TAG, "WiFi Stopped"); + } + + // Set WiFi mode + esp_wifi_set_mode(mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error setting WiFi mode (%d)", ret); + goto exit_error; + } + // Start WiFi + ret = esp_wifi_start(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error starting WiFi (%d)", ret); + goto exit_error; } + wifi_sta_reconnect = reconnect; + + wifi_network_state = WIFI_STATE_STARTED; + ESP_LOGD(MODNETTWORK_TAG, "WiFi Started, mode %d", mode); + return; + +exit_error: + wifi_network_state = WIFI_STATE_INIT; + ret = esp_wifi_stop(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error stopping WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + esp_wifi_deinit(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error deinitializing WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + mp_raise_OSError(ret); +} + +// Activate (start) or deactivate (stop) Wifi +//------------------------------------------------------------- +STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) +{ + if (wifi_network_state < WIFI_STATE_INIT) { + ESP_LOGW(MODNETTWORK_TAG, "WiFi not initialized"); + return mp_const_false; + } + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + wifi_mode_t mode; + + if (n_args < 2) goto exit; + + // Get requested action + bool active = mp_obj_is_true(args[1]); + + if (active) { + // === WiFi activation requested === + if (wifi_network_state == WIFI_STATE_STARTED) { + // WiFi already started, check mode + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); + return mp_const_false; + } + // If requested mode is already started, just return + if (self->wifi_mode & mode) return mp_const_true; + // Restart WiFi adding a new mode + _wifi_init(mode | self->wifi_mode, (mode & WIFI_MODE_STA) & wifi_sta_reconnect); + } + else { + // Start WiFi + _wifi_init(self->wifi_mode, false); + } + } + else { + // === WiFi deactivation requested === + if (wifi_network_state == WIFI_STATE_STARTED) { + // Get current mode + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); + return mp_const_false; + } + if (self->wifi_mode & mode) { + wifi_mode_t new_mode = mode & ~self->wifi_mode; + if (new_mode == 0) { + // No mode is active, stop and deinitialize WiFi + wifi_network_state = WIFI_STATE_INIT; + wifi_sta_isconnected = false; + wifi_sta_has_ipaddress = false; + wifi_sta_changed_ipaddress = false; + wifi_ap_isconnected = false; + wifi_ap_sta_isconnected = false; + ret = esp_wifi_stop(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error stopping WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + esp_wifi_deinit(); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error deinitializing WiFi (%d)", ret); + } + vTaskDelay(5 / portTICK_PERIOD_MS); + ESP_LOGI(MODNETTWORK_TAG, "WiFi Stopped"); + } + else { + _wifi_init(new_mode, (new_mode & WIFI_MODE_STA) & wifi_sta_reconnect); + } + } + } + } - return (mode & bit) ? mp_const_true : mp_const_false; +exit: + // === Return wifi status (started/not started) === + if (wifi_network_state != WIFI_STATE_STARTED) return mp_const_false; + // Get current mode + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); + return mp_const_false; + } + if (self->wifi_mode & mode) return mp_const_true; + return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active); +//------------------------------------------ +static bool _check_wifi_started(bool except) +{ + if (wifi_network_state < WIFI_STATE_STARTED) { + if (except) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "WiFi not started")); + } + else { + ESP_LOGW(MODNETTWORK_TAG, "WiFi not started"); + return false; + } + } + return true; +} + +// Connect to access point (only in STA mode) //---------------------------------------------------------------- STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) { - wifi_mode_t mode; - ESP_EXCEPTIONS(esp_wifi_get_mode(&mode)); - if ((mode & WIFI_MODE_STA) == 0) return mp_const_none; + if (!_check_wifi_started(false)) return mp_const_none; + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->wifi_mode != WIFI_MODE_STA) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Not supported in AP mode")); + } + + wifi_mode_t mode; + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error getting WiFi mode (%d)", ret); + return mp_const_none; + } + // Only connect if in STA mode + if ((mode & WIFI_MODE_STA) == 0) { + ESP_LOGE(MODNETTWORK_TAG, "STA mode not started"); + return mp_const_none; + } mp_uint_t len; const char *p; if (n_args > 1) { + // Get SSID memset(&wifi_sta_config, 0, sizeof(wifi_sta_config)); p = mp_obj_str_get_data(args[1], &len); memcpy(wifi_sta_config.sta.ssid, p, MIN(len, sizeof(wifi_sta_config.sta.ssid))); + // Get password (optional) p = (n_args > 2) ? mp_obj_str_get_data(args[2], &len) : ""; memcpy(wifi_sta_config.sta.password, p, MIN(len, sizeof(wifi_sta_config.sta.password))); - ESP_EXCEPTIONS( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config) ); + if ((n_args > 3)) { + // Get channel (optional + int chan = mp_obj_get_int(args[3]); + if ((chan >= 1) && (chan <= 13)) wifi_sta_config.sta.channel = chan; + } + ret = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config); + if (ret != ESP_OK) { + ESP_LOGE(MODNETTWORK_TAG, "Error configuring WiFi (%d)", ret); + return mp_const_none; + } } MP_THREAD_GIL_EXIT(); - ESP_EXCEPTIONS( esp_wifi_connect() ); + ret = esp_wifi_connect(); MP_THREAD_GIL_ENTER(); - wifi_sta_connected = true; + if (ret == ESP_OK) wifi_sta_reconnect = true; + else { + ESP_LOGE(MODNETTWORK_TAG, "Error connecting to AP (%d)", ret); + } return mp_const_none; } @@ -518,40 +726,93 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 1, 7, esp_connect); //------------------------------------------------ STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) { - wifi_sta_connected = false; - ESP_EXCEPTIONS( esp_wifi_disconnect() ); + if (!_check_wifi_started(false)) return mp_const_none; + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->wifi_mode != WIFI_MODE_STA) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Not supported in AP mode")); + } + + if (wifi_sta_reconnect) { + esp_err_t ret = esp_wifi_disconnect(); + if (ret != ESP_OK) { + ESP_LOGW(MODNETTWORK_TAG, "Error disconnecting from AP (%d)", ret); + } + else wifi_sta_reconnect = false; + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect); -//-------------------------------------------- -STATIC mp_obj_t esp_status(mp_obj_t self_in) { +//--------------------------------------------------------------- +STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) { + if (!_check_wifi_started(false)) return mp_const_none; + + if (n_args == 1) { + // no arguments: return None until link status is implemented + return mp_const_none; + } + + // one argument: return status based on query parameter + switch ((uintptr_t)args[1]) { + case (uintptr_t)MP_OBJ_NEW_QSTR(MP_QSTR_stations): { + // return list of connected stations, only if in soft-AP mode + require_if(args[0], WIFI_IF_AP); + wifi_sta_list_t station_list; + ESP_EXCEPTIONS(esp_wifi_ap_get_sta_list(&station_list)); + wifi_sta_info_t *stations = (wifi_sta_info_t*)station_list.sta; + mp_obj_t list = mp_obj_new_list(0, NULL); + for (int i = 0; i < station_list.num; ++i) { + ip4_addr_t addr; + mp_obj_tuple_t *t = mp_obj_new_tuple(3, NULL); + t->items[0] = mp_obj_new_bytes(stations[i].mac, sizeof(stations[i].mac)); + if (dhcp_search_ip_on_mac(stations[i].mac , &addr)) { + t->items[1] = netutils_format_ipv4_addr((uint8_t*)&addr.addr, NETUTILS_BIG); + } + else t->items[1] = mp_const_none; + t->items[2] = MP_OBJ_NEW_SMALL_INT(stations[i].rssi); + mp_obj_list_append(list, t); + } + return list; + } + + default: + mp_raise_ValueError("unknown status param"); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_status_obj, esp_status); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status); -//------------------------------------------ -STATIC mp_obj_t esp_scan(mp_obj_t self_in) { - // check that STA mode is active +//------------------------------------------------------------- +STATIC mp_obj_t esp_scan(size_t n_args, const mp_obj_t *args) { + _check_wifi_started(true); + + // check that STA mode is active wifi_mode_t mode; - ESP_EXCEPTIONS(esp_wifi_get_mode(&mode)); + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error getting WiFi mode")); + } if ((mode & WIFI_MODE_STA) == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "STA must be active")); } mp_obj_t list = mp_obj_new_list(0, NULL); wifi_scan_config_t config = { 0 }; - // XXX how do we scan hidden APs (and if we can scan them, are they really hidden?) + if (n_args > 1) config.show_hidden = mp_obj_is_true(args[1]); + MP_THREAD_GIL_EXIT(); esp_err_t status = esp_wifi_scan_start(&config, 1); MP_THREAD_GIL_ENTER(); + if (status == 0) { uint16_t count = 0; ESP_EXCEPTIONS( esp_wifi_scan_get_ap_num(&count) ); wifi_ap_record_t *wifi_ap_records = calloc(count, sizeof(wifi_ap_record_t)); ESP_EXCEPTIONS( esp_wifi_scan_get_ap_records(&count, wifi_ap_records) ); for (uint16_t i = 0; i < count; i++) { - mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL); + mp_obj_tuple_t *t = mp_obj_new_tuple(7, NULL); uint8_t *x = memchr(wifi_ap_records[i].ssid, 0, sizeof(wifi_ap_records[i].ssid)); int ssid_len = x ? x - wifi_ap_records[i].ssid : sizeof(wifi_ap_records[i].ssid); t->items[0] = mp_obj_new_bytes(wifi_ap_records[i].ssid, ssid_len); @@ -559,51 +820,91 @@ STATIC mp_obj_t esp_scan(mp_obj_t self_in) { t->items[2] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].primary); t->items[3] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].rssi); t->items[4] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].authmode); - t->items[5] = mp_const_false; // XXX hidden? + t->items[5] = mp_obj_new_str(wifi_auth_modes[wifi_ap_records[i].authmode], strlen(wifi_auth_modes[wifi_ap_records[i].authmode])); + t->items[6] = (ssid_len == 0) ? mp_const_true : mp_const_false; mp_obj_list_append(list, MP_OBJ_FROM_PTR(t)); } free(wifi_ap_records); } return list; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_scan_obj, 1, 2, esp_scan); + +//-------------------------------------------------------------------- +STATIC mp_obj_t esp_isconnected(size_t n_args, const mp_obj_t *args) { + if (!_check_wifi_started(false)) return mp_obj_new_bool(false); + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + bool check_clients = true; + if (n_args > 1) check_clients = mp_obj_is_true(args[1]); -//------------------------------------------------- -STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) { - wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->if_id == WIFI_IF_STA) { - //tcpip_adapter_ip_info_t info; - //tcpip_adapter_get_ip_info(WIFI_IF_STA, &info); - //return mp_obj_new_bool(info.ip.addr != 0); - return mp_obj_new_bool(_isConnected); - } else { - wifi_sta_list_t sta; - esp_wifi_ap_get_sta_list(&sta); - return mp_obj_new_bool(sta.num != 0); + return mp_obj_new_bool(((wifi_sta_isconnected) && (wifi_sta_has_ipaddress))); + } + else { + bool res = wifi_ap_isconnected; + if ((res) && (check_clients)) { + wifi_sta_list_t sta; + esp_wifi_ap_get_sta_list(&sta); + res = (sta.num != 0); + } + return mp_obj_new_bool(res); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_isconnected_obj, 1, 2, esp_isconnected); + +//--------------------------- +static bool wifi_is_started() +{ + wifi_mode_t wifi_mode; + esp_err_t ret = esp_wifi_get_mode(&wifi_mode); + if (ret != ESP_OK) return false; + + bool sta_f = ((wifi_sta_isconnected) && (wifi_sta_has_ipaddress)); + bool ap_f = wifi_ap_isconnected; + if (wifi_mode == WIFI_MODE_STA) return sta_f; + else if (wifi_mode == WIFI_MODE_AP) return ap_f; + else if (wifi_mode == WIFI_MODE_APSTA) return (sta_f | ap_f); + return false; +} + +//---------------------------------------------- +STATIC mp_obj_t esp_isactive(mp_obj_t self_in) { + if (wifi_network_state < WIFI_STATE_STARTED) return mp_obj_new_bool(false); + + return mp_obj_new_bool(wifi_is_started()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isactive_obj, esp_isactive); //----------------------------------------------------------------- STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { - wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (wifi_network_state < WIFI_STATE_INIT) { + mp_raise_ValueError("TCT/IP Adapter not initialized"); + } + + wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); tcpip_adapter_ip_info_t info; tcpip_adapter_dns_info_t dns_info; + tcpip_adapter_get_ip_info(self->if_id, &info); tcpip_adapter_get_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info); if (n_args == 1) { - // get + // === Get configuration === mp_obj_t tuple[4] = { netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.netmask, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&info.gw, NETUTILS_BIG), netutils_format_ipv4_addr((uint8_t*)&dns_info.ip, NETUTILS_BIG), }; + // Return tuple: (ip, netmask, gateway, dns_ip) return mp_obj_new_tuple(4, tuple); - } else { - // set + } + else { + // === set configuration parameters from tuple: (ip, netmask, gateway, dns_ip) === mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 4, &items); + + // Static IP netutils_parse_ipv4_addr(items[0], (void*)&info.ip, NETUTILS_BIG); if (mp_obj_is_integer(items[1])) { // allow numeric netmask, i.e.: @@ -616,8 +917,11 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { else { netutils_parse_ipv4_addr(items[1], (void*)&info.netmask, NETUTILS_BIG); } + // net mask netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG); + // gateway netutils_parse_ipv4_addr(items[3], (void*)&dns_info.ip, NETUTILS_BIG); + // To set a static IP we have to disable DHCP first if ((self->if_id == WIFI_IF_STA) || (self->if_id == ESP_IF_ETH)) { esp_err_t e = tcpip_adapter_dhcpc_stop(self->if_id); @@ -637,9 +941,83 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig); +//-------------------------------------------------------------------------------------- +static mp_obj_t get_config_param(uintptr_t arg, wlan_if_obj_t *self, wifi_config_t *cfg) +{ + mp_obj_t val = mp_const_none; + + #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) + mp_obj_tuple_t *t; + switch (arg) { + case QS(MP_QSTR_mac): { + uint8_t mac[6]; + if (esp_wifi_get_mac(self->if_id, mac) != ESP_OK) val = mp_const_false; + else val = mp_obj_new_bytes(mac, sizeof(mac)); + break; + } + case QS(MP_QSTR_essid): + if (self->if_id == WIFI_IF_AP) val = mp_obj_new_str((char*)cfg->ap.ssid, cfg->ap.ssid_len); + break; + case QS(MP_QSTR_hidden): + if (self->if_id == WIFI_IF_AP) val = mp_obj_new_bool(cfg->ap.ssid_hidden); + break; + case QS(MP_QSTR_authmode): + if (self->if_id == WIFI_IF_AP) { + t = mp_obj_new_tuple(2, NULL); + t->items[0] = MP_OBJ_NEW_SMALL_INT(cfg->ap.authmode); + t->items[1] = mp_obj_new_str(wifi_auth_modes[cfg->ap.authmode], strlen(wifi_auth_modes[cfg->ap.authmode])); + val = MP_OBJ_FROM_PTR(t); + } + break; + case QS(MP_QSTR_mode): + t = mp_obj_new_tuple(2, NULL); + t->items[0] = MP_OBJ_NEW_SMALL_INT(self->if_id); + if (self->if_id == WIFI_IF_STA) + t->items[1] = mp_obj_new_str("STA_IF", 6); + else t->items[1] = mp_obj_new_str("AP_IF", 5); + val = MP_OBJ_FROM_PTR(t); + break; + case QS(MP_QSTR_wifimode): + t = mp_obj_new_tuple(2, NULL); + wifi_mode_t mode; + esp_err_t ret = esp_wifi_get_mode(&mode); + if (ret == ESP_OK) { + t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); + if (mode ==WIFI_MODE_STA) t->items[1] = mp_obj_new_str("STA", 3); + else if (mode ==WIFI_MODE_AP) t->items[1] = mp_obj_new_str("AP", 2); + else if (mode ==WIFI_MODE_APSTA) t->items[1] = mp_obj_new_str("APSTA", 5); + else t->items[1] = mp_obj_new_str("Unknown", 7); + } + else { + t->items[0] = MP_OBJ_NEW_SMALL_INT(0); + t->items[1] = mp_obj_new_str("Unknown", 7); + } + val = MP_OBJ_FROM_PTR(t); + break; + case QS(MP_QSTR_channel): + if (self->if_id == WIFI_IF_AP) val = MP_OBJ_NEW_SMALL_INT(cfg->ap.channel); + break; + case QS(MP_QSTR_dhcp_hostname): { + const char *s; + if (tcpip_adapter_get_hostname(self->if_id, &s) != ESP_OK) val = mp_const_false; + else val = mp_obj_new_str(s, strlen(s)); + break; + } + default: + val = mp_obj_new_str("Unknown config param", 20); + } + #undef QS + + return val; +} + +// Set or get wifi configuration parameters //--------------------------------------------------------------------------------- STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - if (n_args != 1 && kwargs->used != 0) { + //_check_wifi_started(true); + if (wifi_network_state < WIFI_STATE_STOPPED) _init_wifi(); + + if (n_args != 1 && kwargs->used != 0) { mp_raise_TypeError("either pos or kw args are allowed"); } @@ -699,8 +1077,13 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value); break; } + case QS(MP_QSTR_dhcp_hostname): { + const char *s = mp_obj_str_get_str(kwargs->table[i].value); + ESP_EXCEPTIONS(tcpip_adapter_set_hostname(self->if_id, s)); + break; + } default: - goto unknown; + mp_raise_ValueError("unknown config param"); } #undef QS @@ -718,50 +1101,49 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs // Get config if (n_args != 2) { - mp_raise_TypeError("can query only one parameter"); + mp_raise_TypeError("only one query argument allowed"); } - int req_if = -1; mp_obj_t val; - - #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) - switch ((uintptr_t)args[1]) { - case QS(MP_QSTR_mac): { - uint8_t mac[6]; - ESP_EXCEPTIONS(esp_wifi_get_mac(self->if_id, mac)); - return mp_obj_new_bytes(mac, sizeof(mac)); - } - case QS(MP_QSTR_essid): - req_if = WIFI_IF_AP; - val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len, false); - break; - case QS(MP_QSTR_hidden): - req_if = WIFI_IF_AP; - val = mp_obj_new_bool(cfg.ap.ssid_hidden); - break; - case QS(MP_QSTR_authmode): - req_if = WIFI_IF_AP; - val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode); - break; - case QS(MP_QSTR_channel): - req_if = WIFI_IF_AP; - val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel); - break; - default: - goto unknown; + #define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x) + bool get_all = ((uintptr_t)args[1] == QS(MP_QSTR_all)); + + if (get_all) { + // Get all config parameters + mp_obj_dict_t *dct = mp_obj_new_dict(0); + + val = get_config_param(QS(MP_QSTR_mac), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("mac", 3), val); + val = get_config_param(QS(MP_QSTR_essid), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("essid", 5), val); + val = get_config_param(QS(MP_QSTR_hidden), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("hidden", 6), val); + val = get_config_param(QS(MP_QSTR_authmode), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("authmode", 8), val); + val = get_config_param(QS(MP_QSTR_mode), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("mode", 4), val); + val = get_config_param(QS(MP_QSTR_wifimode), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("wifimode", 8), val); + val = get_config_param(QS(MP_QSTR_channel), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("channel", 7), val); + val = get_config_param(QS(MP_QSTR_dhcp_hostname), self, &cfg); + if ((val != mp_const_none) && (val != mp_const_false)) mp_obj_dict_store(dct, mp_obj_new_str("dhcp_hostname", 13), val); + + val = dct; } - #undef QS - - // We post-check interface requirements to save on code size - if (req_if >= 0) { - require_if(args[0], req_if); + else { + // Get one config parameter + val = get_config_param((uintptr_t)args[1], self, &cfg); + if (val == mp_const_none) { + mp_raise_msg(&mp_type_OSError, self->if_id == WIFI_IF_STA ? "AP required" : "STA required"); + } + if (val == mp_const_false) { + mp_raise_msg(&mp_type_OSError, "Parameter not available"); + } } + #undef QS return val; - -unknown: - mp_raise_ValueError("unknown config param"); - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config); @@ -806,16 +1188,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_probereq_callback_obj, 1, 2, esp_ //======================================================== STATIC const mp_map_elem_t wlan_if_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_active), (mp_obj_t)&esp_active_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_connect_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&esp_disconnect_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&esp_isconnected_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&esp_config_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&esp_ifconfig_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_eventCB), (mp_obj_t)&esp_callback_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_probereqCB), (mp_obj_t)&esp_probereq_callback_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_active), (mp_obj_t)&esp_active_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_connect_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&esp_disconnect_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&esp_isconnected_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_wifiactive), (mp_obj_t)&esp_isactive_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&esp_config_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&esp_ifconfig_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_eventCB), (mp_obj_t)&esp_callback_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_probereqCB), (mp_obj_t)&esp_probereq_callback_obj }, }; STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); @@ -832,13 +1215,121 @@ STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode); +//--------------------------------- +int network_get_active_interfaces() +{ + int n_if = 0; + + for (int i=0; i 0) { + return ip_info.ip.addr; + } + } + } + return 0; +} + +//-------------------------- +uint32_t network_has_staip() +{ + tcpip_adapter_ip_info_t ip_info = {0}; + int n_if = network_get_active_interfaces(); + if (n_if) { + for (int i=0; i 0)) { + return ip_info.ip.addr; + } + } + } + return 0; +} + +//---------------------------- +void network_checkConnection() +{ + uint32_t ip = network_has_staip(); + if (ip == 0) { + #ifdef CONFIG_MICROPY_USE_GSM + if (ppposStatus(NULL, NULL, NULL) != GSM_STATE_CONNECTED) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "No Internet connection")); + } + #else + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "No Internet connection")); + #endif + } +} + + + #ifdef CONFIG_MICROPY_USE_MQTT extern const mp_obj_type_t mqtt_type; #endif +// ============================== +// ==== FTP & Telnet services === + #if defined(CONFIG_MICROPY_USE_TELNET) || defined(CONFIG_MICROPY_USE_FTPSERVER) #include "mpthreadport.h" + +//----------------------------- +static mp_obj_t get_listen_ip() +{ + tcpip_adapter_ip_info_t info; + int n_if = network_get_active_interfaces(); + + if (n_if > 0) { + mp_obj_t ip_tuple[n_if]; + for (int i=0; i 0 + { MP_QSTR_login_msg, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + #endif }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + if ((wifi_network_state < WIFI_STATE_STARTED) || (!wifi_is_started())) { + #ifdef CONFIG_MICROPY_USE_ETHERNET + if (!lan_eth_active) { + ESP_LOGE("[Telnet_start]", "Network interface not started or not connected"); + return mp_const_false; + } + #else + return mp_const_false; + #endif + } + if (MP_OBJ_IS_STR(args[0].u_obj)) { snprintf(telnet_user, TELNET_USER_PASS_LEN_MAX, mp_obj_str_get_str(args[0].u_obj)); } @@ -867,6 +1372,12 @@ STATIC mp_obj_t mod_network_startTelnet(mp_uint_t n_args, const mp_obj_t *pos_ar } else strcpy(telnet_pass, TELNET_DEF_PASS); + #if TELNET_LOGIN_MSG_LEN_MAX > 0 + if (MP_OBJ_IS_STR(args[3].u_obj)) { + snprintf(telnet_login_success, TELNET_LOGIN_MSG_LEN_MAX, mp_obj_str_get_str(args[3].u_obj)); + } + else snprintf(telnet_login_success, TELNET_LOGIN_MSG_LEN_MAX, "\r\nLogin succeeded!\r\nType \"help()\" for more information.\r\n"); + #endif telnet_timeout = args[2].u_int * 1000; if ((telnet_timeout < 120000) || (telnet_timeout > 86400000)) telnet_timeout = TELNET_DEF_TIMEOUT_MS; @@ -912,7 +1423,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_TelnetMaxStack_obj, mod_network_Tel //-------------------------------------- STATIC mp_obj_t mod_network_stateTelnet() { - mp_obj_t tuple[2]; + mp_obj_t tuple[3]; char state[16] = {'\0'}; int telnet_state = telnet_getstate(); @@ -926,20 +1437,21 @@ STATIC mp_obj_t mod_network_stateTelnet() else sprintf(state, "Unknown"); tuple[0] = mp_obj_new_int(telnet_state); - tuple[1] = mp_obj_new_str(state, strlen(state), false); + tuple[1] = mp_obj_new_str(state, strlen(state)); + tuple[2] = get_listen_ip(); - return mp_obj_new_tuple(2, tuple); + return mp_obj_new_tuple(3, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_stateTelnet_obj, mod_network_stateTelnet); //=============================================================== STATIC const mp_map_elem_t network_telnet_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_network_startTelnet_obj) }, - { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&mod_network_pauseTelnet_obj) }, - { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&mod_network_resumeTelnet_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_network_stopTelnet_obj) }, - { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&mod_network_stateTelnet_obj) }, - { MP_ROM_QSTR(MP_QSTR_stack), MP_ROM_PTR(&mod_network_TelnetMaxStack_obj) } + { MP_ROM_QSTR(MP_QSTR_start), (mp_obj_t)&mod_network_startTelnet_obj }, + { MP_ROM_QSTR(MP_QSTR_pause), (mp_obj_t)&mod_network_pauseTelnet_obj }, + { MP_ROM_QSTR(MP_QSTR_resume), (mp_obj_t)&mod_network_resumeTelnet_obj }, + { MP_ROM_QSTR(MP_QSTR_stop), (mp_obj_t)&mod_network_stopTelnet_obj }, + { MP_ROM_QSTR(MP_QSTR_status), (mp_obj_t)&mod_network_stateTelnet_obj }, + { MP_ROM_QSTR(MP_QSTR_stack), (mp_obj_t)&mod_network_TelnetMaxStack_obj } }; STATIC MP_DEFINE_CONST_DICT(network_telnet_locals_dict, network_telnet_locals_dict_table); @@ -970,11 +1482,15 @@ STATIC mp_obj_t mod_network_startFtp(mp_uint_t n_args, const mp_obj_t *pos_args, mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - wifi_mode_t wifi_mode; - esp_wifi_get_mode(&wifi_mode); - if ((wifi_mode != WIFI_MODE_STA) && (wifi_mode != WIFI_MODE_AP)) { - ESP_LOGE("[Ftp]", "Invalif WiFi mode\n"); - return mp_const_false; + if ((wifi_network_state < WIFI_STATE_STARTED) || (!wifi_is_started())) { + #ifdef CONFIG_MICROPY_USE_ETHERNET + if (!lan_eth_active) { + ESP_LOGE("[Ftp_start]", "Network interface not started or not connected"); + return mp_const_false; + } + #else + return mp_const_false; + #endif } if (MP_OBJ_IS_STR(args[0].u_obj)) { @@ -1035,7 +1551,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_FtpMaxStack_obj, mod_network_FtpMax //------------------------------------ STATIC mp_obj_t mod_network_stateFtp() { - mp_obj_t tuple[4]; + mp_obj_t tuple[5]; char state[20] = {'\0'}; int ftp_state, ftp_substate; @@ -1063,26 +1579,27 @@ STATIC mp_obj_t mod_network_stateFtp() else if (ftp_state == -1) sprintf(state, "Not started"); else if (ftp_state == -2) sprintf(state, "Busy!"); else sprintf(state, "Unknown"); - tuple[2] = mp_obj_new_str(state, strlen(state), false); + tuple[2] = mp_obj_new_str(state, strlen(state)); if (ftp_substate == E_FTP_STE_SUB_DISCONNECTED) sprintf(state, "Data: Disconnected"); else if (ftp_substate == E_FTP_STE_SUB_LISTEN_FOR_DATA) sprintf(state, "Data: Listen"); else if (ftp_substate == E_FTP_STE_SUB_DATA_CONNECTED) sprintf(state, "Data: Connected"); else sprintf(state, "Unknown"); - tuple[3] = mp_obj_new_str(state, strlen(state), false); + tuple[3] = mp_obj_new_str(state, strlen(state)); + tuple[4] = get_listen_ip(); - return mp_obj_new_tuple(4, tuple); + return mp_obj_new_tuple(5, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_network_stateFtp_obj, mod_network_stateFtp); //============================================================ STATIC const mp_map_elem_t network_ftp_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&mod_network_startFtp_obj) }, - { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&mod_network_pauseFtp_obj) }, - { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&mod_network_resumeFtp_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_network_stopFtp_obj) }, - { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&mod_network_stateFtp_obj) }, - { MP_ROM_QSTR(MP_QSTR_stack), MP_ROM_PTR(&mod_network_FtpMaxStack_obj) } + { MP_ROM_QSTR(MP_QSTR_start), (mp_obj_t)&mod_network_startFtp_obj }, + { MP_ROM_QSTR(MP_QSTR_pause), (mp_obj_t)&mod_network_pauseFtp_obj }, + { MP_ROM_QSTR(MP_QSTR_resume), (mp_obj_t)&mod_network_resumeFtp_obj }, + { MP_ROM_QSTR(MP_QSTR_stop), (mp_obj_t)&mod_network_stopFtp_obj }, + { MP_ROM_QSTR(MP_QSTR_status), (mp_obj_t)&mod_network_stateFtp_obj }, + { MP_ROM_QSTR(MP_QSTR_stack), (mp_obj_t)&mod_network_FtpMaxStack_obj } }; STATIC MP_DEFINE_CONST_DICT(network_ftp_locals_dict, network_ftp_locals_dict_table); @@ -1100,27 +1617,47 @@ const mp_obj_type_t network_ftp_type = { extern const mp_obj_type_t mdns_type; #endif +//-------------------------------------------------------------------- +STATIC mp_obj_t esp_wlan_callback(size_t n_args, const mp_obj_t *args) +{ + if (n_args == 0) { + if (event_callback == NULL) return mp_const_false; + return mp_const_true; + } + + if (wifi_mutex) xSemaphoreTake(wifi_mutex, 1000); + if ((MP_OBJ_IS_FUN(args[0])) || (MP_OBJ_IS_METH(args[0]))) { + event_callback = args[0]; + } + else event_callback = NULL; + if (wifi_mutex) xSemaphoreGive(wifi_mutex); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_wlan_callback_obj, 0, 1, esp_wlan_callback); + //============================================================== STATIC const mp_map_elem_t mp_module_network_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) }, { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_initialize_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WLANcallback), (mp_obj_t)&esp_wlan_callback_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj }, #ifdef CONFIG_MICROPY_USE_ETHERNET { MP_OBJ_NEW_QSTR(MP_QSTR_LAN), (mp_obj_t)&get_lan_obj }, #endif #ifdef CONFIG_MICROPY_USE_MQTT - { MP_ROM_QSTR(MP_QSTR_mqtt), MP_ROM_PTR(&mqtt_type) }, + { MP_ROM_QSTR(MP_QSTR_mqtt), (mp_obj_type_t *)&mqtt_type }, #endif #ifdef CONFIG_MICROPY_USE_TELNET - { MP_ROM_QSTR(MP_QSTR_telnet), MP_ROM_PTR(&network_telnet_type) }, + { MP_ROM_QSTR(MP_QSTR_telnet), (mp_obj_type_t *)&network_telnet_type }, #endif #ifdef CONFIG_MICROPY_USE_FTPSERVER - { MP_ROM_QSTR(MP_QSTR_ftp), MP_ROM_PTR(&network_ftp_type) }, + { MP_ROM_QSTR(MP_QSTR_ftp), (mp_obj_type_t *)&network_ftp_type }, #endif #ifdef CONFIG_MICROPY_USE_MDNS - { MP_ROM_QSTR(MP_QSTR_mDNS), MP_ROM_PTR(&mdns_type) }, + { MP_ROM_QSTR(MP_QSTR_mDNS), (mp_obj_type_t *)&mdns_type }, #endif #if MODNETWORK_INCLUDE_CONSTANTS @@ -1136,7 +1673,6 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA_PSK) }, { MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA2_PSK) }, { MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA_WPA2_PSK) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_MAX), MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_MAX) }, #ifdef CONFIG_MICROPY_USE_ETHERNET { MP_OBJ_NEW_QSTR(MP_QSTR_PHY_LAN8720), MP_OBJ_NEW_SMALL_INT(PHY_LAN8720) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modnetwork.h b/MicroPython_BUILD/components/micropython/esp32/modnetwork.h index 028ea1b0..b1108bb3 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modnetwork.h +++ b/MicroPython_BUILD/components/micropython/esp32/modnetwork.h @@ -24,25 +24,51 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H #define MICROPY_INCLUDED_ESP32_MODNETWORK_H +#include "esp_wifi_types.h" +#include "esp_eth.h" +#include "tcpip_adapter.h" + +#define WIFI_STATE_NOTINIT -1 +#define WIFI_STATE_INIT 0 +#define WIFI_STATE_STOPPED 1 +#define WIFI_STATE_STARTED 2 +#define MAX_ACTIVE_INTERFACES 3 + enum { PHY_LAN8720, PHY_TLK110 }; typedef struct _wlan_if_obj_t { mp_obj_base_t base; int if_id; + wifi_mode_t wifi_mode; } wlan_if_obj_t; typedef void (*wifi_sta_rx_probe_req_t)(const uint8_t *frame, int len, int rssi); extern esp_err_t esp_wifi_set_sta_rx_probe_req(wifi_sta_rx_probe_req_t cb); extern const mp_obj_type_t wlan_if_type; +tcpip_adapter_if_t tcpip_if[3]; + +#ifdef CONFIG_MICROPY_USE_ETHERNET +extern bool lan_eth_active; +//extern eth_phy_check_link_func lan_eth_link_func; +#endif +extern int wifi_network_state; extern bool wifi_sta_isconnected; extern bool wifi_sta_has_ipaddress; extern bool wifi_sta_changed_ipaddress; extern bool wifi_ap_isconnected; +extern bool wifi_ap_sta_isconnected; + +int network_get_active_interfaces(); +uint32_t network_hasip(); +uint32_t network_has_staip(); +void network_checkConnection(); + #ifdef CONFIG_MICROPY_USE_ETHERNET MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj); diff --git a/MicroPython_BUILD/components/micropython/esp32/modota.c b/MicroPython_BUILD/components/micropython/esp32/modota.c index 2adc7abf..10a219a6 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modota.c +++ b/MicroPython_BUILD/components/micropython/esp32/modota.c @@ -46,6 +46,7 @@ #include "rom/crc.h" #include "soc/dport_reg.h" #include "esp_log.h" +#include "esp_http_client.h" #include "py/runtime.h" #include "modmachine.h" @@ -56,89 +57,52 @@ #define BUFFSIZE 4096 static const char *TAG = "OTA_UPDATE"; -static int socket_id = -1; +static char *cert_pem = NULL; -//---------------------------------------------------------------------- -static bool connect_to_http_server(const char *server, const char *port) -{ - const struct addrinfo hints = { - .ai_family = AF_INET, - .ai_socktype = SOCK_STREAM, - }; - struct addrinfo *res; - int http_connect_flag = -1; - - int err = getaddrinfo(server, port, &hints, &res); - if(err != 0 || res == NULL) { - ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res); - return false; - } - - socket_id = socket(res->ai_family, res->ai_socktype, 0); - if (socket_id < 0) { - ESP_LOGE(TAG, "Create socket failed!"); - freeaddrinfo(res); - return false; - } - - // connect to http server - http_connect_flag = connect(socket_id, res->ai_addr, res->ai_addrlen); - if (http_connect_flag != 0) { - ESP_LOGE(TAG, "Connect to server failed! errno=%d", errno); - close(socket_id); - socket_id = -1; - return false; - } - else return true; -} +extern void get_certificate(mp_obj_t cert, char *cert_pem_buf); -//-------------------------------------------------------------------------------------- -static int get_header(char *ota_write_data, int *expect_len, int max_size, int min_size) +//---------------------------------------------------------------- +static esp_err_t _http_event_handler(esp_http_client_event_t *evt) { - char text[513] = {'\0'}; - int body_len = 0; - int idx = 0; - int buff_len = recv(socket_id, text, 512, 0); - while (buff_len > 0) { - text[buff_len+idx] = '\0'; - char *hdr_end = strstr(text, "\r\n\r\n"); - if (hdr_end) { - hdr_end[0] = '\0'; - body_len = buff_len+idx - (hdr_end - text) - 4; - char *sc_len_start = strstr(text, "Content-Length: "); - if (sc_len_start) { - char *sc_len_end = strstr(sc_len_start, "\r\n"); - if (sc_len_end) { - *expect_len = strtol(sc_len_start+16, NULL, 0); - if ((*expect_len > 0) && (*expect_len > max_size)) { - ESP_LOGE(TAG, "Image length bigger than partition size: %u > %u\n", *expect_len, max_size); - return 0; - } - } - } - if (body_len) { - memcpy(ota_write_data, hdr_end+4, buff_len); - } - while (body_len < min_size) { - buff_len = recv(socket_id, ota_write_data+body_len, BUFFSIZE-idx, 0); - if (buff_len <= 0) break; - body_len += buff_len; - } - break; - } - idx += buff_len; - if ((512-buff_len) <= 0) break; - buff_len = recv(socket_id, text+idx, 512-buff_len, 0); - } - return body_len; + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP Event: ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP Event: Connected"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP Event: Header sent"); + break; + case HTTP_EVENT_ON_HEADER: + //ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + //ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP Event: Finish"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGD(TAG, "HTTP Event: Disconnected"); + break; + } + return ESP_OK; } -//---------------------------------------------------------------------------------------------------------------------- -static esp_err_t mpy_ota_update(const char *server, const char *port, const char *name, uint8_t md5, uint8_t force_fact) +//----------------------------------------------------------------------------------- +static esp_err_t mpy_ota_update(const char *upd_url, uint8_t md5, uint8_t force_fact) { + if ((CONFIG_LOG_DEFAULT_LEVEL > ESP_LOG_WARN) && (CONFIG_MICRO_PY_LOG_LEVEL > ESP_LOG_WARN)){ + esp_log_level_set("HTTP_CLIENT", ESP_LOG_WARN); + esp_log_level_set("esp_image", ESP_LOG_WARN); + esp_log_level_set("TRANSPORT", ESP_LOG_WARN); + esp_log_level_set("TRANS_SSL", ESP_LOG_WARN); + } mp_hal_set_wdt_tmo(); - char http_request[128] = {0}; + static esp_http_client_config_t http_client_config; + memset(&http_client_config, 0, sizeof(esp_http_client_config_t)); char remote_md5[33] = {0}; char local_md5[33] = {0}; char *ota_write_data = NULL; // ota data write buffer @@ -184,85 +148,96 @@ static esp_err_t mpy_ota_update(const char *server, const char *port, const char } mp_hal_reset_wdt(); - int body_len = 0; int expect_len = 0; - if (md5) { - // === Connect to http server to get the image MD5 file === - sprintf(http_request, "GET %s.md5 HTTP/1.1\r\nHost: %s:%s \r\n\r\n", name, server, port); - - if (connect_to_http_server(server, port)) { - ESP_LOGI(TAG, "Connected to http server, requesting '%s.md5'", name); - } else { - ESP_LOGE(TAG, "Connect to http server failed!"); - goto exit; - } - - int res = -1; - // Send GET request to http server - res = send(socket_id, http_request, strlen(http_request), 0); - if (res == -1) { - ESP_LOGE(TAG, "Requesting MD5 file failed"); - goto exit; - } - else { - // === wait for body start === - memset(ota_write_data, 0, BUFFSIZE+1); - body_len = get_header(ota_write_data, &expect_len, 128, 32); - - if (body_len >= 32) strncpy(remote_md5, ota_write_data, 32); - } - if (socket_id >= 0) { - close(socket_id); - socket_id = -1; - } - if (strlen(remote_md5) == 32) { - ESP_LOGI(TAG, "Received remote MD5"); - } - else { - ESP_LOGE(TAG, "Remote MD5 requested but not received"); - goto exit; - } + int data_read = 0; + esp_http_client_handle_t client = NULL; + + if (md5) { + // === Get the image MD5 file from server === + char http_request[strlen(upd_url)+8]; + strcpy(http_request, upd_url); + strcat(http_request, ".md5"); + http_client_config.url = http_request; + http_client_config.cert_pem = cert_pem; + http_client_config.event_handler = _http_event_handler; + //http_client_config.buffer_size = BUFFSIZE; + + client = esp_http_client_init(&http_client_config); + if (client == NULL) { + ESP_LOGE(TAG, "Failed to initialise HTTP connection"); + goto exit; + } + err = esp_http_client_open(client, 0); + if (err != ESP_OK) { + esp_http_client_cleanup(client); + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + goto exit_client; + } + + if (esp_http_client_fetch_headers(client) == ESP_FAIL) { + ESP_LOGE(TAG, "Error fetching headers"); + goto exit_client; + } + + data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE); + if (data_read >= 32) strncpy(remote_md5, ota_write_data, 32); + else { + ESP_LOGE(TAG, "Remote MD5 requested but not received"); + goto exit_client; + } + esp_http_client_close(client); + esp_http_client_cleanup(client); + client = NULL; } // === Connect to http server to get the image file === - sprintf(http_request, "GET %s HTTP/1.1\r\nHost: %s:%s \r\n\r\n", name, server, port); - if (connect_to_http_server(server, port)) { - ESP_LOGI(TAG, "Connected to http server, requesting '%s'", name); - } else { - ESP_LOGE(TAG, "Connect to http server failed!"); + http_client_config.url = upd_url; + http_client_config.cert_pem = cert_pem; + http_client_config.event_handler = _http_event_handler; + //http_client_config.buffer_size = BUFFSIZE; + + if (client == NULL) client = esp_http_client_init(&http_client_config); + if (client == NULL) { + ESP_LOGE(TAG, "Failed to initialise HTTP connection"); goto exit; } - mp_hal_reset_wdt(); - int res = -1; - // Send GET request to http server - res = send(socket_id, http_request, strlen(http_request), 0); - if (res == -1) { - ESP_LOGE(TAG, "Send GET request to server failed"); - goto exit; - } else { - ESP_LOGI(TAG, "Send GET request to server succeeded"); + err = esp_http_client_open(client, 0); + if (err != ESP_OK) { + esp_http_client_cleanup(client); + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + goto exit_client; + } + err = esp_http_client_fetch_headers(client); + if (err == ESP_FAIL) { + ESP_LOGE(TAG, "Error fetching headers"); + goto exit_client; } - // === wait for body start === - memset(ota_write_data, 0, BUFFSIZE+1); + mp_hal_reset_wdt(); - expect_len = 0; - body_len = get_header(ota_write_data, &expect_len, update_partition->size, 1); + expect_len = esp_http_client_get_content_length(client); + if (expect_len > 0) { + ESP_LOGI(TAG, "Update image size: %d bytes", expect_len); + } + else { + ESP_LOGW(TAG, "Cannot determine image size"); + } - if (body_len <= 0) { - ESP_LOGE(TAG, "Error: No body received!"); - goto exit; + data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE); + if (data_read <= 0) { + vTaskDelay(5); + data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE); + } + if (data_read <= 0) { + ESP_LOGE(TAG, "Error reading from server (%d)", data_read); + goto exit_client; } // We have some data received, check for image magic byte if (ota_write_data[0] != 0xE9) { - ESP_LOGE(TAG, "Error: OTA image has invalid magic byte!"); - goto exit; - } - - if (expect_len > 0) { - ESP_LOGI(TAG, "Update image size: %d bytes", expect_len); + ESP_LOGE(TAG, "Error: OTA image has invalid magic byte (%02X <> E9)", ota_write_data[0]); + goto exit_client; } // Start writing data @@ -274,28 +249,30 @@ static esp_err_t mpy_ota_update(const char *server, const char *port, const char mbedtls_md5_starts( &ctx ); int binary_file_length = 0; // image total length - while (body_len > 0) { + while (data_read > 0) { mp_hal_reset_wdt(); - err = esp_ota_write( update_handle, (const void *)ota_write_data, body_len); - mbedtls_md5_update( &ctx, (const unsigned char *)ota_write_data, body_len); + err = esp_ota_write( update_handle, (const void *)ota_write_data, data_read); + mbedtls_md5_update( &ctx, (const unsigned char *)ota_write_data, data_read); if (err != ESP_OK) { mp_hal_stdout_tx_newline(); ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err); - goto exit; + goto exit_client; } - binary_file_length += body_len; + binary_file_length += data_read; mp_printf(&mp_plat_print, "%s Received %d bytes\r", TAG, binary_file_length); - body_len = recv(socket_id, ota_write_data, BUFFSIZE, 0); - if ((expect_len > 0) && ((binary_file_length + body_len) > expect_len)) { - ESP_LOGE(TAG, "More than expected bytes received %u > %u\n", binary_file_length+body_len, expect_len); - goto exit; + + data_read = esp_http_client_read(client, ota_write_data, BUFFSIZE); + if ((expect_len > 0) && ((binary_file_length + data_read) > expect_len)) { + ESP_LOGE(TAG, "More than expected bytes received %u > %u\n", binary_file_length+data_read, expect_len); + goto exit_client; } - if ((binary_file_length + body_len) > update_partition->size) { - ESP_LOGE(TAG, "Received more bytes than the partition size: %u > %u\n", binary_file_length+body_len, update_partition->size); - goto exit; + if ((binary_file_length + data_read) > update_partition->size) { + ESP_LOGE(TAG, "Received more bytes than the partition size: %u > %u\n", binary_file_length+data_read, update_partition->size); + goto exit_client; } } - mbedtls_md5_finish( &ctx, md5_byte_array ); + + mbedtls_md5_finish( &ctx, md5_byte_array ); mbedtls_md5_free( &ctx ); for (int i = 0; i<16; i++){ sprintf(local_md5+(i*2),"%02x", md5_byte_array[i]); @@ -306,7 +283,7 @@ static esp_err_t mpy_ota_update(const char *server, const char *port, const char ESP_LOGI(TAG, "Image written, total length = %d bytes\n", binary_file_length); if ((expect_len > 0) && (expect_len != binary_file_length)) { ESP_LOGE(TAG, "Expected image length not equal to received length: %u <> %u\n", expect_len, binary_file_length); - goto exit; + goto exit_client; } if (md5) { if (strlen(remote_md5) == 32) { @@ -315,7 +292,7 @@ static esp_err_t mpy_ota_update(const char *server, const char *port, const char } else { ESP_LOGE(TAG, "MD5 Checksum check FAILED!"); - goto exit; + goto exit_client; } } } @@ -323,23 +300,24 @@ static esp_err_t mpy_ota_update(const char *server, const char *port, const char err = esp_ota_end(update_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "OTA end failed! err=0x%x", err); - goto exit; + goto exit_client; } mp_hal_reset_wdt(); // === Set boot partition === err = esp_ota_set_boot_partition(update_partition); if (err != ESP_OK) { ESP_LOGE(TAG, "OTA set_boot_partition failed! err=0x%x", err); - goto exit; + goto exit_client; } ESP_LOGW(TAG, "On next reboot the system will be started from '%s' partition", update_partition->label); errexit = ESP_OK; + goto exit; + +exit_client: + esp_http_client_close(client); + esp_http_client_cleanup(client); exit: - if (socket_id >= 0) { - close(socket_id); - socket_id = -1; - } if (ota_write_data) free(ota_write_data); return errexit; @@ -348,6 +326,9 @@ static esp_err_t mpy_ota_update(const char *server, const char *port, const char //------------------------------------------------------------------------ static esp_err_t mpy_ota_fileupdate(const char *fname, uint8_t force_fact) { + if ((CONFIG_LOG_DEFAULT_LEVEL > ESP_LOG_WARN) && (CONFIG_MICRO_PY_LOG_LEVEL > ESP_LOG_WARN)){ + esp_log_level_set("esp_image", ESP_LOG_WARN); + } mp_hal_set_wdt_tmo(); char *ota_write_data = NULL; // ota data write buffer @@ -532,36 +513,28 @@ static esp_err_t mpy_ota_fileupdate(const char *fname, uint8_t force_fact) //------------------------------------------------------------------------------------------ STATIC mp_obj_t mod_ota_start(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_server, ARG_port, ARG_name, ARG_restart, ARG_md5, ARG_forceFact }; + enum { ARG_url, ARG_restart, ARG_md5, ARG_forceFact, ARG_cert }; const mp_arg_t allowed_args[] = { - { MP_QSTR_server, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_port, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 80} }, - { MP_QSTR_file, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_md5, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_forceFactory, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_md5, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_forceFactory, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_certificate, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - char sport[16] = {'\0'}; - int nport = args[ARG_port].u_int; - const char *server = mp_obj_str_get_str(args[ARG_server].u_obj); - const char *name = NULL; - - if (MP_OBJ_IS_STR(args[ARG_name].u_obj)) { - name = mp_obj_str_get_str(args[ARG_name].u_obj); - } - else name = "/MicroPython.bin"; + const char *url = mp_obj_str_get_str(args[ARG_url].u_obj); - char fname[strlen(name)+2]; + if (cert_pem) free(cert_pem); + cert_pem = NULL; - if (name[0] != '/') sprintf(fname, "/%s", name); - else sprintf(fname, "%s", name); + get_certificate(args[ARG_cert].u_obj, cert_pem); - sprintf(sport, "%d", nport); + esp_err_t res = mpy_ota_update(url, args[ARG_md5].u_bool, args[ARG_forceFact].u_bool); - esp_err_t res = mpy_ota_update(server, sport, fname, args[ARG_md5].u_bool, args[ARG_forceFact].u_bool); + if (cert_pem) free(cert_pem); + cert_pem = NULL; if (res != ESP_OK) return mp_const_false; diff --git a/MicroPython_BUILD/components/micropython/esp32/modrequests.c b/MicroPython_BUILD/components/micropython/esp32/modrequests.c new file mode 100644 index 00000000..b9e4e09c --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modrequests.c @@ -0,0 +1,1048 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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 "sdkconfig.h" + +#ifdef CONFIG_MICROPY_USE_REQUESTS + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_system.h" +#include "nvs_flash.h" +#include "mbedtls/base64.h" + +#include "esp_http_client.h" +#include "transport.h" +#include "esp_wifi_types.h" +#include "tcpip_adapter.h" + +#include "py/obj.h" +#include "py/runtime.h" +#include "modmachine.h" +#include "extmod/vfs_native.h" +#include "modnetwork.h" + +#define MAX_HTTP_RECV_BUFFER 512 +static const char *TAG = "[REQUESTS]"; + +static char *rqheader = NULL; +static char *rqbody = NULL; +static FILE* rqbody_file = NULL; +static int rqheader_len = 0; +static int rqheader_ptr = 0; +static int rqbody_len = 0; +static int rqbody_ptr = 0; +static bool rqbody_ok = true; +static bool rq_debug = false; +static bool rq_base64 = false; +static char *cert_pem = NULL; + + +/* + * You can get the Root cert for the server using openssl + + The PEM file can be extracted from the output of this command: + openssl s_client -showcerts -connect :443 + + The CA root cert is the last cert given in the chain of certs. +*/ + +//---------------------------------------------------------------- +static esp_err_t _http_event_handler(esp_http_client_event_t *evt) +{ + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + if (rq_debug) ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + if (rq_debug) ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + if (rq_debug) { + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + ESP_LOGD(TAG, " KEY: [%s]", evt->header_key); + ESP_LOGD(TAG, "VALUE: [%s]", evt->header_value); + } + break; + case HTTP_EVENT_ON_HEADER: + if (rq_debug) ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + if (rqheader == NULL) { + rqheader = malloc(256); + if (rqheader) { + rqheader_len = 256; + rqheader_ptr = 0; + rqheader[0] = '\0'; + } + } + if (rqheader) { + bool f = true; + int len = strlen(evt->header_key) + strlen(evt->header_value) + rqheader_ptr + 5; + if (len > rqheader_len) { + char *tmphdr = realloc(rqheader, len + 128); + if (tmphdr) { + rqheader = tmphdr; + rqheader_len = len + 128; + } + else f = false; + } + if (f) { + strcat(rqheader, evt->header_key); + strcat(rqheader, ": "); + strcat(rqheader, evt->header_value); + strcat(rqheader, "\r\n"); + rqheader_ptr = strlen(rqheader); + } + } + break; + case HTTP_EVENT_ON_DATA: + if (rq_debug) ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d, rqptr=%d [%d]", evt->data_len, rqbody_ptr, rqbody_len); + if (rqbody_ok) { + if (rqbody_file) { + int nwrite = fwrite(evt->data, 1, evt->data_len, rqbody_file); + if (nwrite <= 0) { + rqbody_ok = false; + ESP_LOGE(TAG, "Download: Error writing to file %d", nwrite); + } + } + else { + if (rqbody == NULL) { + rqbody = malloc(4096); + if (rqbody) { + rqbody_len = 4096; + rqbody_ptr = 0; + } + } + if (rqbody) { + int len = evt->data_len + rqbody_ptr; + if (len > rqbody_len) { + char *tmpbody = realloc(rqbody, len + 512); + if (tmpbody) { + rqbody = tmpbody; + rqbody_len = len + 512; + } + else { + rqbody_ok = false; + ESP_LOGE(TAG, "Error reallocating body buffer"); + } + } + + if (rqbody_ok) { + memcpy(rqbody + rqbody_ptr, evt->data, evt->data_len); + rqbody_ptr += evt->data_len; + } + } + } + } + break; + case HTTP_EVENT_ON_FINISH: + if (rq_debug) ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + if (rq_debug) ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); + break; + } + return ESP_OK; +} + +/* +//--------------------------- +static void http_auth_basic() +{ + esp_http_client_config_t config = { + .url = "http://user:passwd@httpbin.org/basic-auth/user/passwd", + .event_handler = _http_event_handler, + .auth_type = HTTP_AUTH_TYPE_BASIC, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Basic Auth Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +//------------------------------------ +static void http_auth_basic_redirect() +{ + esp_http_client_config_t config = { + .url = "http://user:passwd@httpbin.org/basic-auth/user/passwd", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Basic Auth redirect Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +//---------------------------- +static void http_auth_digest() +{ + esp_http_client_config_t config = { + .url = "http://user:passwd@httpbin.org/digest-auth/auth/user/passwd/MD5/never", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Digest Auth Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +//----------------- +static void https() +{ + esp_http_client_config_t config = { + .url = "https://www.howsmyssl.com", + .event_handler = _http_event_handler, + //.cert_pem = howsmyssl_com_root_cert_pem_start, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTPS Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_relative_redirect() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/relative-redirect/3", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Relative path redirect Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_absolute_redirect() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/absolute-redirect/3", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Absolute path redirect Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_redirect_to_https() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/redirect-to?url=https%3A%2F%2Fwww.howsmyssl.com", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP redirect to HTTPS Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + + +static void http_download_chunk() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/stream-bytes/8912", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP chunk encoding Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_perform_as_stream_reader() +{ + char *buffer = malloc(MAX_HTTP_RECV_BUFFER); + if (buffer == NULL) { + ESP_LOGE(TAG, "Cannot malloc http receive buffer"); + return; + } + esp_http_client_config_t config = { + .url = "http://httpbin.org/get", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err; + if ((err = esp_http_client_open(client, 0)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + free(buffer); + return; + } + int content_length = esp_http_client_fetch_headers(client); + int total_read_len = 0, read_len; + if (total_read_len < content_length && content_length <= MAX_HTTP_RECV_BUFFER) { + read_len = esp_http_client_read(client, buffer, content_length); + if (read_len <= 0) { + ESP_LOGE(TAG, "Error read data"); + } + buffer[read_len] = 0; + ESP_LOGD(TAG, "read_len = %d", read_len); + } + ESP_LOGI(TAG, "HTTP Stream reader Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + esp_http_client_close(client); + esp_http_client_cleanup(client); + free(buffer); +} +*/ + +//----------------------------------------------- +static char *url_post_fields(mp_obj_dict_t *dict) +{ + char *params = calloc(256, sizeof(char)); + if (params == NULL) return 0; + + int nparam = 0; + const char *key; + const char *value; + char sval[64]; + size_t max = dict->map.alloc; + mp_map_t *map = &dict->map; + mp_map_elem_t *next; + size_t cur = 0; + while (1) { + next = NULL; + for (size_t i = cur; i < max; i++) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + cur = i + 1; + next = &(map->table[i]); + break; + } + } + if (next == NULL) break; + + value = NULL; + key = mp_obj_str_get_str(next->key); + if (MP_OBJ_IS_STR(next->value)) { + value = mp_obj_str_get_str(next->value); + for (int i=0; i 0x7F)) { + value = NULL; + break; + } + } + } + else if (MP_OBJ_IS_INT(next->value)) { + int ival = mp_obj_get_int(next->value); + sprintf(sval,"%d", ival); + value = sval; + } + else if (MP_OBJ_IS_TYPE(next->value, &mp_type_float)) { + double fval = mp_obj_get_float(next->value); + sprintf(sval,"%f", fval); + value = sval; + } + if ((value) && ((strlen(params) + strlen(key) + strlen(value) + 2) < 256)) { + if (strlen(params) > 0) strcat(params, "&"); + strcat(params, key); + strcat(params, "="); + strcat(params, value); + nparam++; + } + } + if (nparam == 0) { + free(params); + params = NULL; + } + return params; +} + +//------------------------------------------------------------------------------------------------------------------------------- +static int post_field(esp_http_client_handle_t client, char *bndry, char *key, char *cont_type, char *value, int vlen, bool send) +{ + int len = vlen; + int res; + char buff[256]; + sprintf(buff, "--%s\r\nContent-Disposition: form-data; name=%s\r\n%s\r\n\r\n", bndry, key, cont_type); + len += strlen(buff); + if (send) { + res = esp_http_client_write(client, buff, strlen(buff)); + if (rq_debug) printf("%s", buff); + if (res <= 0) return res; + res = esp_http_client_write(client, value, vlen); + if (rq_debug) printf("%s", value); + if (res <= 0) return res; + } + + sprintf(buff, "\r\n--%s\r\n\r\n", bndry); + len += strlen(buff); + if (send) { + res = esp_http_client_write(client, buff, strlen(buff)); + if (rq_debug) printf("%s", buff); + if (res <= 0) return res; + } + return len; +} + +//----------------------------------------------------------------------------------------------------- +static int handle_file(esp_http_client_handle_t client, char *bndry, char *key, char *fname, bool send) +{ + int flen = 0; + if (strlen(fname) < 128) { + FILE* file = NULL; + char fullname[128] = {'\0'}; + int res = physicalPath(fname, fullname); + if ((res == 0) && (strlen(fullname) > 0)) { + file = fopen(fullname, "rb"); + if (file == NULL) return flen; + + char *buff = malloc(1024); + if (buff == NULL) return flen; + + if (key) { + sprintf(buff, "--%s\r\nContent-Disposition: form-data; name=\"file_%s\"; filename=\"%s\"\r\nContent-Type: application/octet-stream\r\n\r\n", bndry, key, fname); + flen += strlen(buff); + if (send) { + res = esp_http_client_write(client, buff, strlen(buff)); + if (rq_debug) printf("%s", buff); + if (res <= 0) { + free(buff); + return -1; + } + } + } + res = 1; + while (res > 0) { + res = fread(buff, 1, 1023, file); + if (send) { + if (res > 0) buff[res] = 0; + if ((rq_debug) && (res > 0)) printf("%s", buff); + res = esp_http_client_write(client, buff, res); + } + flen += res; + } + fclose(file); + if (key) { + sprintf(buff, "\r\n--%s\r\n\r\n", bndry); + flen += strlen(buff); + if (send) { + res = esp_http_client_write(client, buff, strlen(buff)); + if (rq_debug) printf("%s", buff); + if (res <= 0) { + free(buff); + return -1; + } + } + } + free(buff); + } + } + return flen; +} + +// Parse MicroPython dictionary, calculate the content length +// or send the body to the server +//------------------------------------------------------------------------------------------------------------ +static int multipart_post_fields(mp_obj_dict_t *dict, char *bndry, esp_http_client_handle_t client, bool send) +{ + int data_len = 0; + int res; + int nparam = 0; + char *key; + char *value; + int vlen; + bool value_free; + char sval[64]; + char cont_type[64]; + + sprintf(cont_type, "%s", "Content-Type: text/plain"); + + // Parse dictionary + size_t max = dict->map.alloc; + mp_map_t *map = &dict->map; + mp_map_elem_t *next; + size_t cur = 0; + if ((rq_debug) && (send)) printf(">>> SEND FIELDS [\n"); + while (1) { + next = NULL; + for (size_t i = cur; i < max; i++) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + cur = i + 1; + next = &(map->table[i]); + break; + } + } + if (next == NULL) break; + + value = NULL; + value_free = false; + key = (char *)mp_obj_str_get_str(next->key); + + if (MP_OBJ_IS_STR(next->value)) { + // String, it can be string to send or file name + value = (char *)mp_obj_str_get_str(next->value); + vlen = strlen(value); + res = handle_file(client, bndry, key, value, send); + if (res == 0) { + for (int i=0; i 0x7F)) { + value = NULL; + break; + } + } + } + else { + data_len += res; + nparam++; + value = NULL; + } + } + else if (MP_OBJ_IS_INT(next->value)) { + int ival = mp_obj_get_int(next->value); + sprintf(sval,"%d", ival); + value = sval; + vlen = strlen(sval); + } + else if (MP_OBJ_IS_TYPE(next->value, &mp_type_float)) { + double fval = mp_obj_get_float(next->value); + sprintf(sval,"%f", fval); + value = sval; + vlen = strlen(sval); + } + else { + mp_obj_type_t *type = mp_obj_get_type(next->value); + mp_buffer_info_t value_buff; + if (type->buffer_p.get_buffer != NULL) { + int ret = type->buffer_p.get_buffer(next->value, &value_buff, MP_BUFFER_READ); + if ((ret == 0) && (value_buff.len > 0)) { + if (rq_base64) { + // Send base64 encoded + value = malloc(value_buff.len * 4 / 3 + 64); + if (value) { + ret = mbedtls_base64_encode((unsigned char *)value, value_buff.len * 4 / 3 + 64, (size_t *)&vlen, (const unsigned char *)value_buff.buf, value_buff.len); + if (ret == 0) { + value[vlen] = '\0'; + sprintf(cont_type, "%s", "Content-Type: binary\r\nContent-Encoding: base64"); + value_free = true; + } + else { + free((void *)value); + value = NULL; + } + } + } + else { + value = value_buff.buf; + vlen = value_buff.len; + } + } + } + } + if (value) { + res = post_field(client, bndry, key, cont_type, value, vlen, send); + if (value_free) free((void *)value); + if (res <= 0) return res; + data_len += res; + nparam++; + } + } + if (rq_debug) { + if (send) { + printf("] LENGTH=%d\n", data_len); + } + else printf(">>> CONTENT LENGTH = %d\n", data_len); + } + return data_len; +} + +//-------------------------------------------------------------------------------------------------- +static mp_obj_t request(int method, bool multipart, mp_obj_t post_data_in, char * url, char *tofile) +{ + int status; + char fullname[128] = {'\0'}; + char err_msg[128] = {'\0'}; + esp_err_t err; + bool perform_handled = false; + bool free_post_data = false; + + // Disable logging + if (!rq_debug) { + esp_log_level_set("HTTP_CLIENT", ESP_LOG_WARN); + esp_log_level_set("TRANSPORT", ESP_LOG_WARN); + esp_log_level_set("TRANS_SSL", ESP_LOG_WARN); + } + + // Check if the response is redirected to file + rqbody_file = NULL; + if (tofile) { + // GET to file + int res = physicalPath(tofile, fullname); + if ((res != 0) || (strlen(fullname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + rqbody_file = fopen(fullname, "wb"); + if (rqbody_file == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error opening file")); + } + } + + char* post_data = NULL; + char bndry[32]; + + esp_http_client_config_t config = {0}; + config.url = url; + config.event_handler = _http_event_handler; + config.buffer_size = 1024; + + // Initialize the http_client and set the method + esp_http_client_handle_t client = esp_http_client_init(&config); + if (client == NULL) { + if (rqbody_file) fclose(rqbody_file); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error initializing http client")); + } + esp_http_client_set_method(client, method); + + if (rqheader) free(rqheader); + if (rqbody) free(rqbody); + rqheader = NULL; + rqheader_len = 0; + rqbody = NULL; + rqbody_len = 0; + rqbody_ptr = 0; + rqbody_ok = true; + + if (method == HTTP_METHOD_POST) { + mp_obj_dict_t *dict; + if (!multipart) { + if (MP_OBJ_IS_TYPE(post_data_in, &mp_type_dict)) { + dict = MP_OBJ_TO_PTR(post_data_in); + post_data = url_post_fields(dict); + err = esp_http_client_set_post_field(client, post_data, strlen(post_data)); + if (err != ESP_OK) { + if (rqbody_file) fclose(rqbody_file); + free(post_data); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error setting post fields")); + } + free_post_data = true; + } + else if (MP_OBJ_IS_STR(post_data_in)) { + post_data = (char *)mp_obj_str_get_str(post_data_in); + err = esp_http_client_set_post_field(client, post_data, strlen(post_data)); + if (err != ESP_OK) { + if (rqbody_file) fclose(rqbody_file); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error setting post fields")); + } + } + else { + if (rqbody_file) fclose(rqbody_file); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Expected Dict or String type argument")); + } + } + else { + // === multipart POST === + if (MP_OBJ_IS_TYPE(post_data_in, &mp_type_dict)) { + dict = MP_OBJ_TO_PTR(post_data_in); + } + else { + if (rqbody_file) fclose(rqbody_file); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Expected Dict type argument")); + } + + // Prepare multipart boundary + memset(bndry,0x00,20); + int randn = rand(); + sprintf(bndry, "_____%d_____", randn); + // Get body length + int cont_len = multipart_post_fields(dict, bndry, client, false); + if (cont_len <= 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Nothing to send")); + } + char temp_buf[128]; + sprintf(temp_buf, "multipart/form-data; boundary=%s", bndry); + esp_http_client_set_header(client, "Content-Type", temp_buf); + + // Perform actions + MP_THREAD_GIL_EXIT(); + err = ESP_OK; + do { + if ((err = esp_http_client_open(client, cont_len)) != ESP_OK) { + sprintf(err_msg, "Http client error: open"); + break; + } + + // Send content + cont_len = multipart_post_fields(dict, bndry, client, true); + + // Check response + if ((esp_http_client_perform_response(client)) != ESP_OK) { + sprintf(err_msg, "Http client error: response"); + break; + } + } while (esp_http_client_process_again(client)); + esp_http_client_cleanup(client); + MP_THREAD_GIL_ENTER(); + perform_handled = true; + } + } + else if ((method == HTTP_METHOD_PUT) || (method == HTTP_METHOD_PATCH)) { + // String, it can be string to send or file name + if (MP_OBJ_IS_STR(post_data_in)) { + post_data = (char *)mp_obj_str_get_str(post_data_in); + int cont_len = handle_file(client, NULL, NULL, post_data, false); + if (cont_len > 0) { + // Perform actions + MP_THREAD_GIL_EXIT(); + err = ESP_OK; + do { + if ((err = esp_http_client_open(client, cont_len)) != ESP_OK) { + sprintf(err_msg, "Http client error: open"); + break; + } + + // Send content + cont_len = handle_file(client, NULL, NULL, post_data, true); + + // Check response + if ((esp_http_client_perform_response(client)) != ESP_OK) { + sprintf(err_msg, "Http client error: response"); + break; + } + } while (esp_http_client_process_again(client)); + esp_http_client_cleanup(client); + MP_THREAD_GIL_ENTER(); + perform_handled = true; + } + else { + err = esp_http_client_set_post_field(client, post_data, strlen(post_data)); + if (err != ESP_OK) { + if (rqbody_file) fclose(rqbody_file); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error setting post fields")); + } + } + } + else { + if (rqbody_file) fclose(rqbody_file); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Expected String type argument")); + } + } + + if (!perform_handled) { + MP_THREAD_GIL_EXIT(); + err = esp_http_client_perform(client); + esp_http_client_cleanup(client); + if ((free_post_data) && (post_data)) free(post_data); + MP_THREAD_GIL_ENTER(); + } + + if (err != ESP_OK) { + if (rqbody_file) fclose(rqbody_file); + if (rqheader) free(rqheader); + if (rqbody) free(rqbody); + rqbody_file = NULL; + rqheader = NULL; + rqbody = NULL; + ESP_LOGE(TAG, "HTTP Request failed: %s [%s]", esp_err_to_name(err), err_msg); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "HTTP Request failed")); + } + + status = esp_http_client_get_status_code(client); + + mp_obj_t tuple[3]; + + tuple[0] = mp_obj_new_int(status); + if ((rqheader) && (rqheader_ptr)) tuple[1] = mp_obj_new_str(rqheader, rqheader_ptr); + else tuple[1] = mp_const_none; + + if (rqbody_file) tuple[2] = mp_obj_new_str(tofile, strlen(tofile)); + else if ((rqbody) && (rqbody_ptr)) tuple[2] = mp_obj_new_str(rqbody, rqbody_ptr); + else tuple[2] = mp_const_none; + + if (rqbody_file) fclose(rqbody_file); + if (rqheader) free(rqheader); + if (rqbody) free(rqbody); + rqbody_file = NULL; + rqheader = NULL; + rqbody = NULL; + + return mp_obj_new_tuple(3, tuple); +} + +//----------------------------------------------------- +void get_certificate(mp_obj_t cert, char *cert_pem_buf) +{ + if (MP_OBJ_IS_STR(cert)) { + struct stat sb; + char *fname = NULL; + char certname[128] = {'\0'}; + + fname = (char *)mp_obj_str_get_str(cert); + esp_err_t res = physicalPath(fname, certname); + if ((res != 0) || (strlen(certname) == 0)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error resolving file name")); + } + if (stat(certname, &sb) != 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error opening certificate file")); + } + FILE *fhndl = fopen(certname, "rb"); + if (!fhndl) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error opening certificate file")); + } + + if (cert_pem_buf) free(cert_pem_buf); + cert_pem_buf = NULL; + cert_pem_buf = calloc(sizeof(char), sb.st_size+16); + if (cert_pem_buf == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating certificate buffer")); + } + int rd_len = fread(cert_pem_buf, 1, sb.st_size, fhndl); + fclose(fhndl); + if (rd_len != sb.st_size) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error reading from certificate file")); + } + } + else if (cert == mp_const_false) { + if (cert_pem_buf) free(cert_pem_buf); + cert_pem_buf = NULL; + } +} + +//-------------------------------------------------------------------------------------- +STATIC mp_obj_t requests_GET(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + network_checkConnection(); + enum { ARG_url, ARG_file }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_file, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *url = NULL; + char *fname = NULL; + + url = (char *)mp_obj_str_get_str(args[ARG_url].u_obj); + + if (MP_OBJ_IS_STR(args[ARG_file].u_obj)) { + // GET to file + fname = (char *)mp_obj_str_get_str(args[ARG_file].u_obj); + } + + mp_obj_t res = request(HTTP_METHOD_GET, false, NULL, url, fname); + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(requests_GET_obj, 1, requests_GET); + +//-------------------------------------------------------------------------------------- +STATIC mp_obj_t requests_HEAD(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + network_checkConnection(); + enum { ARG_url }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *url = NULL; + + url = (char *)mp_obj_str_get_str(args[ARG_url].u_obj); + + mp_obj_t res = request(HTTP_METHOD_HEAD, false, NULL, url, NULL); + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(requests_HEAD_obj, 1, requests_HEAD); + +//--------------------------------------------------------------------------------------- +STATIC mp_obj_t requests_POST(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + network_checkConnection(); + enum { ARG_url, ARG_params, ARG_file, ARG_multipart }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_file, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_multipart, MP_ARG_BOOL, { .u_bool = false } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *url = NULL; + char *fname = NULL; + + url = (char *)mp_obj_str_get_str(args[ARG_url].u_obj); + + if (MP_OBJ_IS_STR(args[ARG_file].u_obj)) { + // GET to file + fname = (char *)mp_obj_str_get_str(args[ARG_file].u_obj); + } + + mp_obj_t res = request(HTTP_METHOD_POST, args[ARG_multipart].u_bool, args[ARG_params].u_obj, url, fname); + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(requests_POST_obj, 1, requests_POST); + +//-------------------------------------------------------------------------------------- +STATIC mp_obj_t requests_PUT(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + network_checkConnection(); + enum { ARG_url, ARG_data }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *url = NULL; + + url = (char *)mp_obj_str_get_str(args[ARG_url].u_obj); + + mp_obj_t res = request(HTTP_METHOD_PUT, false, args[ARG_data].u_obj, url, NULL); + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(requests_PUT_obj, 1, requests_PUT); + +//---------------------------------------------------------------------------------------- +STATIC mp_obj_t requests_PATCH(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + network_checkConnection(); + enum { ARG_url, ARG_data }; + const mp_arg_t allowed_args[] = { + { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + char *url = NULL; + + url = (char *)mp_obj_str_get_str(args[ARG_url].u_obj); + + mp_obj_t res = request(HTTP_METHOD_PATCH, false, args[ARG_data].u_obj, url, NULL); + + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(requests_PATCH_obj, 1, requests_PATCH); + +//--------------------------------------------- +STATIC mp_obj_t requests_debug(mp_obj_t dbg_in) +{ + rq_debug = mp_obj_is_true(dbg_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(requests_debug_obj, requests_debug); + +//---------------------------------------------------- +STATIC mp_obj_t requests_certificate(mp_obj_t cert_in) +{ + if (cert_in != mp_const_none) get_certificate(cert_in, cert_pem); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(requests_certificate_obj, requests_certificate); + + +//================================================================ +STATIC const mp_rom_map_elem_t requests_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_requests) }, + + { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&requests_GET_obj) }, + { MP_ROM_QSTR(MP_QSTR_head), MP_ROM_PTR(&requests_HEAD_obj) }, + { MP_ROM_QSTR(MP_QSTR_post), MP_ROM_PTR(&requests_POST_obj) }, + { MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&requests_PUT_obj) }, + { MP_ROM_QSTR(MP_QSTR_patch), MP_ROM_PTR(&requests_PATCH_obj) }, + { MP_ROM_QSTR(MP_QSTR_debug), MP_ROM_PTR(&requests_debug_obj) }, + { MP_ROM_QSTR(MP_QSTR_certificate), MP_ROM_PTR(&requests_certificate_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(requests_module_globals, requests_module_globals_table); + +//========================================== +const mp_obj_module_t mp_module_requests = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&requests_module_globals, +}; + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/modsocket.c b/MicroPython_BUILD/components/micropython/esp32/modsocket.c index e8891b9a..71f57c56 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modsocket.c +++ b/MicroPython_BUILD/components/micropython/esp32/modsocket.c @@ -48,6 +48,7 @@ #include "py/mperrno.h" #include "lib/netutils/netutils.h" #include "tcpip_adapter.h" +#include "modnetwork.h" #include "lwip/sockets.h" #include "lwip/netdb.h" @@ -63,11 +64,81 @@ typedef struct _socket_obj_t { uint8_t domain; uint8_t type; uint8_t proto; + bool peer_closed; unsigned int retries; + #if MICROPY_PY_USOCKET_EVENTS + mp_obj_t events_callback; + struct _socket_obj_t *events_next; + #endif } socket_obj_t; void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms); +#if MICROPY_PY_USOCKET_EVENTS +// Support for callbacks on asynchronous socket events (when socket becomes readable) + +// This divisor is used to reduce the load on the system, so it doesn't poll sockets too often +#define USOCKET_EVENTS_DIVISOR (8) + +STATIC uint8_t usocket_events_divisor; +STATIC socket_obj_t *usocket_events_head; + +void usocket_events_deinit(void) { + usocket_events_head = NULL; +} + +// Assumes the socket is not already in the linked list, and adds it +STATIC void usocket_events_add(socket_obj_t *sock) { + sock->events_next = usocket_events_head; + usocket_events_head = sock; +} + +// Assumes the socket is already in the linked list, and removes it +STATIC void usocket_events_remove(socket_obj_t *sock) { + for (socket_obj_t **s = &usocket_events_head;; s = &(*s)->events_next) { + if (*s == sock) { + *s = (*s)->events_next; + return; + } + } +} + +// Polls all registered sockets for readability and calls their callback if they are readable +void usocket_events_handler(void) { + if (usocket_events_head == NULL) { + return; + } + if (--usocket_events_divisor) { + return; + } + usocket_events_divisor = USOCKET_EVENTS_DIVISOR; + + fd_set rfds; + FD_ZERO(&rfds); + int max_fd = 0; + + for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) { + FD_SET(s->fd, &rfds); + max_fd = MAX(max_fd, s->fd); + } + + // Poll the sockets + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + int r = select(max_fd + 1, &rfds, NULL, NULL, &timeout); + if (r <= 0) { + return; + } + + // Call the callbacks + for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) { + if (FD_ISSET(s->fd, &rfds)) { + mp_call_function_1_protected(s->events_callback, s); + } + } +} + +#endif // MICROPY_PY_USOCKET_EVENTS + NORETURN static void exception_from_errno(int _errno) { // Here we need to convert from lwip errno values to MicroPython's standard ones if (_errno == EINPROGRESS) { @@ -76,27 +147,10 @@ NORETURN static void exception_from_errno(int _errno) { mp_raise_OSError(_errno); } -void check_for_exceptions() { - mp_obj_t exc = MP_STATE_VM(mp_pending_exception); - if (exc != MP_OBJ_NULL) { - MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; - nlr_raise(exc); - } +static inline void check_for_exceptions(void) { + mp_handle_pending(); } -STATIC mp_obj_t socket_close(const mp_obj_t arg0) { - socket_obj_t *self = MP_OBJ_TO_PTR(arg0); - if (self->fd >= 0) { - int ret = lwip_close_r(self->fd); - if (ret != 0) { - exception_from_errno(errno); - } - self->fd = -1; - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); - static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) { const struct addrinfo hints = { .ai_family = AF_INET, @@ -107,7 +161,7 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc if (MP_OBJ_IS_SMALL_INT(port)) { // This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but // that's the API we have to work with ... - port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str("%s", 2, true), port); + port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port); } const char *host_str = mp_obj_str_get_str(host); @@ -159,7 +213,7 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { struct sockaddr addr; socklen_t addr_len = sizeof(addr); - mp_hal_set_wdt_tmo(); + mp_hal_set_wdt_tmo(); int new_fd = -1; for (int i=0; i<=self->retries; i++) { MP_THREAD_GIL_EXIT(); @@ -168,7 +222,7 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { if (new_fd >= 0) break; if (errno != EAGAIN) exception_from_errno(errno); check_for_exceptions(); - mp_hal_reset_wdt(); + mp_hal_reset_wdt(); } if (new_fd < 0) mp_raise_OSError(MP_ETIMEDOUT); @@ -179,6 +233,7 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) { sock->domain = self->domain; sock->type = self->type; sock->proto = self->proto; + sock->peer_closed = false; _socket_settimeout(sock, UINT64_MAX); // make the return value @@ -226,6 +281,7 @@ STATIC mp_obj_t socket_accepted(const mp_obj_t arg0) { sock->domain = self->domain; sock->type = self->type; sock->proto = self->proto; + sock->peer_closed = false; _socket_settimeout(sock, UINT64_MAX); // make the return value @@ -272,6 +328,25 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { break; } + #if MICROPY_PY_USOCKET_EVENTS + // level: SOL_SOCKET + // special "register callback" option + case 20: { + if (args[3] == mp_const_none) { + if (self->events_callback != MP_OBJ_NULL) { + usocket_events_remove(self); + self->events_callback = MP_OBJ_NULL; + } + } else { + if (self->events_callback == MP_OBJ_NULL) { + usocket_events_add(self); + } + self->events_callback = args[3]; + } + break; + } + #endif + // level: IPPROTO_IP case IP_ADD_MEMBERSHIP: { mp_buffer_info_t bufinfo; @@ -328,25 +403,59 @@ STATIC mp_obj_t socket_setblocking(const mp_obj_t arg0, const mp_obj_t arg1) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); -mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in, - struct sockaddr *from, socklen_t *from_len) { +// XXX this can end up waiting a very long time if the content is dribbled in one character +// at a time, as the timeout resets each time a recvfrom succeeds ... this is probably not +// good behaviour. +STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, + struct sockaddr *from, socklen_t *from_len, int *errcode) { socket_obj_t *sock = MP_OBJ_TO_PTR(self_in); - size_t len = mp_obj_get_int(len_in); - vstr_t vstr; - vstr_init_len(&vstr, len); + // If the peer closed the connection then the lwIP socket API will only return "0" once + // from lwip_recvfrom_r and then block on subsequent calls. To emulate POSIX behaviour, + // which continues to return "0" for each call on a closed socket, we set a flag when + // the peer closed the socket. + if (sock->peer_closed) { + return 0; + } + + mp_hal_set_wdt_tmo(); // XXX Would be nicer to use RTC to handle timeouts - mp_hal_set_wdt_tmo(); - for (int i=0; i<=sock->retries; i++) { + for (int i = 0; i <= sock->retries; ++i) { MP_THREAD_GIL_EXIT(); - int r = lwip_recvfrom_r(sock->fd, vstr.buf, len, 0, from, from_len); + int r = lwip_recvfrom_r(sock->fd, buf, size, 0, from, from_len); MP_THREAD_GIL_ENTER(); - if (r >= 0) { vstr.len = r; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } - if (errno != EWOULDBLOCK) exception_from_errno(errno); + if (r == 0) { + sock->peer_closed = true; + } + if (r >= 0) { + return r; + } + if (errno != EWOULDBLOCK) { + *errcode = errno; + return MP_STREAM_ERROR; + } check_for_exceptions(); - mp_hal_reset_wdt(); + mp_hal_reset_wdt(); + } + + *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; + return MP_STREAM_ERROR; +} + +mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in, + struct sockaddr *from, socklen_t *from_len) { + size_t len = mp_obj_get_int(len_in); + vstr_t vstr; + vstr_init_len(&vstr, len); + + int errcode; + mp_uint_t ret = _socket_read_data(self_in, vstr.buf, len, from, from_len, &errcode); + if (ret == MP_STREAM_ERROR) { + exception_from_errno(errcode); } - mp_raise_OSError(MP_ETIMEDOUT); + + vstr.len = ret; + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { @@ -371,7 +480,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) { int sentlen = 0; - mp_hal_set_wdt_tmo(); + mp_hal_set_wdt_tmo(); for (int i=0; i<=sock->retries && sentlen < datalen; i++) { MP_THREAD_GIL_EXIT(); int r = lwip_write_r(sock->fd, data+sentlen, datalen-sentlen); @@ -379,7 +488,7 @@ int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) { if (r < 0 && errno != EWOULDBLOCK) exception_from_errno(errno); if (r > 0) sentlen += r; check_for_exceptions(); - mp_hal_reset_wdt(); + mp_hal_reset_wdt(); } if (sentlen == 0) mp_raise_OSError(MP_ETIMEDOUT); return sentlen; @@ -420,7 +529,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ to.sin_port = lwip_htons(netutils_parse_inet_addr(addr_in, (uint8_t*)&to.sin_addr, NETUTILS_BIG)); // send the data - mp_hal_set_wdt_tmo(); + mp_hal_set_wdt_tmo(); for (int i=0; i<=self->retries; i++) { MP_THREAD_GIL_EXIT(); int ret = lwip_sendto_r(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to)); @@ -430,7 +539,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ exception_from_errno(errno); } check_for_exceptions(); - mp_hal_reset_wdt(); + mp_hal_reset_wdt(); } mp_raise_OSError(MP_ETIMEDOUT); } @@ -449,31 +558,13 @@ STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile); -// XXX this can end up waiting a very long time if the content is dribbled in one character -// at a time, as the timeout resets each time a recvfrom succeeds ... this is probably not -// good behaviour. - STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { - socket_obj_t *sock = self_in; - - // XXX Would be nicer to use RTC to handle timeouts - mp_hal_set_wdt_tmo(); - for (int i=0; i<=sock->retries; i++) { - MP_THREAD_GIL_EXIT(); - int r = lwip_recvfrom_r(sock->fd, buf, size, 0, NULL, NULL); - MP_THREAD_GIL_ENTER(); - if (r >= 0) return r; - if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; } - check_for_exceptions(); - mp_hal_reset_wdt(); - } - *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; - return MP_STREAM_ERROR; + return _socket_read_data(self_in, buf, size, NULL, NULL, errcode); } STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { socket_obj_t *sock = self_in; - mp_hal_set_wdt_tmo(); + mp_hal_set_wdt_tmo(); for (int i=0; i<=sock->retries; i++) { MP_THREAD_GIL_EXIT(); int r = lwip_write_r(sock->fd, buf, size); @@ -481,7 +572,7 @@ STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_ if (r > 0) return r; if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; } check_for_exceptions(); - mp_hal_reset_wdt(); + mp_hal_reset_wdt(); } *errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT; return MP_STREAM_ERROR; @@ -510,35 +601,51 @@ STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintpt if (FD_ISSET(socket->fd, &wfds)) ret |= MP_STREAM_POLL_WR; if (FD_ISSET(socket->fd, &efds)) ret |= MP_STREAM_POLL_HUP; return ret; + } else if (request == MP_STREAM_CLOSE) { + if (socket->fd >= 0) { + #if MICROPY_PY_USOCKET_EVENTS + if (socket->events_callback != MP_OBJ_NULL) { + usocket_events_remove(socket); + socket->events_callback = MP_OBJ_NULL; + } + #endif + int ret = lwip_close_r(socket->fd); + if (ret != 0) { + *errcode = errno; + return MP_STREAM_ERROR; + } + socket->fd = -1; + } + return 0; } *errcode = MP_EINVAL; return MP_STREAM_ERROR; } -STATIC const mp_map_elem_t socket_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_accepted), (mp_obj_t)&socket_accepted_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sendall), (mp_obj_t)&socket_sendall_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&socket_makefile_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_fileno), (mp_obj_t)&socket_fileno_obj }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj}, - { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj }, +STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, + { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, + { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, + { MP_ROM_QSTR(MP_QSTR_accepted), MP_ROM_PTR(&socket_accepted_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_sendall_obj) }, + { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, + { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, + { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, + { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, + { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, + { MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) }, + { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) }, + + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); @@ -561,6 +668,7 @@ STATIC mp_obj_t get_socket(size_t n_args, const mp_obj_t *args) { sock->domain = AF_INET; sock->type = SOCK_STREAM; sock->proto = 0; + sock->peer_closed = false; if (n_args > 0) { sock->domain = mp_obj_get_int(args[0]); if (n_args > 1) { @@ -581,9 +689,11 @@ STATIC mp_obj_t get_socket(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_socket_obj, 0, 3, get_socket); -STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port) { +STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) { + // TODO support additional args beyond the first two + struct addrinfo *res = NULL; - _socket_getaddrinfo2(host, port, &res); + _socket_getaddrinfo2(args[0], args[1], &res); mp_obj_t ret_list = mp_obj_new_list(0, NULL); for (struct addrinfo *resi = res; resi; resi = resi->ai_next) { @@ -591,7 +701,7 @@ STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port) mp_obj_new_int(resi->ai_family), mp_obj_new_int(resi->ai_socktype), mp_obj_new_int(resi->ai_protocol), - mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname), false), + mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)), mp_const_none }; @@ -602,7 +712,7 @@ STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port) char buf[16]; ip4addr_ntoa_r(&ip4_addr, buf, sizeof(buf)); mp_obj_t inaddr_objs[2] = { - mp_obj_new_str(buf, strlen(buf), false), + mp_obj_new_str(buf, strlen(buf)), mp_obj_new_int(ntohs(addr->sin_port)) }; addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs); @@ -613,7 +723,7 @@ STATIC mp_obj_t esp_socket_getaddrinfo(const mp_obj_t host, const mp_obj_t port) if (res) lwip_freeaddrinfo(res); return ret_list; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_getaddrinfo_obj, esp_socket_getaddrinfo); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_socket_getaddrinfo_obj, 2, 6, esp_socket_getaddrinfo); STATIC mp_obj_t esp_socket_initialize() { static int initialized = 0; @@ -626,23 +736,23 @@ STATIC mp_obj_t esp_socket_initialize() { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_socket_initialize_obj, esp_socket_initialize); -STATIC const mp_map_elem_t mp_module_socket_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) }, - { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_socket_initialize_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&get_socket_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_socket_getaddrinfo_obj }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(SOCK_RAW) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IP), MP_OBJ_NEW_SMALL_INT(IPPROTO_IP) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(SOL_SOCKET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(SO_REUSEADDR) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_OBJ_NEW_SMALL_INT(IP_ADD_MEMBERSHIP) }, +STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, + { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_socket_initialize_obj) }, + { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&get_socket_obj) }, + { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&esp_socket_getaddrinfo_obj) }, + + { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(AF_INET) }, + { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(AF_INET6) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCK_STREAM) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCK_DGRAM) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(SOCK_RAW) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(IPPROTO_TCP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(IPPROTO_UDP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(IPPROTO_IP) }, + { MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(SOL_SOCKET) }, + { MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SO_REUSEADDR) }, + { MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table); diff --git a/MicroPython_BUILD/components/micropython/esp32/modssh.c b/MicroPython_BUILD/components/micropython/esp32/modssh.c index 4b66b548..ffac9c04 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modssh.c +++ b/MicroPython_BUILD/components/micropython/esp32/modssh.c @@ -45,12 +45,13 @@ #include "libs/espcurl.h" #include "extmod/vfs_native.h" #include "libssh2.h" +#include "modnetwork.h" //------------------------------------------------------------------------------------------------------- STATIC mp_obj_t curl_SSH_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, uint8_t type) { - checkConnection(); + network_checkConnection(); enum { ARG_url, ARG_user, ARG_pass, ARG_key, ARG_file, ARG_port }; const mp_arg_t allowed_args[] = { { MP_QSTR_url, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/logging.py b/MicroPython_BUILD/components/micropython/esp32/modules/logging.py index 1c3ef0d8..cea2de03 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules/logging.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/logging.py @@ -19,18 +19,30 @@ class Logger: + level = NOTSET + def __init__(self, name): - self.level = NOTSET self.name = name def _level_str(self, level): - if level in _level_dict: - return _level_dict[level] - return "LVL" + str(level) + l = _level_dict.get(level) + if l is not None: + return l + return "LVL%s" % level + + def setLevel(self, level): + self.level = level + + def isEnabledFor(self, level): + return level >= (self.level or _level) def log(self, level, msg, *args): if level >= (self.level or _level): - print(("%s:%s:" + msg) % ((self._level_str(level), self.name) + args), file=_stream) + _stream.write("%s:%s:" % (self._level_str(level), self.name)) + if not args: + print(msg, file=_stream) + else: + print(msg % args, file=_stream) def debug(self, msg, *args): self.log(DEBUG, msg, *args) @@ -47,6 +59,13 @@ def error(self, msg, *args): def critical(self, msg, *args): self.log(CRITICAL, msg, *args) + def exc(self, e, msg, *args): + self.log(ERROR, msg, *args) + sys.print_exception(e, _stream) + + def exception(self, msg, *args): + self.exc(sys.exc_info()[1], msg, *args) + _level = INFO _loggers = {} diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/i2c_bus.py b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/i2c_bus.py new file mode 100644 index 00000000..13726b3f --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/i2c_bus.py @@ -0,0 +1,20 @@ +from machine import I2C + +PORTA = (21,22) +PORTC = (17,16) +M_BUS = PORTA + +bus_0 = None +bus_1 = None + + +def get(port): + global bus_0, bus_1 + if port == PORTA or port == M_BUS: + if bus_0 == None: + bus_0 = I2C(id=0, sda=port[0], scl=port[1]) + return bus_0 + elif port == PORTC: + if bus_1 == None: + bus_1 = I2C(id=1, sda=port[0], scl=port[1]) + return bus_1 diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/m5stack.py b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/m5stack.py new file mode 100644 index 00000000..ca1cec52 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/m5stack.py @@ -0,0 +1,115 @@ +import utils +import uos as os +import utime as time +import display as lcd +import machine, ubinascii +from ubutton import Button +from micropython import const +from machine import Timer + +tex = Timer(0) +tex.init(mode = tex.EXTBASE) + +_BUTTON_A_PIN = const(39) +_BUTTON_B_PIN = const(38) +_BUTTON_C_PIN = const(37) +_SPEAKER_PIN = const(25) +# ------------------------------------------------------------------------------- # +class Speaker: + def __init__(self, pin=25, volume=5): + self.pwm = machine.PWM(machine.Pin(pin), freq = 1, duty = 0, timer = 2) + self._timer = None + self._volume = volume + self._beat_time = 500 + self._timer = machine.Timer(8) + self._timer.init(period=10, mode=self._timer.ONE_SHOT, callback=self._timeout_cb) + + def _timeout_cb(self, timer): + self.pwm.duty(0) + time.sleep_ms(1) + self.pwm.freq(1) + self._timer.stop() + + def tone(self, freq=1800, duration=200, timer=True, volume=None): + if volume == None: + self.pwm.init(freq=freq, duty=self._volume) + else: + self.pwm.init(freq=freq, duty=volume) + duration = max(0, duration) + if timer: + if self._timer.isrunning(): + self._timer.period(duration) + else: + self._timer.init(period=duration, mode=self._timer.ONE_SHOT, callback=self._timeout_cb) + time.sleep_ms(duration-15) + else: + time.sleep_ms(duration) + self.pwm.duty(0) + time.sleep_ms(1) + self.pwm.freq(1) + + + def sing(self, freq=1800, beat=1, end=True, volume=None): + self.tone(freq, int(beat*self._beat_time), end, volume) + + def set_beat(self, value=120): + self._beat_time = int(60000 / value) + + def volume(self, val): + self._volume = val + + +def fimage(x, y, file, type=1): + if file[:3] == '/sd': + utils.filecp(file, '/flash/fcache', blocksize=8192) + lcd.image(x, y, '/flash/fcache', 0, type) + os.remove('/flash/fcache') + else: + lcd.image(x, y, file, 0, type) + +def delay(ms): + time.sleep_ms(ms) + + +def map_value(value, input_min, input_max, aims_min, aims_max): + value_deal = value * (aims_max - aims_min) / (input_max - input_min) + aims_min + value_deal = value_deal if value_deal < aims_max else aims_max + value_deal = value_deal if value_deal > aims_min else aims_min + return value_deal + +# ------------------ M5Stack ------------------- +# Node ID +node_id = ubinascii.hexlify(machine.unique_id()).decode('utf-8') +print('\nDevice ID:' + node_id) +print('LCD initializing...', end='') + +# pin Analog and digital + +# LCD +lcd = lcd.TFT() +lcd.init(lcd.M5STACK, width=240, height=320, speed=40000000, rst_pin=33, + miso=19, mosi=23, clk=18, cs=14, dc=27, bgr=True,invrot=3, + expwm=machine.PWM(32, duty=0, timer=1)) +lcd.setBrightness(30) +lcd.clear() +lcd.setColor(0xCCCCCC) +print('Done!') + + +#BUTTON +m5button = Button() +buttonA = m5button.register(_BUTTON_A_PIN) +buttonB = m5button.register(_BUTTON_B_PIN) +buttonC = m5button.register(_BUTTON_C_PIN) + +# SPEAKER +speaker = Speaker() + +# ----------------------- for flow----------------------------------------- # +def wait(s): + if s > 0.02: + for i in range(int(s / 0.01)): + time.sleep_ms(10) + else: + time.sleep(s) +# ---------------------------------------------------------------- # \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/ubutton.py b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/ubutton.py new file mode 100644 index 00000000..573f4aee --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/ubutton.py @@ -0,0 +1,121 @@ +from utime import ticks_ms + +# EVENT_IS_PRESSED = const(0x01) +# EVENT_WAS_PRESSED = const(0x02) +# EVENT_WAS_RELEASED = const(0x04) +# EVENT_RELEASED_FOR = const(0x08) + +class M5_Button: + + def __init__(self, pin, name='none', long_name='none', dbtime=20): + from machine import Pin + self._pin = Pin(pin) + self._pin.init(Pin.IN, handler=self.irq_cb, trigger=(Pin.IRQ_FALLING|Pin.IRQ_RISING)) + self._wasPressed_cb = None + self._wasReleased_cb = None + self._releasedFor_cb = None + self._timeshoot = 0 + self._dbtime = dbtime + self._lastState = False + self._startTicks = 0 + self._timeout = 0 + self._name = name + self._long_name = long_name + self._event = 0 + + + def irq_cb(self, pin): + pin_val = pin.value() + if self._pin == pin: + # FALLING + if pin_val == 0: + if ticks_ms() - self._timeshoot > self._dbtime: + self._lastState = True + self._startTicks = ticks_ms() + self._event |= 0x02 # EVENT_WAS_PRESSED + if self._wasPressed_cb: + self._wasPressed_cb() + # RISING + elif pin_val == 1: + if self._lastState == True: + self._lastState = False + self._event |= 0x04 # EVENT_WAS_RELEASED + if self._timeout > 0 and ticks_ms() - self._startTicks > self._timeout: + self._event = 0 + self._event |= 0x08 # EVENT_RELEASED_FOR + if self._releasedFor_cb: + self._releasedFor_cb() + elif self._wasReleased_cb: + self._wasReleased_cb() + self._timeshoot = ticks_ms() + + def clear(self): + self._event = 0 + + def read(self): + return not self._pin.value() + + + def isPressed(self): + return self.read() + + + def isReleased(self): + return not self.read() + + + def wasPressed(self, callback=None): + if callback == None: + if (self._event & 0x02) > 0: # EVENT_WAS_PRESSED + self._event -= 0x02 + return True + else: + return False + else: + self._wasPressed_cb = callback + + + def wasReleased(self, callback=None): + if callback == None: + if (self._event & 0x04 ) > 0: # EVENT_WAS_RELEASED + self._event -= 0x04 + return True + else: + return False + else: + self._wasReleased_cb = callback + + + def pressedFor(self, timeout): + if self._lastState and ticks_ms() - self._startTicks > timeout * 1000: + return True + else: + return False + + + def releasedFor(self, timeout, callback=None): + self._timeout = timeout * 1000 # second + if callback == None: + if (self._event & 0x08) > 0: # EVENT_RELEASED_FOR + self._event -= 0x08 + return True + else: + return False + else: + self._releasedFor_cb = callback + +class Button: + def __init__(self): + self.button = [] + + def register(self, button): + _button = M5_Button(button) + self.button.append(_button) + return _button + + def clear(self): + for i in self.button: + i._event = 0 + i._wasPressed_cb = None + i._wasReleased_cb = None + i._releasedFor_cb = None \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/units.py b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/units.py new file mode 100644 index 00000000..83fac23f --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/units.py @@ -0,0 +1,426 @@ +from micropython import const +import machine +from machine import I2C, Pin, PWM +import math +import i2c_bus +import utime as time +from m5stack import speaker +import ustruct + +# PORTA = (25,13) +PORTA = (21,22) +PORTB = (26,36) +PORTC = (17,16) + +class_map = {'dht12': None, 'bmp280': None, 'adc': None, 'servo': {}} + +class ENV(): + def __init__(self, port=PORTA): + global class_map + from dht12 import DHT12 + from bmp280 import BMP280 + self.i2c = i2c_bus.get(i2c_bus.M_BUS) + if class_map['dht12'] == None: + class_map['dht12'] = DHT12(self.i2c) + if class_map['bmp280'] == None: + class_map['bmp280'] = BMP280(self.i2c) + self.dht12 = class_map['dht12'] + self.bmp280 = class_map['bmp280'] + self.time = 0 + self.data = None + + def available(self): + if 92 in self.i2c.scan(): + return True + else: + return False + + def pressure(self): + if time.ticks_ms() - self.time > 100: + self.time = time.ticks_ms() + self.data = self.values + return round(self.data[1], 2) + + def temperature(self): + if time.ticks_ms() - self.time > 100: + self.time = time.ticks_ms() + self.data = self.values + return round(self.data[0], 2) + + def humidity(self): + if time.ticks_ms() - self.time > 100: + self.time = time.ticks_ms() + self.data = self.values + return round(self.data[2], 2) + + @property + def values(self): + """ readable values """ + self.dht12.measure() + h = self.dht12.humidity() + t, p = self.bmp280.read_compensated_data() + t /= 100 + p /= 25600 + return t, p, h + +class PIR(): # 1 OUT + def __init__(self, port=PORTB): + self.pin = Pin(PORTB[1], Pin.IN) + self.cb = None + + def callback(self, cb): + self.cb = cb + self.pin.init(handler=self._irq_cb, trigger=(Pin.IRQ_RISING | Pin.IRQ_FALLING)) + + def _irq_cb(self, pin): + self.cb(pin.value()) + + def read(self): + return self.pin.value() + +class RGB(): # 0 IN 1 OUT + def __init__(self, port=PORTB, nums=1): + self.nums = nums*3 + self.np = machine.Neopixel(Pin(port[0]), self.nums) + + def setColor(self, color, pos=None): + if pos == None: + self.np.set(1, color, num=self.nums) + else: + self.np.set(pos, color) + + def setHSB(self, hue, saturation, brightness, pos=None): + if pos == None: + self.np.setHSB(1, hue, saturation, brightness, num=self.nums) + else: + self.np.setHSB(pos, hue, saturation, brightness) + + def deinit(self): + self.np.deinit() + +class ANGLE(): # 1 + def __init__(self, port=PORTB): + global class_map + from machine import ADC + if class_map['adc'] != None: + class_map['adc'].deinit() + self.adc = ADC(PORTB[1]) + self.adc.atten(ADC.ATTN_11DB) + class_map['adc'] = self.adc + + def deinit(self): + self.adc.deinit() + + def readraw(self): + return 4095 - self.adc.readraw() + + def read(self): + data = 0 + max = 0 + min = 4096 + for i in range(0, 10): + newdata = 4095 - self.adc.readraw() + data += newdata + if newdata > max: + max = newdata + if newdata < min: + min = newdata + data -= (max + min) + data >>= 3 + return round(1024 * data / 4095, 2) + +class Servo: + """ + A simple class for controlling hobby servos. + + Args: + pin (machine.Pin): The pin where servo is connected. Must support PWM. + freq (int): The frequency of the signal, in hertz. + min_us (int): The minimum signal length supported by the servo. + max_us (int): The maximum signal length supported by the servo. + angle (int): The angle between the minimum and maximum positions. + + """ + def __init__(self, port=PORTA, freq=50, min_us=600, max_us=2400, angle=180): + self.min_us = min_us + self.max_us = max_us + self.us = 0 + self.freq = freq + self.angle = angle + self.port = port + if port[0] in class_map['servo'].keys(): + class_map['servo'][port[0]].deinit() + + self.pwm = PWM(port[0], freq=freq, duty=0, timer=3) + class_map['servo'][port[0]] = self.pwm + + + def write_us(self, us): + """Set the signal to be ``us`` microseconds long. Zero disables it.""" + if us == 0: + self.pwm.duty(0) + return + us = min(self.max_us, max(self.min_us, us)) + duty = us * 100 * self.freq / 1000000 + self.pwm.duty(duty) + + def write_angle(self, degrees=None, radians=None): + """Move to the specified angle in ``degrees`` or ``radians``.""" + if degrees is None: + degrees = math.degrees(radians) + degrees = degrees % 360 + total_range = self.max_us - self.min_us + us = self.min_us + total_range * degrees / self.angle + self.write_us(us) + + +rgb_muti_porta = None +rgb_muti_portb = None +rgb_muti_portc = None + +class RGB_Multi: + # TODO if not sleep, will appear some bug + def __init__(self, port=PORTB, number=143): + global rgb_muti_porta, rgb_muti_portb, rgb_muti_portc + if port == PORTB and rgb_muti_portb != None: + rgb_muti_portb.deinit() + elif port == PORTA and rgb_muti_porta != None: + rgb_muti_porta.deinit() + elif port == PORTC and rgb_muti_portc != None: + rgb_muti_portc.deinit() + self.port = port + self.pin = port[0] + self.number = number + self.np = machine.Neopixel(self.pin, self.number) + self.np.brightness(10, update=False) + self.np.show() + time.sleep_ms(10) + + if port == PORTA: + rgb_muti_porta = self.np + elif port == PORTB: + rgb_muti_portb = self.np + elif port == PORTC: + rgb_muti_portc = self.np + + def setColor(self, num, color): + self.np.set(num, color) + time.sleep_ms(10) + + def setColorFrom(self, begin, end, color): + begin = min(self.number, max(begin, 1)) + end = min(self.number, max(end, 1)) + for i in range(begin, end+1): + self.np.set(i, color, update=False) + self.np.show() + time.sleep_ms(10) + + def setColorAll(self, color): + for i in range(1, self.number+1): + self.np.set(i, color, update=False) + self.np.show() + time.sleep_ms(10) + + def setBrightness(self, brightness): + brightness = min(255, max(0, brightness)) + self.np.brightness(brightness, update=False) + self.np.show() + time.sleep_ms(10) + + def deinit(self): + global rgb_muti_porta, rgb_muti_portb, rgb_muti_portc + self.np.deinit() + if self.port == PORTA: + rgb_muti_porta = None + elif self.port == PORTB: + rgb_muti_portb = None + elif self.port == PORTC: + rgb_muti_portc = None + +class Joystick(): + def __init__(self, port=PORTC): + self.i2c = i2c_bus.get(port) + self.time = 0 + self.value = None + + @property + def X(self): + if time.ticks_ms() - self.time > 100: + self.time = time.ticks_ms() + try: + self.value = self.i2c.readfrom(0x52, 3) + except: + pass + return self.value[0] + + @property + def Y(self): + if time.ticks_ms() - self.time > 100: + self.time = time.ticks_ms() + try: + self.value = self.i2c.readfrom(0x52, 3) + except: + pass + return self.value[1] + + @property + def Press(self): + if time.ticks_ms() - self.time > 100: + self.time = time.ticks_ms() + try: + self.value = self.i2c.readfrom(0x52, 3) + except: + pass + + return self.value[2] if self.value[2] < 2 else 0 + +class Light: + def __init__(self, port=PORTB): + global class_map + from machine import ADC, Pin + if class_map['adc'] != None: + class_map['adc'].deinit() + self.adc = ADC(PORTB[1]) + self.adc.atten(ADC.ATTN_11DB) + class_map['adc'] = self.adc + self.d_pin = Pin(PORTB[0], Pin.IN, Pin.PULL_UP) + + def a_read(self): + data = 0 + max = 0 + min = 4096 + for i in range(0, 10): + newdata = 4095 - self.adc.readraw() + data += newdata + if newdata > max: + max = newdata + if newdata < min: + min = newdata + data -= (max + min) + data >>= 3 + return round(1024 * data / 4095, 2) + + def d_read(self): + return self.d_pin.value() + +Earth = Light + +MAKEY_I2C_ADDR = const(0x51) +class Makey: + def __init__(self, port=PORTA): + self._i2c = i2c_bus.get(port) + self.sing_map = [261, 293, 329, 349, 392, 440, 494, 294] + + def _get_value(self): + value = 0 + data = self._i2c.readfrom(MAKEY_I2C_ADDR, 2) + value = data[0]|(data[1] << 8) + return value + + def write(self, data): + self._i2c.write(MAKEY_I2C_ADDR, data) + + def value(self): + value = self._get_value() + for i in range(14): + if (value >> i) & 0x01: + return i + return -1 + + + def play_piano(self, beat): + key_value = self._get_value() + time.sleep_ms(1) + for i in range(8): + if (key_value >> i) & 0x01: + speaker.sing(self.sing_map[i], beat) + break + +class IR(): # 1 + def __init__(self, port=PORTB): + pass + +class Weigh: + def __init__(self, port=PORTA): + self.pinclk = Pin(port[0], Pin.OUT) + self.pindata = Pin(port[1], Pin.IN) + self.zero_value = 0 + self.gap_value = 250 + self.pinclk.value(0) + + def zero(self): + self.zero_value = self._weight + + @property + def _weight(self): + pinclk = self.pinclk + pindata = self.pindata + val, times, count = 1, 0, 0 + pinclk.value(0) + + + while val: + val = pindata.value() + if val: + times += 1 + time.sleep_ms(10) + if times > 20: + return 0 + + for i in range(0, 24): + pinclk.value(1) + count = count << 1; + pinclk.value(0) + + val = pindata.value() + if val == 1: + count = count + 1 + + pinclk.value(1) + a = 1 + pinclk.value(0) + count = count ^ 0x800000 + return int(count / self.gap_value) + + def get_weight(self): + countdata = self._weight - self.zero_value + return countdata + +class Tracker: + def __init__(self, port=i2c_bus.PORTA): + self._addr = 0x5a + self._i2c = i2c_bus.get(port) + + def _register_char(self, register, value=None, buf=bytearray(1)): + if value is None: + self._i2c.readfrom_mem_into(self._addr, register, buf) + return buf[0] + + ustruct.pack_into("h", buf)[0] + + ustruct.pack_into(">h", buf, 0, value) + return self._i2c.writeto_mem(self._addr, register, buf) + + def get_analog_value(self, number): + if number > 4 or number < 0: + return 0 + + return self._register_short(0x00 | number) + + def set_analog_value(self, number, value): + if number > 4 or number < 0: + return 0 + + self._register_short(0x10 | number, value) + + def get_digital_value(self, number): + if number > 4 or number < 0: + return 0 + + return self._register_char(0x00) & (1 << (number - 1)) \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/utils.py b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/utils.py new file mode 100644 index 00000000..19646344 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/m5flow/utils.py @@ -0,0 +1,62 @@ +import uos as os + +# ---- Basic file func ---- +def exists(fname): + try: + with open(fname): + pass + return True + except OSError: + return False + +def isfile(fname): + return exists(fname) + +def isdir(path): + try: + os.listdir(path) + return True + except: + return False + +def filecp(sfile, pfile, blocksize=4096): + with open(sfile, 'rb') as sf: + with open(pfile, 'w+') as pf: + while pf.write(sf.read(blocksize)): + pass + +def filesize(fname): + if isfile(fname): + return os.stat(fname)[6] + else: + return None + +def makedirs(path): + _path = '' + if path[0] == '/': + path = path.strip('/').split('/') + for i in path: + _path += '/' + i + try: + os.mkdir(_path) + except: + pass + else: + path = path.split('/') + for i in path: + _path += i + try: + os.mkdir(_path) + _path += '/' + except: + pass + +def lcd_text_button(number, message): + x_pos = 0 + if number == 'A': + x_pos = 62 + elif number == 'B': + x_pos = 159 + elif number == 'C': + x_pos = 253 + lcd.text(x_pos - int(lcd.textWidth(message) / 2), 235 - lcd.fontSize()[1], message) \ No newline at end of file diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/microWebSocket.py b/MicroPython_BUILD/components/micropython/esp32/modules/microWebSocket.py old mode 100644 new mode 100755 index afc16641..375eeb59 --- a/MicroPython_BUILD/components/micropython/esp32/modules/microWebSocket.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/microWebSocket.py @@ -1,8 +1,15 @@ +""" +The MIT License (MIT) +Copyright © 2018 Jean-Christophe Bos & HC² (www.hc2.fr) +Copyright © 2018 LoBo (https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo) +""" from hashlib import sha1 from binascii import b2a_base64 from struct import pack -import gc, _thread, time +import _thread +import time +import gc class MicroWebSocket : @@ -26,6 +33,7 @@ class MicroWebSocket : # ===( Utils )=============================================================== # ============================================================================ + @staticmethod def _tryAllocByteArray(size) : for x in range(10) : try : @@ -37,6 +45,7 @@ def _tryAllocByteArray(size) : # ---------------------------------------------------------------------------- + @staticmethod def _tryStartThread(func, args=(), stackSize=4096) : _ = _thread.stack_size(stackSize) for x in range(4) : @@ -61,6 +70,7 @@ def __init__(self, socket, httpClient, httpResponse, maxRecvLen, threaded, accep self.ClosedCallback = None self.thID = None self.isThreaded = threaded + if self._handshake(httpResponse) : self._ctrlBuf = MicroWebSocket._tryAllocByteArray(0x7D) self._msgBuf = MicroWebSocket._tryAllocByteArray(maxRecvLen) @@ -71,7 +81,7 @@ def __init__(self, socket, httpClient, httpResponse, maxRecvLen, threaded, accep th = MicroWebSocket._tryStartThread(self._wsProcess, (acceptCallback, ), stackSize) if th: self.thID = th - return + return else : self._wsProcess(acceptCallback) return @@ -89,8 +99,9 @@ def _handshake(self, httpResponse) : try : key = self._httpCli.GetRequestHeaders().get('Sec-WebSocket-Key', None) if key : - r = sha1(key + self._handshakeSign).digest() - r = b2a_base64(r).decode() + key += self._handshakeSign + r = sha1(key.encode()).digest() + r = b2a_base64(r).decode().strip() httpResponse.WriteSwitchProto("websocket", { "Sec-WebSocket-Accept" : r }) return True except : @@ -106,7 +117,6 @@ def _wsProcess(self, acceptCallback) : acceptCallback(self, self._httpCli) except Exception as ex : print("MicroWebSocket : Error on accept callback (%s)." % str(ex)) - while not self._closed : if self.isThreaded: notify = _thread.getnotification() @@ -115,7 +125,6 @@ def _wsProcess(self, acceptCallback) : break if not self._receiveFrame() : self.Close() - if self.ClosedCallback : try : self.ClosedCallback(self) @@ -126,7 +135,6 @@ def _wsProcess(self, acceptCallback) : def _receiveFrame(self) : try : - b = self._socket.read(2) if not b or len(b) != 2 : return False @@ -163,7 +171,8 @@ def _receiveFrame(self) : buf = memoryview(self._msgBuf)[self._msgLen:] if length > len(buf) : return False - if self._socket.readinto(buf, length) != length : + x = self._socket.readinto(buf[0:length]) + if x != length : return False if masked : for i in range(length) : @@ -194,7 +203,8 @@ def _receiveFrame(self) : if length > len(self._ctrlBuf) : return False if length > 0 : - if self._socket.readinto(self._ctrlBuf, length) != length : + x = self._socket.readinto(self._ctrlBuf[0:length]) + if x != length : return False pingData = memoryview(self._ctrlBuf)[:length] else : @@ -222,9 +232,12 @@ def _sendFrame(self, opcode, data=None, fin=True) : if dataLen > 0 : if dataLen >= 0x7E : self._socket.write(pack('>H', dataLen)) - return self._socket.write(data) == dataLen + ret = self._socket.write(data) == dataLen else : - return True + ret = True + if self._socket is not self._socket : + self._socket.flush() # CPython needs flush to continue protocol + return ret except : pass return False diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py b/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py old mode 100644 new mode 100755 index 589a0018..0e412feb --- a/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/microWebSrv.py @@ -1,10 +1,18 @@ - -from json import dumps -from os import stat -import socket -import gc -import network -import socket, gc, _thread, time +""" +The MIT License (MIT) +Copyright © 2018 Jean-Christophe Bos & HC² (www.hc2.fr) +Copyright © 2018 LoBo (https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo) +""" + + +from json import loads, dumps +from os import stat +import _thread +import network +import time +import socket +import gc +import re try : from microWebTemplate import MicroWebTemplate @@ -16,6 +24,15 @@ except : pass +class MicroWebSrvRoute : + def __init__(self, route, method, func, routeArgNames, routeRegex) : + self.route = route + self.method = method + self.func = func + self.routeArgNames = routeArgNames + self.routeRegex = routeRegex + + class MicroWebSrv : # ============================================================================ @@ -61,15 +78,34 @@ class MicroWebSrv : _pyhtmlPagesExt = '.pyhtml' + # ============================================================================ + # ===( Class globals )======================================================= + # ============================================================================ + + _docoratedRouteHandlers = [] + # ============================================================================ # ===( Utils )=============================================================== # ============================================================================ + @classmethod + def route(cls, url, method='GET'): + """ Adds a route handler function to the routing list """ + def route_decorator(func): + item = (url, method, func) + cls._docoratedRouteHandlers.append(item) + return func + return route_decorator + + # ---------------------------------------------------------------------------- + + @staticmethod def HTMLEscape(s) : return ''.join(MicroWebSrv._html_escape_chars.get(c, c) for c in s) # ---------------------------------------------------------------------------- + @staticmethod def _tryAllocByteArray(size) : for x in range(10) : try : @@ -81,9 +117,10 @@ def _tryAllocByteArray(size) : # ---------------------------------------------------------------------------- - def _tryStartThread(func, args=()) : - _ = _thread.stack_size(8*1024) - for x in range(4) : + @staticmethod + def _tryStartThread(func, args=(), stacksize=8192) : + _ = _thread.stack_size(stacksize) + for x in range(10) : try : gc.collect() th = _thread.start_new_thread("MicroWebServer", func, args) @@ -93,6 +130,8 @@ def _tryStartThread(func, args=()) : return False # ---------------------------------------------------------------------------- + + @staticmethod def _unquote(s) : r = s.split('%') for i in range(1, len(r)) : @@ -105,11 +144,13 @@ def _unquote(s) : # ---------------------------------------------------------------------------- + @staticmethod def _unquote_plus(s) : return MicroWebSrv._unquote(s.replace('+', ' ')) # ---------------------------------------------------------------------------- + @staticmethod def _fileExists(path) : try : stat(path) @@ -119,6 +160,7 @@ def _fileExists(path) : # ---------------------------------------------------------------------------- + @staticmethod def _isPyHTMLFile(filename) : return filename.lower().endswith(MicroWebSrv._pyhtmlPagesExt) @@ -127,11 +169,11 @@ def _isPyHTMLFile(filename) : # ============================================================================ def __init__( self, - routeHandlers = None, + routeHandlers = [], port = 80, bindIP = '0.0.0.0', webPath = "/flash/www" ) : - self._routeHandlers = routeHandlers + self._srvAddr = (bindIP, port) self._webPath = webPath self._notFoundUrl = None @@ -145,6 +187,25 @@ def __init__( self, self.WebSocketStackSize = 4096 self.AcceptWebSocketCallback = None + self._routeHandlers = [] + routeHandlers += self._docoratedRouteHandlers + for route, method, func in routeHandlers : + routeParts = route.split('/') + # -> ['', 'users', '', 'addresses', '', 'test', ''] + routeArgNames = [] + routeRegex = '' + for s in routeParts : + if s.startswith('<') and s.endswith('>') : + routeArgNames.append(s[1:-1]) + routeRegex += '/(\\w*)' + elif s : + routeRegex += '/' + s + routeRegex += '$' + # -> '/users/(\w*)/addresses/(\w*)/test/(\w*)$' + routeRegex = re.compile(routeRegex) + + self._routeHandlers.append(MicroWebSrvRoute(route, method, func, routeArgNames, routeRegex)) + # ============================================================================ # ===( Server Process )======================================================= # ============================================================================ @@ -168,18 +229,22 @@ def _serverProcess(self) : # gc.collect() time.sleep_ms(2) continue - except : + except Exception as e: + if not self.isThreaded: + print(e) break self._client(self, client, cliAddr) self._started = False + self._state = "Stoped" + self.thID = None # ============================================================================ # ===( Functions )============================================================ # ============================================================================ - def Start(self, threaded=True) : + def Start(self, threaded=True, stackSize=8192) : if not self._started : - if not network.WLAN().isconnected(): + if not network.WLAN().wifiactive(): print("WLAN not connected!") return gc.collect() @@ -195,7 +260,7 @@ def Start(self, threaded=True) : # using non-blocking socket self._server.settimeout(0.5) if threaded : - th = MicroWebSrv._tryStartThread(self._serverProcess) + th = MicroWebSrv._tryStartThread(self._serverProcess, stacksize=stackSize) if th: self.thID = th else : @@ -206,6 +271,8 @@ def Start(self, threaded=True) : def Stop(self) : if self._started : self._server.close() + if self.isThreaded: + _ = _thread.notify(self.thID, _thread.EXIT) # ---------------------------------------------------------------------------- @@ -237,17 +304,30 @@ def GetMimeTypeFromFilename(self, filename) : return None # ---------------------------------------------------------------------------- - + def GetRouteHandler(self, resUrl, method) : if self._routeHandlers : - resUrl = resUrl.upper() + #resUrl = resUrl.upper() + if resUrl.endswith('/') : + resUrl = resUrl[:-1] method = method.upper() - for route in self._routeHandlers : - if len(route) == 3 and \ - route[0].upper() == resUrl and \ - route[1].upper() == method : - return route[2] - return None + for rh in self._routeHandlers : + if rh.method == method : + m = rh.routeRegex.match(resUrl) + if m : # found matching route? + if rh.routeArgNames : + routeArgs = {} + for i, name in enumerate(rh.routeArgNames) : + value = m.group(i+1) + try : + value = int(value) + except : + pass + routeArgs[name] = value + return (rh.func, routeArgs) + else : + return (rh.func, None) + return (None, None) # ---------------------------------------------------------------------------- @@ -272,7 +352,7 @@ class _client : # ------------------------------------------------------------------------ def __init__(self, microWebSrv, socket, addr) : - socket.settimeout(4) + socket.settimeout(2) self._microWebSrv = microWebSrv self._socket = socket self._addr = addr @@ -285,6 +365,7 @@ def __init__(self, microWebSrv, socket, addr) : self._headers = { } self._contentType = None self._contentLength = 0 + self._processRequest() # ------------------------------------------------------------------------ @@ -296,9 +377,12 @@ def _processRequest(self) : if self._parseHeader(response) : upg = self._getConnUpgrade() if not upg : - routeHandler = self._microWebSrv.GetRouteHandler(self._resPath, self._method) + routeHandler, routeArgs = self._microWebSrv.GetRouteHandler(self._resPath, self._method) if routeHandler : - routeHandler(self, response) + if routeArgs is not None: + routeHandler(self, response, routeArgs) + else: + routeHandler(self, response) elif self._method.upper() == "GET" : filepath = self._microWebSrv._physPathFromURLPath(self._resPath) if filepath : @@ -470,6 +554,14 @@ def ReadRequestPostedFormData(self) : value = MicroWebSrv._unquote(param[1]) if len(param) > 1 else '' res[MicroWebSrv._unquote(param[0])] = value return res + + # ------------------------------------------------------------------------ + + def ReadRequestContentAsJSON(self) : + try : + return loads(self.ReadRequestContent()) + except : + return None # ============================================================================ # ===( Class Response )====================================================== @@ -485,13 +577,15 @@ def __init__(self, client) : # ------------------------------------------------------------------------ def _write(self, data) : + if type(data) == str: + data = data.encode() return self._client._socket.write(data) # ------------------------------------------------------------------------ def _writeFirstLine(self, code) : reason = self._responseCodes.get(code, ('Unknown reason', ))[0] - self._write("HTTP/1.0 %s %s\r\n" % (code, reason)) + self._write("HTTP/1.1 %s %s\r\n" % (code, reason)) # ------------------------------------------------------------------------ @@ -510,6 +604,11 @@ def _writeContentTypeHeader(self, contentType, charset=None) : # ------------------------------------------------------------------------ + def _writeServerHeader(self) : + self._writeHeader("Server", "MicroWebSrv by JC`zic") + + # ------------------------------------------------------------------------ + def _writeEndHeader(self) : self._write("\r\n") @@ -523,9 +622,9 @@ def _writeBeforeContent(self, code, headers, contentType, contentCharset, conten if contentLength > 0 : self._writeContentTypeHeader(contentType, contentCharset) self._writeHeader("Content-Length", contentLength) - self._writeHeader("Server", "MicroWebSrv by JC`zic") + self._writeServerHeader() self._writeHeader("Connection", "close") - self._writeEndHeader() + self._writeEndHeader() # ------------------------------------------------------------------------ @@ -536,6 +635,8 @@ def WriteSwitchProto(self, upgrade, headers=None) : if isinstance(headers, dict) : for header in headers : self._writeHeader(header, headers[header]) + self._writeServerHeader() + self._writeEndHeader() # ------------------------------------------------------------------------ @@ -555,9 +656,11 @@ def WriteResponsePyHTMLFile(self, filepath, headers=None) : if 'MicroWebTemplate' in globals() : with open(filepath, 'r') as file : code = file.read() - mWebTmpl = MicroWebTemplate(code, escapeStrFunc=MicroWebSrv.HTMLEscape) + gc.collect() + mWebTmpl = MicroWebTemplate(code, escapeStrFunc=MicroWebSrv.HTMLEscape, filepath=filepath) try : - return self.WriteResponseOk(headers, "text/html", "UTF-8", mWebTmpl.Execute()) + tmplResult = mWebTmpl.Execute() + return self.WriteResponse(200, headers, "text/html", "UTF-8", tmplResult) except Exception as ex : return self.WriteResponse( 500, None, @@ -609,7 +712,7 @@ def WriteResponseOk(self, headers=None, contentType=None, contentCharset=None, c # ------------------------------------------------------------------------ def WriteResponseJSONOk(self, obj=None, headers=None) : - return self.WriteResponseOk(headers, "application/json", "UTF-8", dumps(obj)) + return self.WriteResponse(200, headers, "application/json", "UTF-8", dumps(obj)) # ------------------------------------------------------------------------ diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/microWebTemplate.py b/MicroPython_BUILD/components/micropython/esp32/modules/microWebTemplate.py old mode 100644 new mode 100755 index 35dcfaf8..8ace5cad --- a/MicroPython_BUILD/components/micropython/esp32/modules/microWebTemplate.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/microWebTemplate.py @@ -1,3 +1,7 @@ +""" +The MIT License (MIT) +Copyright © 2018 Jean-Christophe Bos & HC² (www.hc2.fr) +""" import re @@ -18,14 +22,16 @@ class MicroWebTemplate : INSTRUCTION_ELSE = 'else' INSTRUCTION_FOR = 'for' INSTRUCTION_END = 'end' + INSTRUCTION_INCLUDE = 'include' # ============================================================================ # ===( Constructor )========================================================== # ============================================================================ - def __init__(self, code, escapeStrFunc=None) : + def __init__(self, code, escapeStrFunc=None, filepath='') : self._code = code self._escapeStrFunc = escapeStrFunc + self._filepath = filepath self._pos = 0 self._endPos = len(code)-1 self._line = 1 @@ -40,6 +46,7 @@ def __init__(self, code, escapeStrFunc=None) : MicroWebTemplate.INSTRUCTION_ELSE : self._processInstructionELSE, MicroWebTemplate.INSTRUCTION_FOR : self._processInstructionFOR, MicroWebTemplate.INSTRUCTION_END : self._processInstructionEND, + MicroWebTemplate.INSTRUCTION_INCLUDE: self._processInstructionINCLUDE, } # ============================================================================ @@ -81,7 +88,7 @@ def _parseBloc(self, execute) : while self._pos <= self._endPos : c = self._code[self._pos] if c == MicroWebTemplate.TOKEN_OPEN[0] and \ - self._code[ self._pos : self._pos + MicroWebTemplate.TOKEN_OPEN_LEN ] == MicroWebTemplate.TOKEN_OPEN : + self._code[ self._pos : self._pos + MicroWebTemplate.TOKEN_OPEN_LEN ] == MicroWebTemplate.TOKEN_OPEN : self._pos += MicroWebTemplate.TOKEN_OPEN_LEN tokenContent = '' x = self._pos @@ -264,7 +271,7 @@ def _processInstructionFOR(self, instructionBody, execute) : try : result = eval(expression, self._pyGlobalVars, self._pyLocalVars) except : - raise Exception('%s (line %s)' % (str(ex), self._line)) + raise Exception('%s (line %s)' % (str(expression), self._line)) if execute and len(result) > 0 : for x in result : self._pyLocalVars[identifier] = x @@ -294,6 +301,21 @@ def _processInstructionEND(self, instructionBody, execute) : % (MicroWebTemplate.INSTRUCTION_END, self._line) ) return MicroWebTemplate.INSTRUCTION_END + # ---------------------------------------------------------------------------- + + def _processInstructionINCLUDE(self, instructionBody, execute) : + if not instructionBody : + raise Exception( '"%s" alone is an incomplete syntax (line %s)' % (MicroWebTemplate.INSTRUCTION_INCLUDE, self._line) ) + filename = instructionBody.replace('"','').replace("'",'').strip() + idx = self._filepath.rindex('/') + if idx >= 0 : + filename = self._filepath[:idx+1] + filename + with open(filename, 'r') as file : + includeCode = file.read() + + self._code = self._code[:self._pos] + includeCode + self._code[self._pos:] + self._endPos += len(includeCode) + # ============================================================================ # ============================================================================ # ============================================================================ diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/upip.py b/MicroPython_BUILD/components/micropython/esp32/modules/upip.py index 7d59a90a..788df465 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules/upip.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/upip.py @@ -1,3 +1,10 @@ +# +# upip - Package manager for MicroPython +# +# Copyright (c) 2015-2018 Paul Sokolovsky +# +# Licensed under the MIT license. +# import sys import gc import uos as os @@ -5,7 +12,6 @@ import ujson as json import uzlib import upip_utarfile as tarfile -gc.collect() debug = False @@ -93,6 +99,11 @@ def install_tar(f, prefix): save_file(outfname, subf) return meta +def expandhome(s): + if "~/" in s: + h = os.getenv("HOME") + s = s.replace("~/", h + "/") + return s import ussl import usocket @@ -105,16 +116,16 @@ def url_open(url): proto, _, host, urlpath = url.split('/', 3) try: - ai = usocket.getaddrinfo(host, 443) + ai = usocket.getaddrinfo(host, 443, 0, usocket.SOCK_STREAM) except OSError as e: fatal("Unable to resolve %s (no Internet?)" % host, e) #print("Address infos:", ai) - addr = ai[0][4] + ai = ai[0] - s = usocket.socket(ai[0][0]) + s = usocket.socket(ai[0], ai[1], ai[2]) try: #print("Connect address:", addr) - s.connect(addr) + s.connect(ai[-1]) if proto == "https:": s = ussl.wrap_socket(s, server_hostname=host) @@ -144,7 +155,7 @@ def url_open(url): def get_pkg_metadata(name): - f = url_open("https://pypi.python.org/pypi/%s/json" % name) + f = url_open("https://pypi.org/pypi/%s/json" % name) try: return json.load(f) finally: @@ -181,6 +192,7 @@ def install_pkg(pkg_spec, install_path): return meta def install(to_install, install_path=None): + gc.collect() # Calculate gzip dictionary size to use global gzdict_sz sz = gc.mem_free() + gc.mem_alloc() @@ -215,12 +227,14 @@ def install(to_install, install_path=None): print("Error installing '{}': {}, packages may be partially installed".format( pkg_spec, e), file=sys.stderr) + gc.collect() def get_install_path(): global install_path if install_path is None: # sys.path[0] is current module's path install_path = sys.path[1] + install_path = expandhome(install_path) return install_path def cleanup(): diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/upysh.py b/MicroPython_BUILD/components/micropython/esp32/modules/upysh.py index a930189b..17d773b9 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules/upysh.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/upysh.py @@ -9,15 +9,66 @@ def __repr__(self): return "" def __call__(self, path="."): - l = os.listdir(path) + if path == "/": + l = os.listdir('/') + for f in l: + print(" %s" % (f)) + return + + if path == ".": + path = os.getcwd() + try: + st = os.stat(path) + except: + print("Not a directory") + return + + if not (st[0] & 0x4000): + print("Not a directory") + return + + origpath = os.getcwd() + os.chdir(path) + l = os.listdir() l.sort() + total = 0 for f in l: - st = os.stat("%s/%s" % (path, f)) + st = os.stat(f) ftime = time.strftime("%Y/%m/%d %X", time.localtime(st[8])) if st[0] & 0x4000: # stat.S_IFDIR print(" %s %s" % (ftime, f)) else: print("% 8d %s %s" % (st[6], ftime, f)) + total += st[6] + drive = os.getdrive() + if drive != "/": + stvfs = os.statvfs(drive) + if total < (10*1024): + stotal = "{} B".format(total) + elif total < (1024*1024): + stotal = "{:0.2f} KB".format(total/1024) + else: + stotal = "{:0.3f} MB".format(total/(1024*1024)) + print("\nTotal in '{}': {}".format(path, stotal)) + + dsize = stvfs[0]*stvfs[2] + dfree = stvfs[0]*stvfs[3] + if dsize < (1024*1024): + ssize = "{:0.2f} KB".format(dsize/(1024)) + elif dsize < (1024*1024*1024): + ssize = "{:0.3f} MB".format(dsize/(1024*1024)) + else: + ssize = "{:0.3f} GB".format(dsize/(1024*1024*1024)) + + if dfree < (1024*1024): + sfree = "{:0.2f} KB".format(dfree/(1024)) + elif dsize < (1024*1024*1024): + sfree = "{:0.3f} MB".format(dfree/(1024*1024)) + else: + sfree = "{:0.3f} GB".format(dfree/(1024*1024*1024)) + + print("Drive: '{}' size: {}, free: {}".format(drive, ssize, sfree)) + os.chdir(origpath) class PWD: @@ -34,10 +85,59 @@ def __repr__(self): def __call__(self): return self.__repr__() +class CP: + + def __repr__(self): + self.__call__() + return "" + + def __call__(self, srcf, destf): + if srcf == destf: + print("Destination file must be different than source") + return + try: + st = os.stat(srcf) + except: + print("'{}' not found".format(srcf)) + return + try: + st = os.stat(destf) + print("'{}' exists".format(destf)) + return + except: + pass + try: + fs = open(srcf, 'rb') + try: + fd = open(destf, 'wb') + except: + fs.close() + print("Error opening '{}'".format(srcf)) + return + try: + while True: + buf = fs.read(1024) + if len(buf) == 0: + break + else: + fd.write(buf) + except: + try: + fd.close() + os.remove(destf) + except: + pass + print("Error during copy") + fd.close() + fs.close() + except: + print("Error opening '{}'".format(srcf)) + pwd = PWD() ls = LS() clear = CLEAR() +cp = CP() cd = os.chdir mkdir = os.mkdir @@ -77,7 +177,8 @@ def __repr__(self): upysh commands: pwd, cd("new_dir"), ls, ls(...), head(...), cat(...) -newfile(...), mv("old", "new"), rm(...), mkdir(...), rmdir(...), +newfile(...), mv("old", "new"), rm(...), mkdir(...), rmdir(...) +cp("from", "to") clear """) diff --git a/MicroPython_BUILD/components/micropython/esp32/modules/urequests.py b/MicroPython_BUILD/components/micropython/esp32/modules/urequests.py index cdd5b5ff..acb220e8 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules/urequests.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules/urequests.py @@ -16,9 +16,11 @@ def close(self): @property def content(self): if self._cached is None: - self._cached = self.raw.read() - self.raw.close() - self.raw = None + try: + self._cached = self.raw.read() + finally: + self.raw.close() + self.raw = None return self._cached @property @@ -48,49 +50,58 @@ def request(method, url, data=None, json=None, headers={}, stream=None): host, port = host.split(":", 1) port = int(port) - ai = usocket.getaddrinfo(host, port) - addr = ai[0][-1] - s = usocket.socket() - s.connect(addr) - if proto == "https:": - s = ussl.wrap_socket(s, server_hostname=host) - s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) - if not "Host" in headers: - s.write(b"Host: %s\r\n" % host) - # Iterate over keys to avoid tuple alloc - for k in headers: - s.write(k) - s.write(b": ") - s.write(headers[k]) + ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) + ai = ai[0] + + s = usocket.socket(ai[0], ai[1], ai[2]) + try: + s.connect(ai[-1]) + if proto == "https:": + s = ussl.wrap_socket(s, server_hostname=host) + s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) + if not "Host" in headers: + s.write(b"Host: %s\r\n" % host) + # Iterate over keys to avoid tuple alloc + for k in headers: + s.write(k) + s.write(b": ") + s.write(headers[k]) + s.write(b"\r\n") + if json is not None: + assert data is None + import ujson + data = ujson.dumps(json) + s.write(b"Content-Type: application/json\r\n") + if data: + s.write(b"Content-Length: %d\r\n" % len(data)) s.write(b"\r\n") - if json is not None: - assert data is None - import ujson - data = ujson.dumps(json) - if data: - s.write(b"Content-Length: %d\r\n" % len(data)) - s.write(b"\r\n") - if data: - s.write(data) - - l = s.readline() - protover, status, msg = l.split(None, 2) - status = int(status) - #print(protover, status, msg) - while True: + if data: + s.write(data) + l = s.readline() - if not l or l == b"\r\n": - break #print(l) - if l.startswith(b"Transfer-Encoding:"): - if b"chunked" in l: - raise ValueError("Unsupported " + l) - elif l.startswith(b"Location:") and not 200 <= status <= 299: - raise NotImplementedError("Redirects not yet supported") + l = l.split(None, 2) + status = int(l[1]) + reason = "" + if len(l) > 2: + reason = l[2].rstrip() + while True: + l = s.readline() + if not l or l == b"\r\n": + break + #print(l) + if l.startswith(b"Transfer-Encoding:"): + if b"chunked" in l: + raise ValueError("Unsupported " + l) + elif l.startswith(b"Location:") and not 200 <= status <= 299: + raise NotImplementedError("Redirects not yet supported") + except OSError: + s.close() + raise resp = Response(s) resp.status_code = status - resp.reason = msg.rstrip() + resp.reason = reason return resp diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/drivers/ak8963.py b/MicroPython_BUILD/components/micropython/esp32/modules_examples/drivers/ak8963.py new file mode 100644 index 00000000..7eb3af70 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/drivers/ak8963.py @@ -0,0 +1,153 @@ +# +# This file is part of MicroPython MPU9250 driver +# Copyright (c) 2018 Mika Tuupola +# +# Licensed under the MIT license: +# http://www.opensource.org/licenses/mit-license.php +# +# See: +# https://github.com/tuupola/micropython-mpu9250 +# https://www.akm.com/akm/en/file/datasheet/AK8963C.pdf +# + +""" +MicroPython I2C driver for AK8963 magnetometer +""" + +__version__ = "0.2.0-dev" + +# pylint: disable=import-error +import ustruct +from machine import I2C, Pin +from micropython import const +# pylint: enable=import-error + +_WIA = const(0x00) +_HXL = const(0x03) +_HXH = const(0x04) +_HYL = const(0x05) +_HYH = const(0x06) +_HZL = const(0x07) +_HZH = const(0x08) +_ST2 = const(0x09) +_CNTL1 = const(0x0a) +_ASAX = const(0x10) +_ASAY = const(0x11) +_ASAZ = const(0x12) + +_MODE_POWER_DOWN = 0b00000000 +MODE_SINGLE_MEASURE = 0b00000001 +MODE_CONTINOUS_MEASURE_1 = 0b00000010 # 8Hz +MODE_CONTINOUS_MEASURE_2 = 0b00000110 # 100Hz +MODE_EXTERNAL_TRIGGER_MEASURE = 0b00000100 +_MODE_SELF_TEST = 0b00001000 +_MODE_FUSE_ROM_ACCESS = 0b00001111 + +OUTPUT_14_BIT = 0b00000000 +OUTPUT_16_BIT = 0b00010000 + +_SO_14BIT = 0.6 # μT per digit when 14bit mode +_SO_16BIT = 0.15 # μT per digit when 16bit mode + +class AK8963: + """Class which provides interface to AK8963 magnetometer.""" + def __init__( + self, i2c, address=0x0c, + mode=MODE_CONTINOUS_MEASURE_1, output=OUTPUT_16_BIT, + offset=(0, 0, 0), scale=(1, 1, 1) + ): + self.i2c = i2c + self.address = address + self._offset = offset + self._scale = scale + + if 0x48 != self.whoami: + raise RuntimeError("AK8963 not found in I2C bus.") + + # Sensitivity adjustement values + self._register_char(_CNTL1, _MODE_FUSE_ROM_ACCESS) + asax = self._register_char(_ASAX) + asay = self._register_char(_ASAY) + asaz = self._register_char(_ASAZ) + self._register_char(_CNTL1, _MODE_POWER_DOWN) + + # Should wait atleast 100us before next mode + self._adjustement = ( + (0.5 * (asax - 128)) / 128 + 1, + (0.5 * (asay - 128)) / 128 + 1, + (0.5 * (asaz - 128)) / 128 + 1 + ) + + # Power on + self._register_char(_CNTL1, (mode | output)) + + if output is OUTPUT_16_BIT: + self._so = _SO_16BIT + else: + self._so = _SO_14BIT + + @property + def magnetic(self): + """ + X, Y, Z axis micro-Tesla (uT) as floats. + """ + xyz = list(self._register_three_shorts(_HXL)) + self._register_char(_ST2) # Enable updating readings again + + # Apply factory axial sensitivy adjustements + xyz[0] *= self._adjustement[0] + xyz[1] *= self._adjustement[1] + xyz[2] *= self._adjustement[2] + + # Apply output scale determined in constructor + so = self._so + xyz[0] *= so + xyz[1] *= so + xyz[2] *= so + + # Apply hard iron ie. offset bias from calibration + xyz[0] -= self._offset[0] + xyz[1] -= self._offset[1] + xyz[2] -= self._offset[2] + + # Apply soft iron ie. scale bias from calibration + xyz[0] *= self._scale[0] + xyz[1] *= self._scale[1] + xyz[2] *= self._scale[2] + + return tuple(xyz) + + @property + def adjustement(self): + return self._adjustement + + @property + def whoami(self): + """ Value of the whoami register. """ + return self._register_char(_WIA) + + def _register_short(self, register, value=None, buf=bytearray(2)): + if value is None: + self.i2c.readfrom_mem_into(self.address, register, buf) + return ustruct.unpack("h", buf)[0] + + ustruct.pack_into(">h", buf, 0, value) + return self.i2c.writeto_mem(self.address, register, buf) + + def _register_three_shorts(self, register, buf=bytearray(6)): + self.i2c.readfrom_mem_into(self.address, register, buf) + return ustruct.unpack(">hhh", buf) + + def _register_char(self, register, value=None, buf=bytearray(1)): + if value is None: + self.i2c.readfrom_mem_into(self.address, register, buf) + return buf[0] + + ustruct.pack_into(" 80: + print("Not connected") + break + +# subscribe to channel +thing.subscribe(subchan) + +# subscribe to field +thing.subscribe(subfield) + +# publish to channel +# Payload can include any of those fields separated b< ';': +# "field1=value;field2=value;...;field8=value;latitude=value;longitude=value;elevation=value;status=value" +thing.publish(pubchan, "field1=25.2;status=On line") + +# Publish to field +thing.publish(pubfield, "24.5") + diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/ssd1306_spi_example.py b/MicroPython_BUILD/components/micropython/esp32/modules_examples/ssd1306_spi_example.py index 6dec2efc..41eca93b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules_examples/ssd1306_spi_example.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/ssd1306_spi_example.py @@ -6,8 +6,8 @@ pdc = machine.Pin(27, machine.Pin.OUT) pcs = machine.Pin(26, machine.Pin.OUT) sck_pin = machine.Pin(19, machine.Pin.OUT) -mosi_pin = machine.Pin(23, machine.Pin.IN) -miso_pin = machine.Pin(25, machine.Pin.OUT) +mosi_pin = machine.Pin(23, machine.Pin.OUT) +miso_pin = machine.Pin(25, machine.Pin.IN) prst = machine.Pin(18, machine.Pin.OUT) diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py b/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py index b4eee5df..d3ce4c10 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/uftpserver.py @@ -148,8 +148,8 @@ def ftpserver(timeout = 300, inthread = False, prnip = True): if prnip: print ("Starting ftp server. Version 1.2") - if not network.WLAN().isconnected(): - print("Not connected!") + if not network.WLAN().wifiactive(): + print("WiFi not started!") return DATA_PORT = 1050 diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/webserver/webserver_example.py b/MicroPython_BUILD/components/micropython/esp32/modules_examples/webserver/webserver_example.py index 047d430a..dac58dbf 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules_examples/webserver/webserver_example.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/webserver/webserver_example.py @@ -1,16 +1,40 @@ -from microWebSrv import MicroWebSrv +from microWebSrv import MicroWebSrv import _thread # set to True to print WebSocket messages WS_messages = False -# ---------------------------------------------------------------------------- +# ================================================= +# Recommended configuration: +# - run microWebServer in thread +# - do NOT run MicroWebSocket in thread +# ================================================= +# Run microWebServer in thread +srv_run_in_thread = True +# Run microWebSocket in thread +ws_run_in_thread = False + + +# ---------------------------------------------------------------------- +# To test *.pyhtml* rendered pages goto /test.pyhtml in your browser +# ---------------------------------------------------------------------- + +# ------------------------------------------------------------ +# To test websocket page goto /wstest.html in your browser +# ------------------------------------------------------------ + +# ----------------------------------------------------- +# Define microWebServer route handlers using decorators +# ----------------------------------------------------- + +# /TEST +@MicroWebSrv.route('/TEST') def _httpHandlerTestGet(httpClient, httpResponse) : content = """\ - + TEST GET @@ -32,13 +56,14 @@ def _httpHandlerTestGet(httpClient, httpResponse) : contentCharset = "UTF-8", content = content ) +@MicroWebSrv.route('/TEST', 'POST') def _httpHandlerTestPost(httpClient, httpResponse) : formData = httpClient.ReadRequestPostedFormData() firstname = formData["firstname"] lastname = formData["lastname"] content = """\ - + TEST POST @@ -56,12 +81,48 @@ def _httpHandlerTestPost(httpClient, httpResponse) : contentCharset = "UTF-8", content = content ) -# ---------------------------------------------------------------------------- +@MicroWebSrv.route('/edit/') # /edit/123 -> args['index']=123 +@MicroWebSrv.route('/edit//abc/') # /edit/123/abc/bar -> args['index']=123 args['foo']='bar' +@MicroWebSrv.route('/edit') # /edit -> args={} +def _httpHandlerEditWithArgs(httpClient, httpResponse, args={}) : + content = """\ + + + + + TEST EDIT + + + """ + content += "

EDIT item with {} variable arguments

"\ + .format(len(args)) + + if 'index' in args : + content += "

index = {}

".format(args['index']) + + if 'foo' in args : + content += "

foo = {}

".format(args['foo']) + + content += """ + + + """ + httpResponse.WriteResponseOk( headers = None, + contentType = "text/html", + contentCharset = "UTF-8", + content = content ) + +# ------------------------------------ + +# === MicroWebSocket callbacks === def _acceptWebSocketCallback(webSocket, httpClient) : if WS_messages: print("WS ACCEPT") - _thread.list() + if ws_run_in_thread or srv_run_in_thread: + # Print thread list so that we can monitor maximum stack size + # of WebServer thread and WebSocket thread if any is used + _thread.list() webSocket.RecvTextCallback = _recvTextCallback webSocket.RecvBinaryCallback = _recvBinaryCallback webSocket.ClosedCallback = _closedCallback @@ -77,30 +138,33 @@ def _recvBinaryCallback(webSocket, data) : def _closedCallback(webSocket) : if WS_messages: - _thread.list() + if ws_run_in_thread or srv_run_in_thread: + _thread.list() print("WS CLOSED") # ---------------------------------------------------------------------------- -routeHandlers = [ - ( "/test", "GET", _httpHandlerTestGet ), - ( "/test", "POST", _httpHandlerTestPost ) -] - -srv = MicroWebSrv(routeHandlers=routeHandlers) +# You can set the path to the www directory, default is '/flash/www' +#srv = MicroWebSrv(webPath='www_path') +srv = MicroWebSrv() # ------------------------------------------------------ # WebSocket configuration srv.MaxWebSocketRecvLen = 256 -# Run WebSocket in thread -srv.WebSocketThreaded = True -# If WS is running in thread, set the thread stack size -# For this example 4096 is enough, for more complex -# webSocket handling you may need to increase this size + +# Run WebSocket in thread or not +srv.WebSocketThreaded = ws_run_in_thread +# If WebSocket is running in thread, set the thread stack size +# For this example 4096 should be enough, for more complex +# webSocket handling you may need to increase this size +# If WebSocketS is NOT running in thread, and WebServer IS running in thread +# make shure WebServer has enough stack size to handle also the WebSocket requests srv.WebSocketStackSize = 4096 srv.AcceptWebSocketCallback = _acceptWebSocketCallback # ------------------------------------------------------ -srv.Start(threaded=True) +# If WebSocketS used and NOT running in thread, and WebServer IS running in thread +# make shure WebServer has enough stack size to handle also the WebSocket requests +srv.Start(threaded=srv_run_in_thread, stackSize=8192) # ---------------------------------------------------------------------------- diff --git a/MicroPython_BUILD/components/micropython/esp32/moduos.c b/MicroPython_BUILD/components/micropython/esp32/moduos.c index ed96d20f..f6078f4b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/moduos.c +++ b/MicroPython_BUILD/components/micropython/esp32/moduos.c @@ -28,10 +28,13 @@ * THE SOFTWARE. */ +#include "sdkconfig.h" + #include #include "esp_system.h" #include "esp_log.h" +#include "driver/spi_common.h" #include "py/mpconfig.h" #include "py/obj.h" @@ -41,7 +44,10 @@ #include "extmod/vfs.h" #include "mpversion.h" #include "extmod/vfs_native.h" -#include "machine_pin.h" +#include "modmachine.h" +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 2 +#include "libs/littleflash.h" +#endif //extern const mp_obj_type_t mp_fat_vfs_type; @@ -105,14 +111,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify); //------------------------------------------------------------------ STATIC mp_obj_t os_mount_sdcard(size_t n_args, const mp_obj_t *args) { - int res = -1; if (n_args > 0) { int chd = mp_obj_get_int(args[0]); if (chd) { - int res = mount_vfs(VFS_NATIVE_TYPE_SDCARD, VFS_NATIVE_EXTERNAL_MP); + mount_vfs(VFS_NATIVE_TYPE_SDCARD, VFS_NATIVE_EXTERNAL_MP); } } - else res = mount_vfs(VFS_NATIVE_TYPE_SDCARD, NULL); + else mount_vfs(VFS_NATIVE_TYPE_SDCARD, NULL); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_mount_sdcard_obj, 0, 1, os_mount_sdcard); @@ -121,11 +126,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_mount_sdcard_obj, 0, 1, os_mount_s STATIC mp_obj_t os_umount_sdcard(void) { // umount external (sdcard) file system - mp_obj_t sddir = mp_obj_new_str(VFS_NATIVE_EXTERNAL_MP, strlen(VFS_NATIVE_EXTERNAL_MP), false); + mp_obj_t sddir = mp_obj_new_str(VFS_NATIVE_EXTERNAL_MP, strlen(VFS_NATIVE_EXTERNAL_MP)); mp_call_function_1(MP_OBJ_FROM_PTR(&mp_vfs_umount_obj), sddir); // Change directory to /flash - sddir = mp_obj_new_str(VFS_NATIVE_INTERNAL_MP, strlen(VFS_NATIVE_INTERNAL_MP), false); + sddir = mp_obj_new_str(VFS_NATIVE_INTERNAL_MP, strlen(VFS_NATIVE_INTERNAL_MP)); mp_call_function_1(MP_OBJ_FROM_PTR(&mp_vfs_chdir_obj), sddir); return mp_const_none; @@ -136,11 +141,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_umount_sdcard_obj, os_umount_sdcard); STATIC mp_obj_t os_sdcard_config(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, - { MP_QSTR_clk, MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_mosi, MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_miso, MP_ARG_OBJ, { .u_obj = mp_const_none } }, - { MP_QSTR_cs, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, + { MP_QSTR_clk, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_mosi, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_miso, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_cs, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_maxspeed, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_spihost, MP_ARG_INT, { .u_int = VSPI_HOST } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -148,7 +155,7 @@ STATIC mp_obj_t os_sdcard_config(size_t n_args, const mp_obj_t *pos_args, mp_map int mode = args[0].u_int; if ((mode < 1) || (mode > 3)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported sdcard mode")); + mp_raise_ValueError("Unsupported sdcard mode"); } if (mode == 1) { int clk = machine_pin_get_gpio(args[1].u_obj); @@ -162,16 +169,49 @@ STATIC mp_obj_t os_sdcard_config(size_t n_args, const mp_obj_t *pos_args, mp_map sdcard_config.miso = miso; sdcard_config.cs = cs; sdcard_config.mode = mode; + if ((args[6].u_int != HSPI_HOST) && (args[6].u_int != VSPI_HOST)) { + mp_raise_ValueError("Unsupported SPI hots (1 (HSPI) or 2 (VSPI) allowed)"); + } + sdcard_config.host = args[6].u_int; } else { if (native_vfs_mounted[VFS_NATIVE_TYPE_SDCARD]) os_umount_sdcard(); sdcard_config.mode = mode; + sdcard_config.host = 1; + } + if (args[5].u_int >= 0) { + if ((args[5].u_int == 400) || ((args[5].u_int >= 8) && (args[5].u_int <= 40))) { + if (args[5].u_int == 400) sdcard_config.max_speed = 400; + else sdcard_config.max_speed = args[5].u_int * 1000; + } + else { + mp_raise_ValueError("Unsupported max speed (8 - 40 MHz allowed)"); + } } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(os_sdcard_config_obj, 0, os_sdcard_config); +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 2 +//---------------------------------------------------------- +STATIC mp_obj_t os_trim(size_t n_args, const mp_obj_t *args) +{ + uint32_t nblocks = 0; + int noerase = 0; + if (n_args > 0) { + nblocks = mp_obj_get_int(args[0]); + } + if (n_args > 1) { + noerase = mp_obj_get_int(args[1]); + } + uint32_t nerased = littleFlash_trim(nblocks, noerase); + + return mp_obj_new_int(nerased); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_trim_obj, 0, 2, os_trim); + +#endif //========================================================== STATIC const mp_rom_map_elem_t os_module_globals_table[] = { @@ -189,6 +229,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, + { MP_ROM_QSTR(MP_QSTR_getdrive), MP_ROM_PTR(&native_vfs_getdrive_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, @@ -198,6 +239,9 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mountsd), MP_ROM_PTR(&os_mount_sdcard_obj) }, { MP_ROM_QSTR(MP_QSTR_umountsd), MP_ROM_PTR(&os_umount_sdcard_obj) }, { MP_ROM_QSTR(MP_QSTR_sdconfig), MP_ROM_PTR(&os_sdcard_config_obj) }, + #if CONFIG_MICROPY_FILESYSTEM_TYPE == 2 + { MP_ROM_QSTR(MP_QSTR_trim), MP_ROM_PTR(&os_trim_obj) }, + #endif // Constants { MP_ROM_QSTR(MP_QSTR_SDMODE_SPI), MP_ROM_INT(1) }, { MP_ROM_QSTR(MP_QSTR_SDMODE_1LINE), MP_ROM_INT(2) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modutime.c b/MicroPython_BUILD/components/micropython/esp32/modutime.c index 71c1ab9d..de033568 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modutime.c +++ b/MicroPython_BUILD/components/micropython/esp32/modutime.c @@ -143,7 +143,7 @@ STATIC mp_obj_t time_strftime(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map strftime(str_time, 127, fmt, tm_info); - return mp_obj_new_str(str_time, strlen(str_time), false); + return mp_obj_new_str(str_time, strlen(str_time)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(time_strftime_obj, 1, time_strftime); @@ -171,7 +171,7 @@ STATIC mp_obj_t time_mktime(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t time_t seconds = mktime(&tm_inf); - return mp_obj_new_float((float)seconds); + return mp_obj_new_float((double)seconds); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(time_mktime_obj, 1, time_mktime); @@ -181,6 +181,18 @@ STATIC mp_obj_t time_ticks_base(void) { } MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_base_obj, time_ticks_base); +//--------------------------------------------------- +STATIC mp_obj_t time_block_sleep(mp_obj_t tm_sleep) { + #if MICROPY_PY_BUILTINS_FLOAT + vTaskDelay((uint32_t)(1000 * mp_obj_get_float(tm_sleep)) / portTICK_RATE_MS); + #else + uint32_t t = mp_hal_delay_ms(1000 * mp_obj_get_int(args[0])); + vTaskDelay((uint32_t)(1000 * mp_obj_get_int(tm_sleep)) / portTICK_RATE_MS); + #endif + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_block_sleep_obj, time_block_sleep); + //============================================================ STATIC const mp_rom_map_elem_t time_module_globals_table[] = { @@ -193,6 +205,7 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_strftime), MP_ROM_PTR(&time_strftime_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, + { MP_ROM_QSTR(MP_QSTR_block_sleep), MP_ROM_PTR(&mp_utime_block_sleep_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modymodem.c b/MicroPython_BUILD/components/micropython/esp32/modymodem.c index b9928c75..d181f6da 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modymodem.c +++ b/MicroPython_BUILD/components/micropython/esp32/modymodem.c @@ -96,7 +96,6 @@ static int32_t receive_Bytes (unsigned char *buf, int size, uint32_t timeout) //-------------------------------------------------------------- static int32_t Receive_Byte (unsigned char *c, uint32_t timeout) { - unsigned char ch; int cb = mp_hal_stdin_rx_chr(timeout); if (cb < 0) return -1; @@ -508,7 +507,7 @@ int Ymodem_Transmit (char* sendFileName, unsigned int sizeFile, FILE *ffd, char uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD]; uint16_t blkNumber; unsigned char receivedC; - int i, err; + int err; uint32_t size = 0; // Wait for response from receiver @@ -720,11 +719,8 @@ STATIC mp_obj_t ymodem_send(mp_obj_t fname_in) #if CONFIG_MICROPY_RX_BUFFER_SIZE > 1079 const char *fname = mp_obj_str_get_str(fname_in); int fsize = 0, err = 0; - char fullname[128] = {'\0'};; + char fullname[128] = {'\0'}; char err_msg[128] = {'\0'}; - char cwd[128] = {'\0'};; - char orig_name[128] = {'\0'}; - char *pcwd = NULL; if (physicalPath(fname, fullname) != 0) { sprintf(err_msg, "File name cannot be resolved"); @@ -750,7 +746,7 @@ STATIC mp_obj_t ymodem_send(mp_obj_t fname_in) uart0_raw_input = 1; xSemaphoreGive(uart0_mutex); - int trans_res = Ymodem_Transmit(fname, fsize, ffd, err_msg); + int trans_res = Ymodem_Transmit((char *)fname, fsize, ffd, err_msg); xSemaphoreTake(uart0_mutex, UART_SEMAPHORE_WAIT); uart0_raw_input = 0; diff --git a/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h b/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h index 8a211cd4..9169aceb 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h @@ -32,6 +32,26 @@ #include "rom/ets_sys.h" #include "sdkconfig.h" +// ------------------------------------------------------------ +// For testing only, don't change unless you want to experiment +// ------------------------------------------------------------ +// Don't use alloca calls. As alloca() is not part of ANSI C, this +// workaround option is provided for compilers lacking this de-facto +// standard function. The way it works is allocating from heap, and +// relying on garbage collection to free it eventually. This is of +// course much less optimal than real alloca(). +#define MICROPY_NO_ALLOCA (0) +// Avoid using C stack when making Python function calls. +// C stack still may be used if there's no free heap. +#define MICROPY_STACKLESS (0) +// Never use C stack when making Python function calls. +#define MICROPY_STACKLESS_STRICT (0) +// Whether to build functions that print debugging info: +// mp_bytecode_print +// mp_parse_node_print +#define MICROPY_DEBUG_PRINTERS (0) +// ------------------------------------------------------------ + // object representation and NLR handling #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) #define MICROPY_NLR_SETJMP (1) @@ -47,14 +67,29 @@ #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) -// optimisations +// optimizations #define MICROPY_OPT_COMPUTED_GOTO (1) #define MICROPY_OPT_MPZ_BITWISE (1) // Python internal features +// Whether to return number of collected objects from gc.collect() +#ifdef CONFIG_MICROPY_GC_COLLECT_RETVAL +#define MICROPY_PY_GC_COLLECT_RETVAL (1) +#else +#define MICROPY_PY_GC_COLLECT_RETVAL (0) +#endif #define MICROPY_READER_VFS (1) #define MICROPY_ENABLE_GC (1) +// Be conservative and always clear to zero newly (re)allocated memory in the GC. +// This helps eliminate stray pointers that hold on to memory that's no longer used. +// It decreases performance due to unnecessary memory clearing. +#define MICROPY_GC_CONSERVATIVE_CLEAR (1) +// Whether to enable finalisers in the garbage collector (ie call __del__) +#ifdef CONFIG_MICROPY_ENABLE_FINALISER #define MICROPY_ENABLE_FINALISER (1) +#else +#define MICROPY_ENABLE_FINALISER (0) +#endif #define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_KBD_EXCEPTION (1) @@ -78,10 +113,10 @@ #define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool #define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_USE_INTERNAL_ERRNO (1) -#define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf -#define MICROPY_PY_SYS_EXC_INFO (1) -#define MICROPY_ENABLE_SCHEDULER (1) -#define MICROPY_SCHEDULER_DEPTH (8) +#define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf, do NOT change +#define MICROPY_ENABLE_SCHEDULER (1) // Do NOT change +// Maximum number of entries in the scheduler +#define MICROPY_SCHEDULER_DEPTH (CONFIG_MICROPY_SCHEDULER_DEPTH) #define MICROPY_VFS (1) // !! DO NOT CHANGE, MUST BE 1 !! #define MICROPY_VFS_FAT (0) // !! DO NOT CHANGE, NOT USED !! @@ -89,7 +124,11 @@ // control over Python builtins #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) +#ifdef CONFIG_MICROPY_USE_UNICODE #define MICROPY_PY_BUILTINS_STR_UNICODE (1) +#else +#define MICROPY_PY_BUILTINS_STR_UNICODE (0) +#endif #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) @@ -121,6 +160,7 @@ #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_COLLECTIONS (1) +#define MICROPY_PY_COLLECTIONS_DEQUE (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) @@ -142,7 +182,8 @@ #define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_THREAD (1) #define MICROPY_PY_THREAD_GIL (1) -#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) +// Number of VM jump-loops to do before releasing the GIL. +#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR) // extended modules #define MICROPY_PY_UCTYPES (1) @@ -151,8 +192,6 @@ #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UTIMEQ (1) -#define MICROPY_PY_UHASHLIB (0) // We use the ESP32 version -#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UBINASCII_CRC32 (1) #define MICROPY_PY_URANDOM (1) @@ -165,23 +204,26 @@ #define MICROPY_PY_MACHINE_SPI_MSB (0) #define MICROPY_PY_MACHINE_SPI_LSB (1) #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new -#define MICROPY_PY_MACHINE_SPI_MIN_DELAY (0) -#define MICROPY_PY_MACHINE_SPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly #define MICROPY_PY_USSL (1) #define MICROPY_SSL_MBEDTLS (1) +#define MICROPY_PY_USSL_FINALISER (0) // Crashes on gc if enabled! +#define MICROPY_PY_UHASHLIB (0) // We use the ESP32 version +#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS) + #ifdef CONFIG_MICROPY_USE_WEBSOCKETS #define MICROPY_PY_WEBSOCKET (1) #else #define MICROPY_PY_WEBSOCKET (0) #endif -#define MICROPY_PY_OS_DUPTERM (0) -#define MICROPY_PY_WEBREPL (0) +#define MICROPY_PY_OS_DUPTERM (0) // not supported, do NOT change +#define MICROPY_PY_WEBREPL (0) // not supported, do NOT change #ifdef CONFIG_MICROPY_PY_FRAMEBUF #define MICROPY_PY_FRAMEBUF (1) #else #define MICROPY_PY_FRAMEBUF (0) #endif +#define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL) /* * Defined in 'component.mk' @@ -202,8 +244,8 @@ #endif #define MICROPY_FATFS_RPATH (2) #define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_MAX_LFN (CONFIG_FATFS_MAX_LFN) // Get from config -#define MICROPY_FATFS_LFN_CODE_PAGE (CONFIG_FATFS_CODEPAGE) // Get from config +#define MICROPY_FATFS_MAX_LFN (CONFIG_FATFS_MAX_LFN) // Get from sdkconfig +#define MICROPY_FATFS_LFN_CODE_PAGE (CONFIG_FATFS_CODEPAGE) // Get from sdkconfig #define mp_type_fileio nativefs_type_fileio #define mp_type_textio nativefs_type_textio @@ -215,12 +257,6 @@ #define MICROPY_INTERNALFS_ENCRIPTED (0) // do not use encription on filesystem #endif -#if defined(CONFIG_MICROPY_USE_SPIFFS) -#define MICROPY_USE_SPIFFS (1) // use spiffs instead of FatFS on spi Flash -#else -#define MICROPY_USE_SPIFFS (0) -#endif - // === sdcard using ESP32 sdmmc driver configuration === #ifdef CONFIG_MICROPY_SDMMC_SHOW_INFO #define MICROPY_SDMMC_SHOW_INFO (1) // show sdcard info after initialization @@ -246,6 +282,13 @@ extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t mp_module_network; extern const struct _mp_obj_module_t mp_module_ymodem; +#ifdef CONFIG_MICROPY_USE_REQUESTS +extern const struct _mp_obj_module_t mp_module_requests; +#define BUILTIN_MODULE_REQUESTS { MP_OBJ_NEW_QSTR(MP_QSTR_requests), (mp_obj_t)&mp_module_requests }, +#else +#define BUILTIN_MODULE_REQUESTS +#endif + #ifdef CONFIG_MICROPY_USE_CURL extern const struct _mp_obj_module_t mp_module_curl; #define BUILTIN_MODULE_CURL { MP_OBJ_NEW_QSTR(MP_QSTR_curl), (mp_obj_t)&mp_module_curl }, @@ -298,6 +341,7 @@ extern const struct _mp_obj_module_t mp_module_bluetooth; { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ BUILTIN_MODULE_DISPLAY \ BUILTIN_MODULE_CURL \ + BUILTIN_MODULE_REQUESTS \ BUILTIN_MODULE_SSH \ BUILTIN_MODULE_GSM \ BUILTIN_MODULE_OTA \ @@ -323,16 +367,8 @@ extern const struct _mp_obj_module_t mp_module_bluetooth; #define MP_STATE_PORT MP_STATE_VM -#if CONFIG_SPIRAM_SUPPORT -#define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[80]; \ - mp_obj_list_t mod_network_nic_list; \ - mp_obj_t machine_pin_irq_handler[40]; -#else #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[16]; \ - mp_obj_t machine_pin_irq_handler[40]; -#endif + const char *readline_hist[20]; \ // type definitions for the specific machine #define BYTES_PER_WORD (4) @@ -371,6 +407,8 @@ extern const struct _mp_obj_module_t mp_module_bluetooth; typedef int32_t mp_int_t; // must be pointer size typedef uint32_t mp_uint_t; // must be pointer size typedef long mp_off_t; +// ssize_t, off_t as required by POSIX-signatured functions in stream.h +#include // board specifics diff --git a/MicroPython_BUILD/components/micropython/esp32/mphalport.c b/MicroPython_BUILD/components/micropython/esp32/mphalport.c index 37f1dc11..186a831f 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mphalport.c +++ b/MicroPython_BUILD/components/micropython/esp32/mphalport.c @@ -36,7 +36,9 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "rom/uart.h" +#include "driver/uart.h" #include "esp_task_wdt.h" +#include "esp_log.h" #include "py/obj.h" #include "py/mpstate.h" @@ -52,16 +54,30 @@ #endif uint32_t mp_hal_wdg_rst_tmo = 0; -uint64_t mp_hal_ticks_base = 0; +RTC_DATA_ATTR uint64_t mp_hal_ticks_base; static bool stdin_disable = false; static char stdin_enable_pattern[16] = ""; +STATIC uint8_t stdin_ringbuf_array[CONFIG_MICROPY_RX_BUFFER_SIZE]; +ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; + +extern void mp_handle_pending(void); + //-------------------------------- void disableStdin(const char *pat) { snprintf(stdin_enable_pattern, 15, "%s", pat); stdin_disable = true; + char wpat[64] = {'\0'}; + char hpat[5] = {'\0'}; + for (int i=0; i<16; i++) { + if (stdin_enable_pattern[i] == 0) break; + if ((stdin_enable_pattern[i] < 0x20) || (stdin_enable_pattern[i] < 0x20)) sprintf(hpat, "\\x%02X", stdin_enable_pattern[i]); + else sprintf(hpat, "%c", stdin_enable_pattern[i]); + strcat(wpat, hpat); + } + ESP_LOGI("[stdin]", "Disabled, waiting for pattern [%s]", wpat); } //--------------------- @@ -93,9 +109,6 @@ void mp_hal_set_wdt_tmo() } -STATIC uint8_t stdin_ringbuf_array[CONFIG_MICROPY_RX_BUFFER_SIZE]; -ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0}; - // wait until at least one character is received or the timeout expires //--------------------------------------- int mp_hal_stdin_rx_chr(uint32_t timeout) @@ -119,13 +132,15 @@ int mp_hal_stdin_rx_chr(uint32_t timeout) c = ringbuf_get(&stdin_ringbuf); if (c < 0) { // no character in ring buffer - // wait 10 ms for character + // wait max 10 ms for character MP_THREAD_GIL_EXIT(); if ( xSemaphoreTake( uart0_semaphore, 10 / portTICK_PERIOD_MS ) == pdTRUE ) { + // received MP_THREAD_GIL_ENTER(); c = ringbuf_get(&stdin_ringbuf); } else { + // not received MP_THREAD_GIL_ENTER(); c = -1; } @@ -149,9 +164,15 @@ int mp_hal_stdin_rx_chr(uint32_t timeout) pattern[pattern_idx++] = c; pattern[pattern_idx] = '\0'; if (strstr(stdin_enable_pattern, pattern) == stdin_enable_pattern) { - if (strlen(stdin_enable_pattern) == strlen(pattern)) stdin_disable = false; + if (strlen(stdin_enable_pattern) == strlen(pattern)) { + // pattern received, enable stdin + stdin_disable = false; + ESP_LOGI("[stdin]", "Pattern matched, enabled"); + } } + else if (stdin_disable) pattern_idx = 0; } + if (stdin_disable) continue; return -1; } return c; @@ -161,7 +182,9 @@ int mp_hal_stdin_rx_chr(uint32_t timeout) int raw = uart0_raw_input; xSemaphoreGive(uart0_mutex); if (raw == 0) { - MICROPY_EVENT_POLL_HOOK + // check pending exception + //MICROPY_EVENT_POLL_HOOK + mp_handle_pending(); } } return -1; @@ -186,26 +209,31 @@ static void telnet_stdout_tx_str(const char *str, uint32_t len) } #endif +// send newline character to printf channel //------------------------------- void mp_hal_stdout_tx_newline() { #ifdef CONFIG_MICROPY_USE_TELNET if (telnet_loggedin()) telnet_tx_strn("\r\n", 2); - else uart_tx_one_char('\n'); + else { + uart_tx_one_char('\n'); + } #else uart_tx_one_char('\n'); #endif } +// send NULL ending string to printf channel //------------------------------------------ void mp_hal_stdout_tx_str(const char *str) { + if (str == NULL) return; #ifdef CONFIG_MICROPY_USE_TELNET if (telnet_loggedin()) telnet_tx_strn(str, strlen(str)); else { - //MP_THREAD_GIL_EXIT(); + MP_THREAD_GIL_EXIT(); while (*str) { uart_tx_one_char(*str++); } - //MP_THREAD_GIL_ENTER(); + MP_THREAD_GIL_ENTER(); } #else MP_THREAD_GIL_EXIT(); @@ -216,16 +244,18 @@ void mp_hal_stdout_tx_str(const char *str) { #endif } +// send 'len' characters from string buffer to printf channel //--------------------------------------------------------- void mp_hal_stdout_tx_strn(const char *str, uint32_t len) { + if (str == NULL) return; #ifdef CONFIG_MICROPY_USE_TELNET if (telnet_loggedin()) telnet_tx_strn(str, len); else { - //MP_THREAD_GIL_EXIT(); + MP_THREAD_GIL_EXIT(); while (len--) { uart_tx_one_char(*str++); } - //MP_THREAD_GIL_ENTER(); + MP_THREAD_GIL_ENTER(); } #else MP_THREAD_GIL_EXIT(); @@ -236,27 +266,29 @@ void mp_hal_stdout_tx_strn(const char *str, uint32_t len) { #endif } +// Efficiently convert "\n" to "\r\n" //---------------------------------------------------------------- void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) { + if (str == NULL) return; #ifdef CONFIG_MICROPY_USE_TELNET if (telnet_loggedin()) telnet_stdout_tx_str(str, len); else { - //MP_THREAD_GIL_EXIT(); + MP_THREAD_GIL_EXIT(); while (len--) { if (*str == '\n') { uart_tx_one_char('\r'); } uart_tx_one_char(*str++); } - //MP_THREAD_GIL_ENTER(); + MP_THREAD_GIL_ENTER(); } #else MP_THREAD_GIL_EXIT(); while (len--) { - if (*str == '\n') { - uart_tx_one_char('\r'); - } - uart_tx_one_char(*str++); + if (*str == '\n') { + uart_tx_one_char('\r'); + } + uart_tx_one_char(*str++); } MP_THREAD_GIL_ENTER(); #endif @@ -332,7 +364,7 @@ int mp_hal_delay_ms(uint32_t ms) gettimeofday(&tv, NULL); uint32_t tstart = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); uint32_t tend = tstart; - uint32_t nres = tstart; + uint32_t nres = tstart + (CONFIG_TASK_WDT_TIMEOUT_S * 500); MP_THREAD_GIL_EXIT(); @@ -346,9 +378,9 @@ int mp_hal_delay_ms(uint32_t ms) vTaskDelay(2); #ifdef CONFIG_MICROPY_USE_TASK_WDT - if ((tend-nres) > (CONFIG_TASK_WDT_TIMEOUT_S*500)) { + if (tend > nres) { esp_task_wdt_reset(); - nres = tend; + nres = tend + (CONFIG_TASK_WDT_TIMEOUT_S * 500); } #endif // Break if notification received @@ -369,7 +401,7 @@ void mp_hal_delay_us(uint32_t us) { if (us > 10000) { // Delay greater then 10 ms, use ms delay function uint32_t dus = us % 10000; // remaining micro seconds - mp_hal_delay_ms(us/1000); + mp_hal_delay_ms(us/10000); if (dus) ets_delay_us(dus); return; } diff --git a/MicroPython_BUILD/components/micropython/esp32/mpsleep.c b/MicroPython_BUILD/components/micropython/esp32/mpsleep.c index 57cfc3ec..6e957a54 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpsleep.c +++ b/MicroPython_BUILD/components/micropython/esp32/mpsleep.c @@ -40,7 +40,7 @@ #include "sdkconfig.h" #include "rom/rtc.h" #include "esp_system.h" -#include "esp_deep_sleep.h" +#include "esp_sleep.h" #include "esp_log.h" #include "mpsleep.h" @@ -80,20 +80,20 @@ void mpsleep_init0 (void) { } // check the wakeup reason - switch (esp_deep_sleep_get_wakeup_cause()) { - case ESP_DEEP_SLEEP_WAKEUP_EXT0: + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_EXT0: mpsleep_wake_reason = MPSLEEP_GPIO0_WAKE; break; - case ESP_DEEP_SLEEP_WAKEUP_EXT1: + case ESP_SLEEP_WAKEUP_EXT1: mpsleep_wake_reason = MPSLEEP_GPIO1_WAKE; break; - case ESP_DEEP_SLEEP_WAKEUP_TOUCHPAD: + case ESP_SLEEP_WAKEUP_TOUCHPAD: mpsleep_wake_reason = MPSLEEP_TOUCH_WAKE; break; - case ESP_DEEP_SLEEP_WAKEUP_TIMER: + case ESP_SLEEP_WAKEUP_TIMER: mpsleep_wake_reason = MPSLEEP_RTC_WAKE; break; - case ESP_DEEP_SLEEP_WAKEUP_UNDEFINED: + case ESP_SLEEP_WAKEUP_UNDEFINED: default: mpsleep_wake_reason = MPSLEEP_NONE_WAKE; break; diff --git a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c index 273d6f61..b3642f61 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c +++ b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c @@ -34,15 +34,18 @@ #include "sdkconfig.h" #include "esp_attr.h" #include "esp_log.h" +#include "soc/cpu.h" #include "py/mpstate.h" #include "py/gc.h" #include "py/mpthread.h" #include "py/mphal.h" #include "mpthreadport.h" -#include "modnetwork.h" +#include "modmachine.h" #if defined(CONFIG_MICROPY_USE_TELNET) || defined(CONFIG_MICROPY_USE_FTPSERVER) +#include "libs/libGSM.h" +#include "modnetwork.h" #include "tcpip_adapter.h" #include "esp_wifi_types.h" #include "esp_wifi.h" @@ -63,6 +66,7 @@ extern TaskHandle_t FtpTaskHandle; extern int MainTaskCore; TaskHandle_t MainTaskHandle = NULL; +TaskHandle_t ReplTaskHandle = NULL; uint8_t main_accept_msg = 1; @@ -73,8 +77,12 @@ typedef struct _thread_t { int ready; // whether the thread is ready and running void *arg; // thread Python args, a GC root pointer void *stack; // pointer to the stack + void *curr_sp; // current stack pointer + void *stack_top; // stack top StaticTask_t *tcb; // pointer to the Task Control Block size_t stack_len; // number of words in the stack + void **ptrs; // root pointers + size_t ptrs_len; // length of root pointers char name[THREAD_NAME_MAX_SIZE]; // thread name QueueHandle_t threadQueue; // queue used for inter thread communication int8_t allow_suspend; @@ -89,36 +97,43 @@ typedef struct _thread_t { // the mutex controls access to the linked list STATIC mp_thread_mutex_t thread_mutex; STATIC thread_t thread_entry0; -STATIC thread_t *thread; // root pointer, handled by mp_thread_gc_others +STATIC thread_t *thread = NULL; // root pointer, handled by mp_thread_gc_others -//------------------------------- -void vPortCleanUpTCB(void *tcb) { - thread_t *prev = NULL; - mp_thread_mutex_lock(&thread_mutex, 1); - for (thread_t *th = thread; th != NULL; prev = th, th = th->next) { - // unlink the node from the list - if (th->tcb == tcb) { - if (prev != NULL) { - prev->next = th->next; - } else { - // move the start pointer - thread = th->next; - } - // explicitly release all its memory - if (th->tcb) free(th->tcb); - if (th->stack) free(th->stack); - //m_del(thread_t, th, 1); - free(th); - break; - } - } - mp_thread_mutex_unlock(&thread_mutex); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void vPortCleanUpTCB(void *tcb) +{ + if ((MainTaskHandle) && (thread)) { + thread_t *prev = NULL; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; prev = th, th = th->next) { + // unlink the node from the list + if (th->tcb == tcb) { + if (prev != NULL) { + prev->next = th->next; + } else { + // move the start pointer + thread = th->next; + } + // explicitly release all its memory + if (th->tcb) free(th->tcb); + if (th->stack) free(th->stack); + //m_del(thread_t, th, 1); + free(th); + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); + } } // === Initialize the main MicroPython thread === -//------------------------------------------------------- -void mp_thread_preinit(void *stack, uint32_t stack_len) { +//----------------------------------------------------- +void mp_thread_preinit(void *stack, uint32_t stack_len) +{ + // Initialize threads mutex + mp_thread_mutex_init(&thread_mutex); + mp_thread_set_state(&mp_state_ctx.thread); // create first entry in linked list of all threads thread = &thread_entry0; @@ -126,6 +141,8 @@ void mp_thread_preinit(void *stack, uint32_t stack_len) { thread->ready = 1; thread->arg = NULL; thread->stack = stack; + thread->curr_sp = stack+stack_len; + thread->stack_top = stack+stack_len; thread->stack_len = stack_len; sprintf(thread->name, "MainThread"); thread->threadQueue = xQueueCreate( THREAD_QUEUE_MAX_ITEMS, sizeof(thread_msg_t) ); @@ -137,30 +154,51 @@ void mp_thread_preinit(void *stack, uint32_t stack_len) { thread->type = THREAD_TYPE_MAIN; thread->next = NULL; MainTaskHandle = thread->id; -} -//------------------------- -void mp_thread_init(void) { - mp_thread_mutex_init(&thread_mutex); } -//------------------------------ -void mp_thread_gc_others(void) { +//---------------------------------- +void mp_thread_gc_others(int flag) { mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { - if (th->type == THREAD_TYPE_SERVICE) { - continue; - } - gc_collect_root((void**)&th, 1); - gc_collect_root(&th->arg, 1); // probably not needed - if (th->id == xTaskGetCurrentTaskHandle()) { - continue; - } if (!th->ready) { continue; } - //ToDo: Check if needed - gc_collect_root(th->stack, th->stack_len); // probably not needed + if (th->type == THREAD_TYPE_SERVICE) continue; + + if (th->arg) { + #if MICROPY_PY_GC_COLLECT_RETVAL + n_marked = MP_STATE_MEM(gc_marked); + #endif + // Mark the pointers on thread arguments + gc_collect_root(&th->arg, 1); + #if MICROPY_PY_GC_COLLECT_RETVAL + if (flag) printf("th_collect: marked on arg: %d (%s)\n", MP_STATE_MEM(gc_marked) - n_marked, th->name); + #endif + } + + if (th->id == xTaskGetCurrentTaskHandle()) continue; + + #if MICROPY_PY_GC_COLLECT_RETVAL + n_marked = MP_STATE_MEM(gc_marked); + #endif + // Mark the thread root pointers + gc_collect_root(th->ptrs, th->ptrs_len); + //gc_collect_root((void**)&th, 1); + #if MICROPY_PY_GC_COLLECT_RETVAL + if (flag) printf("th_collect: marked on thrd: %d (%s)\n", MP_STATE_MEM(gc_marked) - n_marked, th->name); + #endif + + #if MICROPY_PY_GC_COLLECT_RETVAL + n_marked = MP_STATE_MEM(gc_marked); + #endif + // Mark the pointers on thread stack + gc_collect_root(th->curr_sp, (th->stack_top - th->curr_sp) / sizeof(uint32_t)); + + #if MICROPY_PY_GC_COLLECT_RETVAL + if (flag) printf("th_collect: marked on stack: %d (%s) [%p - %p]\n", + MP_STATE_MEM(gc_marked) - n_marked, th->name, th->curr_sp, th->stack_top); + #endif } mp_thread_mutex_unlock(&thread_mutex); } @@ -197,66 +235,69 @@ STATIC void freertos_entry(void *arg) { vTaskDelete(NULL); } -//------------------------------------------------------------------------------------------------------------------------------ -TaskHandle_t mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, int priority, char *name, bool same_core) +//--------------------------------------------------------------------------------------------------------------------------------- +TaskHandle_t mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *in_stack_size, int priority, char *name, bool same_core) { - // store thread entry function into a global variable so we can access it + size_t stack_size = *in_stack_size; + bool is_repl = (strcmp(name, "REPLthread") == 0); + if (is_repl) { + if (ReplTaskHandle) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "REPL thread already started")); + } + } + // store thread entry function into a global variable so we can access it ext_thread_entry = entry; // Check thread stack size - if (*stack_size == 0) { - *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; //use default stack size + if (stack_size == 0) { + stack_size = MP_THREAD_DEFAULT_STACK_SIZE; //use default stack size } else { - if (*stack_size < MP_THREAD_MIN_STACK_SIZE) *stack_size = MP_THREAD_MIN_STACK_SIZE; - else if (*stack_size > MP_THREAD_MAX_STACK_SIZE) *stack_size = MP_THREAD_MAX_STACK_SIZE; + if (stack_size < MP_THREAD_MIN_STACK_SIZE) stack_size = MP_THREAD_MIN_STACK_SIZE; + else if (stack_size > MP_THREAD_MAX_STACK_SIZE) stack_size = MP_THREAD_MAX_STACK_SIZE; } + stack_size &= 0x7FFFFFF8; - // allocate TCB, stack and linked-list node (must be outside thread_mutex lock) - //StaticTask_t *tcb = m_new(StaticTask_t, 1); - //StackType_t *stack = m_new(StackType_t, *stack_size / sizeof(StackType_t)); - - // ====================================================================== - // We are NOT going to allocate thread tcb & stack on Micropython heap - // In case we are using SPI RAM, it can produce some problems and crashes - // ====================================================================== + // === Allocate TCB, stack and linked-list node === StaticTask_t *tcb = NULL; StackType_t *stack = NULL; + thread_t *th = NULL; - tcb = malloc(sizeof(StaticTask_t)); - stack = malloc(*stack_size+256); - - //thread_t *th = m_new_obj(thread_t); - thread_t *th = (thread_t *)malloc(sizeof(thread_t)); - - mp_thread_mutex_lock(&thread_mutex, 1); + if (mpy_use_spiram) tcb = heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + else tcb = malloc(sizeof(StaticTask_t)); + if (tcb == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread (tcb)")); + } - // === Create the thread task === - #if CONFIG_MICROPY_USE_BOTH_CORES - TaskHandle_t id = xTaskCreateStatic(freertos_entry, name, *stack_size, arg, priority, stack, tcb); - #else - int run_on_core = MainTaskCore; - #if !CONFIG_FREERTOS_UNICORE - if (!same_core) run_on_core = MainTaskCore ^ 1; - #endif + if (mpy_use_spiram) stack = heap_caps_malloc((stack_size * sizeof(StackType_t))+8, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + else stack = malloc((stack_size * sizeof(StackType_t))+8);; + if (stack == NULL) { + free(tcb); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread (stack)")); + } - TaskHandle_t id = xTaskCreateStaticPinnedToCore(freertos_entry, name, *stack_size, arg, priority, stack, tcb, run_on_core); - #endif - if (id == NULL) { - mp_thread_mutex_unlock(&thread_mutex); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); + if (mpy_use_spiram) th = heap_caps_malloc(sizeof(thread_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + else th = malloc(sizeof(thread_t)); + if (th == NULL) { + free(stack); + free(tcb); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread (th)")); } + memset(th, 0, sizeof(thread_t)); + + mp_thread_mutex_lock(&thread_mutex, 1); // adjust the stack_size to provide room to recover from hitting the limit - //*stack_size -= 1024; + //stack_size -= 1024; // add thread to linked list of all threads - th->id = id; th->ready = 0; th->arg = arg; th->stack = stack; + th->curr_sp = stack+stack_size; + th->stack_top = stack+stack_size; th->tcb = tcb; - th->stack_len = *stack_size; + th->stack_len = stack_size; th->next = thread; snprintf(th->name, THREAD_NAME_MAX_SIZE, name); th->threadQueue = xQueueCreate( THREAD_QUEUE_MAX_ITEMS, sizeof(thread_msg_t) ); @@ -265,10 +306,36 @@ TaskHandle_t mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack th->waiting = 0; th->deleted = 0; th->notifyed = 0; - th->type = THREAD_TYPE_PYTHON; + if (is_repl) th->type = THREAD_TYPE_REPL; + else th->type = THREAD_TYPE_PYTHON; thread = th; - mp_thread_mutex_unlock(&thread_mutex); + // === Create and start the thread task === + #if CONFIG_MICROPY_USE_BOTH_CORES + TaskHandle_t id = xTaskCreateStatic(freertos_entry, name, stack_size, arg, priority, stack, tcb); + #else + int run_on_core = MainTaskCore; + #if !CONFIG_FREERTOS_UNICORE + if (!same_core) run_on_core = MainTaskCore ^ 1; + #endif + TaskHandle_t id = xTaskCreateStaticPinnedToCore(freertos_entry, name, stack_size, arg, priority, stack, tcb, run_on_core); + #endif + if (id == NULL) { + // Task not started, restore previous thread and clean-up + thread = th->next; + if (th->threadQueue) vQueueDelete(th->threadQueue); + free(th); + free(stack); + free(tcb); + mp_thread_mutex_unlock(&thread_mutex); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); + } + + th->id = id; + if (is_repl) ReplTaskHandle = id; + + mp_thread_mutex_unlock(&thread_mutex); + *in_stack_size = stack_size; return id; } @@ -282,9 +349,9 @@ STATIC void mp_clean_thread(thread_t *th) { if (th->threadQueue) { int n = 1; - while (n) { + while (n > 0) { n = uxQueueMessagesWaiting(th->threadQueue); - if (n) { + if (n > 0) { thread_msg_t msg; xQueueReceive(th->threadQueue, &msg, 0); if (msg.strdata != NULL) free(msg.strdata); @@ -324,24 +391,6 @@ void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { xSemaphoreGive(mutex->handle); } -// Terminate all Python threads -// used before entering sleep/reset -//--------------------------- -void mp_thread_deinit(void) { - mp_thread_mutex_lock(&thread_mutex, 1); - for (thread_t *th = thread; th != NULL; th = th->next) { - // don't delete the current task - if (th->id == xTaskGetCurrentTaskHandle()) { - continue; - } - mp_clean_thread(th); - vTaskDelete(th->id); - } - mp_thread_mutex_unlock(&thread_mutex); - // allow FreeRTOS to clean-up the threads - vTaskDelay(2); -} - //-------------------------------------- void mp_thread_allowsuspend(int allow) { mp_thread_mutex_lock(&thread_mutex, 1); @@ -414,6 +463,52 @@ int mp_thread_setblocked() { return res; } +//----------------------------------------- +int mp_thread_set_sp(void *sp, void *top) { + int res = 0; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == xTaskGetCurrentTaskHandle()) { + th->curr_sp = sp; + th->stack_top = top; + res = 1; + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); + return res; +} + +//-------------------------- +int mp_thread_get_sp(void) { + int res = 0; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == xTaskGetCurrentTaskHandle()) { + res = (uintptr_t)th->curr_sp; + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); + return res; +} + +//------------------------------------------------ +int mp_thread_set_ptrs(void **ptrs, size_t size) { + int res = 0; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == xTaskGetCurrentTaskHandle()) { + th->ptrs = ptrs; + th->ptrs_len = size; + res = 1; + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); + return res; +} + //----------------------------- int mp_thread_setnotblocked() { int res = 0; @@ -447,6 +542,17 @@ int mp_thread_notify(TaskHandle_t id, uint32_t value) { return res; } +//--------------------------- +int mp_thread_num_threads() { + int res = 0; + mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id != xTaskGetCurrentTaskHandle()) res++; + } + mp_thread_mutex_unlock(&thread_mutex); + return res; +} + //--------------------------------------------- uint32_t mp_thread_getnotify(bool check_only) { uint32_t value = 0; @@ -689,6 +795,23 @@ int mp_thread_list(thread_list_t *list) { int mp_thread_replAcceptMsg(int8_t accept) { int res = main_accept_msg; mp_thread_mutex_lock(&thread_mutex, 1); + for (thread_t *th = thread; th != NULL; th = th->next) { + if (th->id == xTaskGetCurrentTaskHandle()) { + if ((th->id == ReplTaskHandle) && (accept >= 0)) { + main_accept_msg = accept & 1; + } + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); + + return res; +} + +//------------------------------------------ +int mp_thread_mainAcceptMsg(int8_t accept) { + int res = main_accept_msg; + mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { if (th->id == xTaskGetCurrentTaskHandle()) { if ((th->id == MainTaskHandle) && (accept >= 0)) { @@ -706,26 +829,23 @@ int mp_thread_replAcceptMsg(int8_t accept) { // ===== SERVICE THREADS ============================================== #if defined(CONFIG_MICROPY_USE_TELNET) || defined(CONFIG_MICROPY_USE_FTPSERVER) -// Check if WiFi connection is available -//---------------------- -static int _check_wifi() -{ - tcpip_adapter_if_t if_type; - tcpip_adapter_ip_info_t info; - wifi_mode_t wifi_mode; - esp_wifi_get_mode(&wifi_mode); - if (wifi_mode == WIFI_MODE_AP) if_type = TCPIP_ADAPTER_IF_AP; - else if (wifi_mode == WIFI_MODE_STA) if_type = TCPIP_ADAPTER_IF_STA; - else return 2; - - tcpip_adapter_get_ip_info(if_type, &info); - if (info.ip.addr == 0) return 0; - - if ((wifi_mode == WIFI_MODE_STA) && ((!wifi_sta_isconnected) || (!wifi_sta_has_ipaddress))) return 0; - else if ((wifi_mode == WIFI_MODE_AP) && (!wifi_ap_isconnected)) return 0; - - return 1; +// Check if any network connection is available (WiFi STA and/or AP, ethernet) +//----------------------- +static bool _check_network() +{ + uint32_t ip = network_hasip(); + if (ip == 0) { + #ifdef CONFIG_MICROPY_USE_GSM + //ToDo: should we enable telnet/ftp over GSM ? + //if (ppposStatus(NULL, NULL, NULL) != GSM_STATE_CONNECTED) { + return false; + //} + #else + return false; + #endif + } + return true; } #endif @@ -733,45 +853,40 @@ static int _check_wifi() //=================================== void telnet_task (void *pvParameters) { - int res; // Initialize telnet, create rx buffer and mutex telnet_init(); - // Check if WiFi connection is available - res = _check_wifi(); - while ( res == 0) { + // Check if network connection is available + while (!_check_network()) { vTaskDelay(1000 / portTICK_PERIOD_MS); - res = _check_wifi(); + if (telnet_stop_requested()) goto exit; } - if (res == 2) goto exit; - // We have WiFi connection, enable telnet + // We have network connection, enable telnet telnet_enable(); while (1) { - res = telnet_run(); + int res = telnet_run(); if ( res < 0) { if (res == -1) { ESP_LOGD("[Telnet]", "\nRun Error"); } + // -2 is returned if Telnet stop was requested by user break; } vTaskDelay(1); - // ---- Check if WiFi is still available ---- - res = _check_wifi(); - if (res == 0) { + // ---- Check if network is still available ---- + if (!_check_network()) { bool was_enabled = telnet_isenabled(); telnet_disable(); - while ( res == 0) { + while (!_check_network()) { vTaskDelay(200 / portTICK_PERIOD_MS); - res = _check_wifi(); - if (res == 2) goto exit; + if (telnet_stop_requested()) goto exit; } if (was_enabled) telnet_enable(); } - else if (res == 2) break; // ------------------------------------------ } exit: @@ -805,54 +920,54 @@ uintptr_t mp_thread_createTelnetTask(size_t stack_size) //================================ void ftp_task (void *pvParameters) { - int res; uint64_t elapsed, time_ms = mp_hal_ticks_ms(); // Initialize ftp, create rx buffer and mutex - ftp_init(); + if (!ftp_init()) { + ESP_LOGE("[Ftp]", "Init Error"); + goto exit1; + } - res = _check_wifi(); - while ( res == 0) { + while (!_check_network()) { vTaskDelay(1000 / portTICK_PERIOD_MS); - res = _check_wifi(); + if (ftp_stop_requested()) goto exit; } - if (res == 2) goto exit; - // We have WiFi connection, enable ftp + // We have network connection, enable ftp ftp_enable(); time_ms = mp_hal_ticks_ms(); while (1) { + // Calculate time between two ftp_run() calls elapsed = mp_hal_ticks_ms() - time_ms; time_ms = mp_hal_ticks_ms(); - res = ftp_run(elapsed); + int res = ftp_run(elapsed); if (res < 0) { if (res == -1) { ESP_LOGD("[Ftp]", "\nRun Error"); } + // -2 is returned if Ftp stop was requested by user break; } vTaskDelay(1); - // ---- Check if WiFi is still available ---- - res = _check_wifi(); - if (res == 0) { + // ---- Check if network is still available ---- + if (!_check_network()) { bool was_enabled = ftp_isenabled(); ftp_disable(); - while ( res == 0) { + while (!_check_network()) { vTaskDelay(200 / portTICK_PERIOD_MS); - res = _check_wifi(); - if (res == 2) goto exit; + if (ftp_stop_requested()) goto exit; } if (was_enabled) ftp_enable(); } - else if (res == 2) break; // ------------------------------------------ } exit: ftp_disable(); ftp_deinit(); +exit1: ESP_LOGD("[Ftp]", "\nTask terminated!"); FtpTaskHandle = NULL; vSemaphoreDelete(ftp_mutex); diff --git a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h index 79a148ab..7f4ce929 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h @@ -39,6 +39,7 @@ #define THREAD_TYPE_MAIN 1 #define THREAD_TYPE_PYTHON 2 #define THREAD_TYPE_SERVICE 3 +#define THREAD_TYPE_REPL 3 // Reserved thread notification constants #define THREAD_NOTIFY_PAUSE 0x01000000 @@ -112,14 +113,16 @@ typedef struct _thread_list_t { threadlistitem_t *threads; // pointer to thread info } thread_list_t; +extern TaskHandle_t MainTaskHandle; +extern TaskHandle_t ReplTaskHandle; + thread_msg_t thread_messages[MAX_THREAD_MESSAGES]; uint8_t main_accept_msg; void mp_thread_preinit(void *stack, uint32_t stack_len); -void mp_thread_init(void); -void mp_thread_gc_others(void); -void mp_thread_deinit(void); +int mp_thread_num_threads(); +void mp_thread_gc_others(int flag); void mp_thread_allowsuspend(int allow); int mp_thread_suspend(TaskHandle_t id); @@ -132,6 +135,9 @@ int mp_thread_semdmsg(TaskHandle_t id, int type, uint32_t msg_int, uint8_t *buf, int mp_thread_getmsg(uint32_t *msg_int, uint8_t **buf, uint32_t *buflen, uint32_t *sender); int mp_thread_status(TaskHandle_t id); +int mp_thread_set_sp(void *sp, void *top); +int mp_thread_get_sp(void); +int mp_thread_set_ptrs(void **ptrs, size_t size); int mp_thread_setblocked(); int mp_thread_setnotblocked(); @@ -140,6 +146,7 @@ int mp_thread_getSelfname(char *name); int mp_thread_getname(TaskHandle_t id, char *name); int mp_thread_list(thread_list_t *list); int mp_thread_replAcceptMsg(int8_t accept); +int mp_thread_mainAcceptMsg(int8_t accept); #ifdef CONFIG_MICROPY_USE_TELNET uintptr_t mp_thread_createTelnetTask(size_t stack_size); diff --git a/MicroPython_BUILD/components/micropython/esp32/mpversion.h b/MicroPython_BUILD/components/micropython/esp32/mpversion.h index ad9b97b5..0ba73ea8 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpversion.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpversion.h @@ -24,10 +24,14 @@ * THE SOFTWARE. */ -#define MICROPY_GIT_TAG "ESP32_LoBo_v3.1.20" -#define MICROPY_GIT_HASH "g6acb38af" -#define MICROPY_BUILD_DATE "2017-02-28" +#define MICROPY_GIT_TAG "ESP32_LoBo_v3.2.24" +#define MICROPY_ESPIDF_HASH "53509c7bfde505b6d0aa5ce0cd1ac48bc3743039" +#define MICROPY_ESPIDF_VERSION "v3.1-rc1-53509c7b" +#define MICROPY_ESPIDF_DATE "2018-08-15" +#define MICROPY_BUILD_DATE "2018-09-06" #define MICROPY_VERSION_MAJOR (3) -#define MICROPY_VERSION_MINOR (1) -#define MICROPY_VERSION_MICRO (20) -#define MICROPY_VERSION_STRING "3.1.20" +#define MICROPY_VERSION_MINOR (2) +#define MICROPY_VERSION_MICRO (24) +#define MICROPY_VERSION_STRING "3.2.24" +#define MICROPY_CORE_VERSION "1b7487e" +#define MICROPY_CORE_DATE "2018-05-16" diff --git a/MicroPython_BUILD/components/micropython/esp32/network_lan.c b/MicroPython_BUILD/components/micropython/esp32/network_lan.c index c0fe8645..8693e9f0 100644 --- a/MicroPython_BUILD/components/micropython/esp32/network_lan.c +++ b/MicroPython_BUILD/components/micropython/esp32/network_lan.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2017 "Eric Poulsen" + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Based on the ESP IDF example code which is Public Domain / CC0 * @@ -28,8 +29,6 @@ #include "sdkconfig.h" -#ifdef CONFIG_MICROPY_USE_ETHERNET - #include "py/runtime.h" #include "py/mphal.h" @@ -38,8 +37,16 @@ #include "eth_phy/phy_lan8720.h" #include "tcpip_adapter.h" +#include "netutils.h" +#include "modmachine.h" #include "modnetwork.h" +bool lan_eth_active = false; + +#ifdef CONFIG_MICROPY_USE_ETHERNET + +static eth_phy_check_link_func lan_eth_link_func = NULL; + typedef struct _lan_if_obj_t { mp_obj_base_t base; int if_id; // MUST BE FIRST to match wlan_if_obj_t @@ -55,8 +62,9 @@ typedef struct _lan_if_obj_t { } lan_if_obj_t; const mp_obj_type_t lan_if_type; -STATIC lan_if_obj_t lan_obj = {{&lan_if_type}, ESP_IF_ETH, false, false}; +STATIC lan_if_obj_t lan_obj = {{&lan_if_type}, ESP_IF_ETH, false, false, 23, 18, -1, 1, 0, NULL, NULL}; +//----------------------------------------- STATIC void phy_power_enable(bool enable) { lan_if_obj_t* self = &lan_obj; @@ -85,12 +93,14 @@ STATIC void phy_power_enable(bool enable) { } } +//--------------------------- STATIC void init_lan_rmii() { lan_if_obj_t* self = &lan_obj; phy_rmii_configure_data_interface_pins(); phy_rmii_smi_configure_pins(self->mdc_pin, self->mdio_pin); } +//----------------------------------------------------------------------------------- STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { lan_if_obj_t* self = &lan_obj; @@ -98,14 +108,15 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar return MP_OBJ_FROM_PTR(&lan_obj); } - enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type }; + enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type, ARG_clk_type }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_id, MP_ARG_OBJ, { .u_obj = mp_const_none} }, + { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 1 } }, + { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = PHY_LAN8720 } }, + { MP_QSTR_clk_type, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = ETH_CLOCK_GPIO0_IN } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -117,18 +128,25 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar } } - self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj); - self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj); - self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj); + self->mdc_pin = machine_pin_get_gpio(args[ARG_mdc].u_obj); + self->mdio_pin = machine_pin_get_gpio(args[ARG_mdio].u_obj); + self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_gpio(args[ARG_power].u_obj); - if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) { + if ((args[ARG_phy_addr].u_int < 0x00) || (args[ARG_phy_addr].u_int > 0x1f)) { mp_raise_ValueError("invalid phy address"); } - if (args[ARG_phy_type].u_int != PHY_LAN8720 && args[ARG_phy_type].u_int != PHY_TLK110) { + if ((args[ARG_phy_type].u_int != PHY_LAN8720) && (args[ARG_phy_type].u_int != PHY_TLK110)) { mp_raise_ValueError("invalid phy type"); } + if ((args[ARG_clk_type].u_int < 0) || (args[ARG_clk_type].u_int > 3)) { + mp_raise_ValueError("invalid clock type"); + } + if ((mpy_use_spiram) && (args[ARG_clk_type].u_int > 1)) { + mp_raise_ValueError("clock on gpio 16 & 17 not allowed when SPIRAM is used"); + } + eth_config_t config; switch (args[ARG_phy_type].u_int) { @@ -141,11 +159,13 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar } self->link_func = config.phy_check_link; + lan_eth_link_func = config.phy_check_link; // Replace default power func with our own self->power_func = config.phy_power_enable; config.phy_power_enable = phy_power_enable; + config.clock_mode = args[ARG_clk_type].u_int; config.phy_addr = args[ARG_phy_addr].u_int; config.gpio_config = init_lan_rmii; config.tcpip_input = tcpip_adapter_eth_input; @@ -160,6 +180,7 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar } MP_DEFINE_CONST_FUN_OBJ_KW(get_lan_obj, 0, get_lan); +//--------------------------------------------------------------- STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) { lan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]); @@ -176,30 +197,53 @@ STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) { } } } + lan_eth_active = self->active; return mp_obj_new_bool(self->active); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lan_active_obj, 1, 2, lan_active); +//-------------------------------------------- STATIC mp_obj_t lan_status(mp_obj_t self_in) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_status_obj, lan_status); +//------------------------------------------------- STATIC mp_obj_t lan_isconnected(mp_obj_t self_in) { lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); return self->active ? mp_obj_new_bool(self->link_func()) : mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_isconnected_obj, lan_isconnected); + +tcpip_adapter_ip_info_t info; +tcpip_adapter_dns_info_t dns_info; + +//----------------------------------------- +STATIC mp_obj_t lan_hasip(mp_obj_t self_in) +{ + lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in); + + tcpip_adapter_ip_info_t info; + tcpip_adapter_get_ip_info(self->if_id, &info); + if (info.ip.addr == 0) return mp_const_false; + + return netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_hasip_obj, lan_hasip); + +//=========================================================== STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&lan_active_obj) }, + { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&lan_active_obj) }, { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&lan_isconnected_obj) }, - { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) }, - { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) }, + { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) }, + { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) }, + { MP_ROM_QSTR(MP_QSTR_hasip), MP_ROM_PTR(&lan_hasip_obj) }, }; STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table); +//================================= const mp_obj_type_t lan_if_type = { { &mp_type_type }, .name = MP_QSTR_LAN, diff --git a/MicroPython_BUILD/components/micropython/esp32/network_mdns.c b/MicroPython_BUILD/components/micropython/esp32/network_mdns.c index c77aa30b..fb450fe3 100644 --- a/MicroPython_BUILD/components/micropython/esp32/network_mdns.c +++ b/MicroPython_BUILD/components/micropython/esp32/network_mdns.c @@ -194,16 +194,26 @@ STATIC mp_obj_t mdns_add_service(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ } if (MP_OBJ_IS_TYPE(args[ARG_txdata].u_obj, &mp_type_dict)) { - mp_obj_dict_t *params = MP_OBJ_TO_PTR(args[ARG_txdata].u_obj); - mp_map_t *map = ¶ms->map; - mp_map_elem_t *table = map->table; - if (map->used > 0) { - for (int i=0; iused; i++) { - if (i > 7) break; - svctxdata[i].key = (char *)mp_obj_str_get_str(table[i].key); - svctxdata[i].value = (char *)mp_obj_str_get_str(table[i].value); - ntxdata++; - } + mp_obj_dict_t *dict = MP_OBJ_TO_PTR(args[ARG_txdata].u_obj); + size_t max = dict->map.alloc; + mp_map_t *map = &dict->map; + mp_map_elem_t *next; + size_t cur = 0; + while (1) { + next = NULL; + for (size_t i = cur; i < max; i++) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + cur = i + 1; + next = &(map->table[i]); + break; + } + } + if (next == NULL) break; + + svctxdata[ntxdata].key = (char *)mp_obj_str_get_str(next->key); + svctxdata[ntxdata].value = (char *)mp_obj_str_get_str(next->value); + ntxdata++; + if (ntxdata > 7) break; } } @@ -270,7 +280,7 @@ STATIC mp_obj_t mdns_host_query(mp_uint_t n_args, const mp_obj_t *pos_args, mp_m else if (res == ESP_ERR_NOT_FOUND) sprintf(tmps, "Host was not found!"); else sprintf(tmps, "Query Failed"); - return mp_obj_new_str(tmps, strlen(tmps), false);; + return mp_obj_new_str(tmps, strlen(tmps)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mdns_host_query_obj, 2, mdns_host_query); @@ -320,21 +330,21 @@ STATIC mp_obj_t mdns_service_query(mp_uint_t n_args, const mp_obj_t *pos_args, m while (r) { // Interface type sprintf(tmps, "%s", if_str[r->tcpip_if]); - t->items[0] = mp_obj_new_str(tmps, strlen(tmps), false); + t->items[0] = mp_obj_new_str(tmps, strlen(tmps)); // Protocol, V4 or V6 sprintf(tmps, "%s", ip_protocol_str[r->ip_protocol]); - t->items[1] = mp_obj_new_str(tmps, strlen(tmps), false); + t->items[1] = mp_obj_new_str(tmps, strlen(tmps)); // Instance name if (r->instance_name) sprintf(tmps, "%s", r->instance_name); else sprintf(tmps, "?"); - t->items[2] = mp_obj_new_str(tmps, strlen(tmps), false); + t->items[2] = mp_obj_new_str(tmps, strlen(tmps)); // Host name & port if(r->hostname) { sprintf(tmps, "%s.local", r->hostname); - t->items[3] = mp_obj_new_str(tmps, strlen(tmps), false); + t->items[3] = mp_obj_new_str(tmps, strlen(tmps)); t->items[4] = mp_obj_new_int(r->port); } else { @@ -353,7 +363,7 @@ STATIC mp_obj_t mdns_service_query(mp_uint_t n_args, const mp_obj_t *pos_args, m else { sprintf(tmps, IPSTR, IP2STR(&(a->addr.u_addr.ip4))); } - mp_obj_list_append(addrlist, mp_obj_new_str(tmps, strlen(tmps), false)); + mp_obj_list_append(addrlist, mp_obj_new_str(tmps, strlen(tmps))); a = a->next; } t->items[5] = addrlist; @@ -364,7 +374,7 @@ STATIC mp_obj_t mdns_service_query(mp_uint_t n_args, const mp_obj_t *pos_args, m if(r->txt_count){ mp_obj_dict_t *dct = mp_obj_new_dict(0); for(int i=0; itxt_count; i++){ - mp_obj_dict_store(dct, mp_obj_new_str(r->txt[i].key, strlen(r->txt[i].key), false), mp_obj_new_str(r->txt[i].value, strlen(r->txt[i].key), false)); + mp_obj_dict_store(dct, mp_obj_new_str(r->txt[i].key, strlen(r->txt[i].key)), mp_obj_new_str(r->txt[i].value, strlen(r->txt[i].key))); } t->items[6] = dct; } diff --git a/MicroPython_BUILD/components/micropython/esp32/uart.c b/MicroPython_BUILD/components/micropython/esp32/uart.c index a4a8d26d..0c19a839 100644 --- a/MicroPython_BUILD/components/micropython/esp32/uart.c +++ b/MicroPython_BUILD/components/micropython/esp32/uart.c @@ -6,6 +6,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,16 +40,18 @@ STATIC void uart_irq_handler(void *arg); QueueHandle_t uart0_mutex = NULL; QueueSetMemberHandle_t uart0_semaphore = NULL; int uart0_raw_input = 0; +static uart_isr_handle_t uart0_handle = NULL; //------------------ void uart_init(void) { - uart0_mutex = xSemaphoreCreateMutex(); - uart0_semaphore = xSemaphoreCreateBinary(); + if (uart0_mutex == NULL) uart0_mutex = xSemaphoreCreateMutex(); + if (uart0_semaphore == NULL) uart0_semaphore = xSemaphoreCreateBinary(); - uart_isr_handle_t handle; - uart_isr_register(UART_NUM_0, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle); - uart_enable_rx_intr(UART_NUM_0); + if (uart0_handle == NULL) { + uart_isr_register(UART_NUM_0, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &uart0_handle); + uart_enable_rx_intr(UART_NUM_0); + } } // all code executed in ISR must be in IRAM, and any const data must be in DRAM diff --git a/MicroPython_BUILD/components/micropython/esp32/uart.h b/MicroPython_BUILD/components/micropython/esp32/uart.h index 3b6ffa4a..31bdd14d 100644 --- a/MicroPython_BUILD/components/micropython/esp32/uart.h +++ b/MicroPython_BUILD/components/micropython/esp32/uart.h @@ -6,6 +6,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c b/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c index bb57a4cf..508ba67c 100644 --- a/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c +++ b/MicroPython_BUILD/components/micropython/extmod/machine_pulse.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/extmod/machine_signal.c b/MicroPython_BUILD/components/micropython/extmod/machine_signal.c index 78d0c3fe..3f9f5af9 100644 --- a/MicroPython_BUILD/components/micropython/extmod/machine_signal.c +++ b/MicroPython_BUILD/components/micropython/extmod/machine_signal.c @@ -58,7 +58,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t // If first argument isn't a Pin-like object, we filter out "invert" // from keyword arguments and pass them all to the exported Pin // constructor to create one. - mp_obj_t pin_args[n_args + n_kw * 2]; + mp_obj_t *pin_args = mp_local_alloc((n_args + n_kw * 2) * sizeof(mp_obj_t)); memcpy(pin_args, args, n_args * sizeof(mp_obj_t)); const mp_obj_t *src = args + n_args; mp_obj_t *dst = pin_args + n_args; @@ -88,6 +88,8 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t // will just ignore it as set a concrete type. If not, we'd need // to expose port's "default" pin type too. pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args); + + mp_local_free(pin_args); } else #endif diff --git a/MicroPython_BUILD/components/micropython/extmod/modbtree.c b/MicroPython_BUILD/components/micropython/extmod/modbtree.c index f509eda7..dd9e348f 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modbtree.c +++ b/MicroPython_BUILD/components/micropython/extmod/modbtree.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -282,7 +283,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in); switch (op) { - case MP_BINARY_OP_IN: { + case MP_BINARY_OP_CONTAINS: { DBT key, val; key.data = (void*)mp_obj_str_get_data(rhs_in, &key.size); int res = __bt_get(self->db, &key, &val, 0); diff --git a/MicroPython_BUILD/components/micropython/extmod/modframebuf.c b/MicroPython_BUILD/components/micropython/extmod/modframebuf.c index c9fb6821..7f809ab8 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modframebuf.c +++ b/MicroPython_BUILD/components/micropython/extmod/modframebuf.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -54,7 +55,9 @@ typedef struct _mp_framebuf_p_t { // constants for formats #define FRAMEBUF_MVLSB (0) #define FRAMEBUF_RGB565 (1) +#define FRAMEBUF_GS2_HMSB (5) #define FRAMEBUF_GS4_HMSB (2) +#define FRAMEBUF_GS8 (6) #define FRAMEBUF_MHLSB (3) #define FRAMEBUF_MHMSB (4) @@ -130,6 +133,30 @@ STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, i } } +// Functions for GS2_HMSB format + +STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { + uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2]; + uint8_t shift = (x & 0x3) << 1; + uint8_t mask = 0x3 << shift; + uint8_t color = (col & 0x3) << shift; + *pixel = color | (*pixel & (~mask)); +} + +STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { + uint8_t pixel = ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2]; + uint8_t shift = (x & 0x3) << 1; + return (pixel >> shift) & 0x3; +} + +STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { + for (int xx=x; xx < x+w; xx++) { + for (int yy=y; yy < y+h; yy++) { + gs2_hmsb_setpixel(fb, xx, yy, col); + } + } +} + // Functions for GS4_HMSB format STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { @@ -181,10 +208,31 @@ STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, } } +// Functions for GS8 format + +STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { + uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)]; + *pixel = col & 0xff; +} + +STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, int x, int y) { + return ((uint8_t*)fb->buf)[(x + y * fb->stride)]; +} + +STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) { + uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)]; + while (h--) { + memset(pixel, col, w); + pixel += fb->stride; + } +} + STATIC mp_framebuf_p_t formats[] = { [FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect}, [FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect}, + [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect}, [FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect}, + [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect}, [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, }; @@ -240,9 +288,14 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size case FRAMEBUF_MHMSB: o->stride = (o->stride + 7) & ~7; break; + case FRAMEBUF_GS2_HMSB: + o->stride = (o->stride + 3) & ~3; + break; case FRAMEBUF_GS4_HMSB: o->stride = (o->stride + 1) & ~1; break; + case FRAMEBUF_GS8: + break; default: mp_raise_ValueError("invalid format"); } @@ -579,7 +632,9 @@ STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) }, { MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) }, { MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) }, + { MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) }, { MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) }, + { MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) }, { MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) }, { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) }, }; diff --git a/MicroPython_BUILD/components/micropython/extmod/modlwip.c b/MicroPython_BUILD/components/micropython/extmod/modlwip.c index c21c809d..66410331 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modlwip.c +++ b/MicroPython_BUILD/components/micropython/extmod/modlwip.c @@ -6,6 +6,7 @@ * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Galen Hazelwood * Copyright (c) 2015-2017 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -498,6 +499,11 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui err_t err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY); + // If the output buffer is getting full then send the data to the lower layers + if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) { + err = tcp_output(socket->pcb.tcp); + } + if (err != ERR_OK) { *_errno = error_lookup_table[-err]; return MP_STREAM_ERROR; @@ -632,42 +638,6 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s return socket; } -STATIC mp_obj_t lwip_socket_close(mp_obj_t self_in) { - lwip_socket_obj_t *socket = self_in; - bool socket_is_listener = false; - - if (socket->pcb.tcp == NULL) { - return mp_const_none; - } - switch (socket->type) { - case MOD_NETWORK_SOCK_STREAM: { - if (socket->pcb.tcp->state == LISTEN) { - socket_is_listener = true; - } - if (tcp_close(socket->pcb.tcp) != ERR_OK) { - DEBUG_printf("lwip_close: had to call tcp_abort()\n"); - tcp_abort(socket->pcb.tcp); - } - break; - } - case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break; - //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; - } - socket->pcb.tcp = NULL; - socket->state = _ERR_BADF; - if (socket->incoming.pbuf != NULL) { - if (!socket_is_listener) { - pbuf_free(socket->incoming.pbuf); - } else { - tcp_abort(socket->incoming.connection); - } - socket->incoming.pbuf = NULL; - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(lwip_socket_close_obj, lwip_socket_close); - STATIC mp_obj_t lwip_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { lwip_socket_obj_t *socket = self_in; @@ -1163,7 +1133,8 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ ret |= MP_STREAM_POLL_RD; } - if (flags & MP_STREAM_POLL_WR && tcp_sndbuf(socket->pcb.tcp) > 0) { + // Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf + if (flags & MP_STREAM_POLL_WR && socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) { ret |= MP_STREAM_POLL_WR; } @@ -1172,8 +1143,47 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ // return EOF, write - error. Without this poll will hang on a // socket which was closed by peer. ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR); + } else if (socket->state == ERR_RST) { + // Socket was reset by peer, a write will return an error + ret |= flags & (MP_STREAM_POLL_WR | MP_STREAM_POLL_HUP); + } else if (socket->state < 0) { + // Socket in some other error state, use catch-all ERR flag + // TODO: may need to set other return flags here + ret |= flags & MP_STREAM_POLL_ERR; } + } else if (request == MP_STREAM_CLOSE) { + bool socket_is_listener = false; + + if (socket->pcb.tcp == NULL) { + return 0; + } + switch (socket->type) { + case MOD_NETWORK_SOCK_STREAM: { + if (socket->pcb.tcp->state == LISTEN) { + socket_is_listener = true; + } + if (tcp_close(socket->pcb.tcp) != ERR_OK) { + DEBUG_printf("lwip_close: had to call tcp_abort()\n"); + tcp_abort(socket->pcb.tcp); + } + break; + } + case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break; + //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break; + } + socket->pcb.tcp = NULL; + socket->state = _ERR_BADF; + if (socket->incoming.pbuf != NULL) { + if (!socket_is_listener) { + pbuf_free(socket->incoming.pbuf); + } else { + tcp_abort(socket->incoming.connection); + } + socket->incoming.pbuf = NULL; + } + ret = 0; + } else { *errcode = MP_EINVAL; ret = MP_STREAM_ERROR; @@ -1183,8 +1193,8 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_ } STATIC const mp_rom_map_elem_t lwip_socket_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&lwip_socket_close_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&lwip_socket_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&lwip_socket_bind_obj) }, { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&lwip_socket_listen_obj) }, { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&lwip_socket_accept_obj) }, @@ -1291,14 +1301,33 @@ STATIC void lwip_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) // lwip.getaddrinfo STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) { - if (n_args > 2) { - mp_warning("getaddrinfo constraints not supported"); - } - mp_obj_t host_in = args[0], port_in = args[1]; const char *host = mp_obj_str_get_str(host_in); mp_int_t port = mp_obj_get_int(port_in); + // If constraints were passed then check they are compatible with the supported params + if (n_args > 2) { + mp_int_t family = mp_obj_get_int(args[2]); + mp_int_t type = 0; + mp_int_t proto = 0; + mp_int_t flags = 0; + if (n_args > 3) { + type = mp_obj_get_int(args[3]); + if (n_args > 4) { + proto = mp_obj_get_int(args[4]); + if (n_args > 5) { + flags = mp_obj_get_int(args[5]); + } + } + } + if (!((family == 0 || family == MOD_NETWORK_AF_INET) + && (type == 0 || type == MOD_NETWORK_SOCK_STREAM) + && proto == 0 + && flags == 0)) { + mp_warning("unsupported getaddrinfo constraints"); + } + } + getaddrinfo_state_t state; state.status = 0; diff --git a/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c b/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c index 3fad6924..65e1ae49 100644 --- a/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c +++ b/MicroPython_BUILD/components/micropython/extmod/moduhashlib.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,7 +34,7 @@ #include "crypto-algorithms/sha256.h" #if MICROPY_PY_UHASHLIB_SHA1 -#include "lib/axtls/crypto/crypto.h" +#include "mbedtls/sha1.h" #endif typedef struct _mp_obj_hash_t { @@ -59,9 +60,10 @@ STATIC mp_obj_t sha1_update(mp_obj_t self_in, mp_obj_t arg); STATIC mp_obj_t sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(SHA1_CTX)); + mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context)); o->base.type = type; - SHA1_Init((SHA1_CTX*)o->state); + mbedtls_sha1_init((mbedtls_sha1_context*)o->state); + mbedtls_sha1_starts((mbedtls_sha1_context*)o->state); if (n_args == 1) { sha1_update(MP_OBJ_FROM_PTR(o), args[0]); } @@ -83,7 +85,7 @@ STATIC mp_obj_t sha1_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); - SHA1_Update((SHA1_CTX*)self->state, bufinfo.buf, bufinfo.len); + mbedtls_sha1_update((mbedtls_sha1_context*)self->state, bufinfo.buf, bufinfo.len); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(sha1_update_obj, sha1_update); @@ -102,8 +104,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(hash_digest_obj, hash_digest); STATIC mp_obj_t sha1_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; - vstr_init_len(&vstr, SHA1_SIZE); - SHA1_Final((byte*)vstr.buf, (SHA1_CTX*)self->state); + vstr_init_len(&vstr, 20); + mbedtls_sha1_finish((mbedtls_sha1_context*)self->state, (byte*)vstr.buf); + mbedtls_sha1_free((mbedtls_sha1_context*)self->state); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } MP_DEFINE_CONST_FUN_OBJ_1(sha1_digest_obj, sha1_digest); diff --git a/MicroPython_BUILD/components/micropython/extmod/modujson.c b/MicroPython_BUILD/components/micropython/extmod/modujson.c index f14682d2..f731d719 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modujson.c +++ b/MicroPython_BUILD/components/micropython/extmod/modujson.c @@ -34,6 +34,16 @@ #if MICROPY_PY_UJSON +STATIC mp_obj_t mod_ujson_dump(mp_obj_t obj, mp_obj_t stream) { + if (!MP_OBJ_IS_OBJ(stream)) { + mp_raise_TypeError(NULL); + } + mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor}; + mp_obj_print_helper(&print, obj, PRINT_JSON); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ujson_dump_obj, mod_ujson_dump); + STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { vstr_t vstr; mp_print_t print; @@ -166,7 +176,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { goto fail; } S_NEXT(s); - next = mp_obj_new_str(vstr.buf, vstr.len, false); + next = mp_obj_new_str(vstr.buf, vstr.len); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { @@ -283,6 +293,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads); STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) }, + { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_ujson_dump_obj) }, { MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) }, { MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) }, { MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_ujson_loads_obj) }, diff --git a/MicroPython_BUILD/components/micropython/extmod/modure.c b/MicroPython_BUILD/components/micropython/extmod/modure.c index 78de4706..31c2b986 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modure.c +++ b/MicroPython_BUILD/components/micropython/extmod/modure.c @@ -144,7 +144,7 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) { } mp_obj_t retval = mp_obj_new_list(0, NULL); - const char **caps = alloca(caps_num * sizeof(char*)); + const char **caps = mp_local_alloc(caps_num * sizeof(char*)); while (true) { // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char memset((char**)caps, 0, caps_num * sizeof(char*)); @@ -165,6 +165,8 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) { break; } } + // cast is a workaround for a bug in msvc (see above) + mp_local_free((char**)caps); mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte*)subj.begin, subj.end - subj.begin); mp_obj_list_append(retval, s); diff --git a/MicroPython_BUILD/components/micropython/extmod/moduselect.c b/MicroPython_BUILD/components/micropython/extmod/moduselect.c index dfb5097b..bfdabf2a 100644 --- a/MicroPython_BUILD/components/micropython/extmod/moduselect.c +++ b/MicroPython_BUILD/components/micropython/extmod/moduselect.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -129,7 +130,7 @@ STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) { timeout = (mp_uint_t)(timeout_f * 1000); } #else - timeout = mp_obj_get_int(args[3]) * 1000; + timeout = mp_obj_get_int64(args[3]) * 1000; #endif } } @@ -232,7 +233,7 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { int flags = 0; if (n_args >= 2) { if (args[1] != mp_const_none) { - int64_t timeout_i = mp_obj_get_int(args[1]); + int64_t timeout_i = mp_obj_get_int64(args[1]); if (timeout_i >= 0) { timeout = timeout_i; } diff --git a/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c b/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c index 375c648d..9a5375f8 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c +++ b/MicroPython_BUILD/components/micropython/extmod/modussl_mbedtls.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Linaro Ltd. + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -279,20 +280,26 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); -STATIC mp_obj_t socket_close(mp_obj_t self_in) { - mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); - - mbedtls_pk_free(&self->pkey); - mbedtls_x509_crt_free(&self->cert); - mbedtls_x509_crt_free(&self->cacert); - mbedtls_ssl_free(&self->ssl); - mbedtls_ssl_config_free(&self->conf); - mbedtls_ctr_drbg_free(&self->ctr_drbg); - mbedtls_entropy_free(&self->entropy); - - return mp_stream_close(self->sock); +STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { + mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in); + (void)arg; + switch (request) { + case MP_STREAM_CLOSE: + mbedtls_pk_free(&self->pkey); + mbedtls_x509_crt_free(&self->cert); + mbedtls_x509_crt_free(&self->cacert); + mbedtls_ssl_free(&self->ssl); + mbedtls_ssl_config_free(&self->conf); + mbedtls_ctr_drbg_free(&self->ctr_drbg); + mbedtls_entropy_free(&self->entropy); + mp_stream_close(self->sock); + return 0; + + default: + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, @@ -300,9 +307,9 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, #if MICROPY_PY_USSL_FINALISER - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&socket_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, #endif { MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) }, }; @@ -312,6 +319,7 @@ STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_tab STATIC const mp_stream_p_t ussl_socket_stream_p = { .read = socket_read, .write = socket_write, + .ioctl = socket_ioctl, }; STATIC const mp_obj_type_t ussl_socket_type = { diff --git a/MicroPython_BUILD/components/micropython/extmod/modutimeq.c b/MicroPython_BUILD/components/micropython/extmod/modutimeq.c index 0c07ae94..8e4445e0 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modutimeq.c +++ b/MicroPython_BUILD/components/micropython/extmod/modutimeq.c @@ -1,10 +1,11 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * * Copyright (c) 2014 Damien P. George * Copyright (c) 2016-2017 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,21 +27,15 @@ */ #include - +#include #include "py/objlist.h" #include "py/runtime.h" #include "py/smallint.h" #if MICROPY_PY_UTIMEQ -#define MODULO MICROPY_PY_UTIME_TICKS_PERIOD - -#define DEBUG 0 - -// the algorithm here is modeled on CPython's heapq.py - struct qentry { - mp_uint_t time; + int64_t time; mp_uint_t id; mp_obj_t callback; mp_obj_t args; @@ -50,75 +45,59 @@ typedef struct _mp_obj_utimeq_t { mp_obj_base_t base; mp_uint_t alloc; mp_uint_t len; + bool ascending; struct qentry items[]; } mp_obj_utimeq_t; -STATIC mp_uint_t utimeq_id; +STATIC mp_uint_t utimeq_id = 0; +STATIC bool sort_asc = true; +//-------------------------------------------------- STATIC mp_obj_utimeq_t *get_heap(mp_obj_t heap_in) { return MP_OBJ_TO_PTR(heap_in); } -STATIC bool time_less_than(struct qentry *item, struct qentry *parent) { - mp_uint_t item_tm = item->time; - mp_uint_t parent_tm = parent->time; - mp_uint_t res = parent_tm - item_tm; +//---------------------------------------------------------------- +STATIC int compare_times(const void * item, const void * parent) { + int ret = 0; + int64_t res = ((struct qentry *)parent)->time - ((struct qentry *)item)->time; + ret = (res < 0) ? -1 : 1; if (res == 0) { - // TODO: This actually should use the same "ring" logic - // as for time, to avoid artifacts when id's overflow. - return item->id < parent->id; - } - if ((mp_int_t)res < 0) { - res += MODULO; + ret = (((struct qentry *)parent)->id - ((struct qentry *)item)->id); } - return res && res < (MODULO / 2); + if (sort_asc) ret *= -1; + + return ret; } -STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 1, 1, false); - mp_uint_t alloc = mp_obj_get_int(args[0]); +//--------------------------------------------- +STATIC void sort_items(mp_obj_utimeq_t *heap) { + sort_asc = heap->ascending; + qsort(&heap->items, heap->len, sizeof(struct qentry), compare_times); +} + +//---------------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_size, ARG_sort }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_size, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none}}, + { MP_QSTR_asc, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true}}, + }; + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_arg_check_num(n_args, n_kw, 1, 1, true); + + mp_uint_t alloc = mp_obj_get_int(args[ARG_size].u_obj); mp_obj_utimeq_t *o = m_new_obj_var(mp_obj_utimeq_t, struct qentry, alloc); o->base.type = type; memset(o->items, 0, sizeof(*o->items) * alloc); o->alloc = alloc; o->len = 0; - return MP_OBJ_FROM_PTR(o); -} + o->ascending = args[ARG_sort].u_bool; -STATIC void heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) { - struct qentry item = heap->items[pos]; - while (pos > start_pos) { - mp_uint_t parent_pos = (pos - 1) >> 1; - struct qentry *parent = &heap->items[parent_pos]; - bool lessthan = time_less_than(&item, parent); - if (lessthan) { - heap->items[pos] = *parent; - pos = parent_pos; - } else { - break; - } - } - heap->items[pos] = item; -} - -STATIC void heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) { - mp_uint_t start_pos = pos; - mp_uint_t end_pos = heap->len; - struct qentry item = heap->items[pos]; - for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) { - // choose right child if it's <= left child - if (child_pos + 1 < end_pos) { - bool lessthan = time_less_than(&heap->items[child_pos], &heap->items[child_pos + 1]); - if (!lessthan) { - child_pos += 1; - } - } - // bubble up the smaller child - heap->items[pos] = heap->items[child_pos]; - pos = child_pos; - } - heap->items[pos] = item; - heap_siftdown(heap, start_pos, pos); + return MP_OBJ_FROM_PTR(o); } //------------------------------------------------------------------------ @@ -130,19 +109,23 @@ STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) { mp_raise_msg(&mp_type_IndexError, "queue overflow"); } mp_uint_t l = heap->len; - mp_uint_t itime; + // time argument can be float or integer + // if float, convert it to 64-bit integer + int64_t itime; if (mp_obj_is_float(args[1])) { mp_float_t time = mp_obj_float_get(args[1]); - itime = (uint32_t)time; + itime = (int64_t)(round(time)); } - else itime = mp_obj_get_int(args[1]); + else itime = mp_obj_get_int64(args[1]); heap->items[l].time = itime; heap->items[l].id = utimeq_id++; heap->items[l].callback = args[2]; heap->items[l].args = args[3]; - heap_siftdown(heap, 0, heap->len); heap->len++; + + sort_items(heap); + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_heappush_obj, 4, 4, mod_utimeq_heappush); @@ -159,44 +142,100 @@ STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) { } struct qentry *item = &heap->items[0]; - ret->items[0] = mp_obj_new_int(item->time); + ret->items[0] = mp_obj_new_int_from_ll(item->time); ret->items[1] = item->callback; ret->items[2] = item->args; + heap->len -= 1; - heap->items[0] = heap->items[heap->len]; - heap->items[heap->len].callback = MP_OBJ_NULL; // so we don't retain a pointer - heap->items[heap->len].args = MP_OBJ_NULL; + if (heap->len) { - heap_siftup(heap, 0); + memmove(&heap->items[0], &heap->items[1], sizeof(struct qentry) * heap->len); + //sort_items(heap); + // we don't want to retain a pointers ! + memset(&heap->items[heap->len], 0, sizeof(struct qentry)); } + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop); -//----------------------------------------------------- -STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) { +//----------------------------------------------------------------------------------------- +STATIC mp_obj_t mod_utimeq_heappeek(mp_obj_t heap_in, mp_obj_t idx_in, mp_obj_t list_ref) { mp_obj_utimeq_t *heap = get_heap(heap_in); if (heap->len == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); } + int pos = mp_obj_get_int(idx_in); + if ((pos < 0) || (pos >= heap->len)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "wrong heap index")); + } + mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref); + if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 3) { + mp_raise_TypeError(NULL); + } - struct qentry *item = &heap->items[0]; - return mp_obj_new_int(item->time); + struct qentry *item = &heap->items[pos]; + ret->items[0] = mp_obj_new_int_from_ll(item->time); + ret->items[1] = item->callback; + ret->items[2] = item->args; + + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_peektime_obj, mod_utimeq_peektime); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_utimeq_heappeek_obj, mod_utimeq_heappeek); + +//------------------------------------------------------------------------ +STATIC mp_obj_t mod_utimeq_peektime(size_t n_args, const mp_obj_t *args) { + mp_obj_utimeq_t *heap = get_heap(args[0]); + if (heap->len == 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap")); + } -#if DEBUG -STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) { + int pos = 0; + if (n_args == 2) { + pos = mp_obj_get_int(args[1]); + if ((pos < 0) || (pos >= heap->len)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "wrong heap index")); + } + } + struct qentry *item = &heap->items[pos]; + return mp_obj_new_int_from_ll(item->time); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_peektime_obj, 1, 2, mod_utimeq_peektime); + +//------------------------------------------------ +STATIC mp_obj_t mod_utimeq_len(mp_obj_t heap_in) { mp_obj_utimeq_t *heap = get_heap(heap_in); - for (int i = 0; i < heap->len; i++) { - printf(UINT_FMT "\t%p\t%p\n", heap->items[i].time, + mp_obj_tuple_t *t = mp_obj_new_tuple(2, NULL); + + t->items[0] = mp_obj_new_int(heap->len); + t->items[1] = mp_obj_new_int(heap->alloc); + + return t; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_len_obj, mod_utimeq_len); + +//-------------------------------------------------------------------- +STATIC mp_obj_t mod_utimeq_dump(size_t n_args, const mp_obj_t *args) { + mp_obj_utimeq_t *heap = get_heap(args[0]); + + int maxlen = heap->len; + if (n_args == 2) { + if ( mp_obj_is_true(args[1])) maxlen = heap->alloc; + } + printf("%4s%21s%10s%12s%12s\n", "Idx", "Time", "ID", "Callback", "Arg"); + printf("-----------------------------------------------------------\n"); + for (int i = 0; i < maxlen; i++) { + printf("%4d%21lld%10u%12p%12p", i, heap->items[i].time, heap->items[i].id, MP_OBJ_TO_PTR(heap->items[i].callback), MP_OBJ_TO_PTR(heap->items[i].args)); + if (i >= heap->len) printf(" (empty)\n"); + else printf("\n"); } + printf("-----------------------------------------------------------\n"); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_dump_obj, mod_utimeq_dump); -#endif +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_dump_obj, 1, 2, mod_utimeq_dump); +//------------------------------------------------------------------- STATIC mp_obj_t utimeq_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_utimeq_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { @@ -206,17 +245,18 @@ STATIC mp_obj_t utimeq_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } +//=========================================================== STATIC const mp_rom_map_elem_t utimeq_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&mod_utimeq_heappush_obj) }, - { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&mod_utimeq_heappop_obj) }, + { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&mod_utimeq_heappush_obj) }, + { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&mod_utimeq_heappop_obj) }, + { MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&mod_utimeq_heappeek_obj) }, { MP_ROM_QSTR(MP_QSTR_peektime), MP_ROM_PTR(&mod_utimeq_peektime_obj) }, - #if DEBUG - { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_utimeq_dump_obj) }, - #endif + { MP_ROM_QSTR(MP_QSTR_len), MP_ROM_PTR(&mod_utimeq_len_obj) }, + { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_utimeq_dump_obj) }, }; - STATIC MP_DEFINE_CONST_DICT(utimeq_locals_dict, utimeq_locals_dict_table); +//======================================== STATIC const mp_obj_type_t utimeq_type = { { &mp_type_type }, .name = MP_QSTR_utimeq, @@ -225,13 +265,14 @@ STATIC const mp_obj_type_t utimeq_type = { .locals_dict = (void*)&utimeq_locals_dict, }; +//================================================================= STATIC const mp_rom_map_elem_t mp_module_utimeq_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utimeq) }, - { MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&utimeq_type) }, + { MP_ROM_QSTR(MP_QSTR_utimeq), MP_ROM_PTR(&utimeq_type) }, }; - STATIC MP_DEFINE_CONST_DICT(mp_module_utimeq_globals, mp_module_utimeq_globals_table); +//======================================== const mp_obj_module_t mp_module_utimeq = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&mp_module_utimeq_globals, diff --git a/MicroPython_BUILD/components/micropython/extmod/modwebsocket.c b/MicroPython_BUILD/components/micropython/extmod/modwebsocket.c index a651164b..5a826ec6 100644 --- a/MicroPython_BUILD/components/micropython/extmod/modwebsocket.c +++ b/MicroPython_BUILD/components/micropython/extmod/modwebsocket.c @@ -256,6 +256,11 @@ STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in); switch (request) { + case MP_STREAM_CLOSE: + // TODO: Send close signaling to the other side, otherwise it's + // abrupt close (connection abort). + mp_stream_close(self->sock); + return 0; case MP_STREAM_GET_DATA_OPTS: return self->ws_flags & FRAME_OPCODE_MASK; case MP_STREAM_SET_DATA_OPTS: { @@ -269,21 +274,13 @@ STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t } } -STATIC mp_obj_t websocket_close(mp_obj_t self_in) { - mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in); - // TODO: Send close signaling to the other side, otherwise it's - // abrupt close (connection abort). - return mp_stream_close(self->sock); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(websocket_close_obj, websocket_close); - STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&websocket_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table); diff --git a/MicroPython_BUILD/components/micropython/extmod/re1.5/compilecode.c b/MicroPython_BUILD/components/micropython/extmod/re1.5/compilecode.c index 3267a419..a685a508 100644 --- a/MicroPython_BUILD/components/micropython/extmod/re1.5/compilecode.c +++ b/MicroPython_BUILD/components/micropython/extmod/re1.5/compilecode.c @@ -5,9 +5,9 @@ #include "re1.5.h" #define INSERT_CODE(at, num, pc) \ - ((code ? memmove(code + at + num, code + at, pc - at) : (void)0), pc += num) + ((code ? memmove(code + at + num, code + at, pc - at) : 0), pc += num) #define REL(at, to) (to - at - 2) -#define EMIT(at, byte) (code ? (code[at] = byte) : (void)(at)) +#define EMIT(at, byte) (code ? (code[at] = byte) : (at)) #define PC (prog->bytelen) static const char *_compilecode(const char *re, ByteProg *prog, int sizecode) diff --git a/MicroPython_BUILD/components/micropython/extmod/uos_dupterm.c b/MicroPython_BUILD/components/micropython/extmod/uos_dupterm.c deleted file mode 100644 index f77cff57..00000000 --- a/MicroPython_BUILD/components/micropython/extmod/uos_dupterm.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Paul Sokolovsky - * Copyright (c) 2017 Damien P. George - * - * 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 -#include "py/mpconfig.h" - -#include "py/runtime.h" -#include "py/objtuple.h" -#include "py/objarray.h" -#include "py/stream.h" -#include "lib/utils/interrupt_char.h" - -#if MICROPY_PY_OS_DUPTERM - -void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) { - mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]); - MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL; - mp_printf(&mp_plat_print, msg); - if (exc != MP_OBJ_NULL) { - mp_obj_print_exception(&mp_plat_print, exc); - } - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_stream_close(term); - nlr_pop(); - } else { - // Ignore any errors during stream closing - } -} - -int mp_uos_dupterm_rx_chr(void) { - for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { - if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) { - continue; - } - - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_obj_t readinto_m[3]; - mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_readinto, readinto_m); - readinto_m[2] = MP_STATE_VM(dupterm_arr_obj); - mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m); - if (res == mp_const_none) { - nlr_pop(); - } else if (res == MP_OBJ_NEW_SMALL_INT(0)) { - nlr_pop(); - mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL); - } else { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(MP_STATE_VM(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ); - nlr_pop(); - if (*(byte*)bufinfo.buf == mp_interrupt_char) { - // Signal keyboard interrupt to be raised as soon as the VM resumes - mp_keyboard_interrupt(); - return -2; - } - return *(byte*)bufinfo.buf; - } - } else { - mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val); - } - } - - // No chars available - return -1; -} - -void mp_uos_dupterm_tx_strn(const char *str, size_t len) { - for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) { - if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) { - continue; - } - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_obj_t write_m[3]; - mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_write, write_m); - - mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj)); - void *org_items = arr->items; - arr->items = (void*)str; - arr->len = len; - write_m[2] = MP_STATE_VM(dupterm_arr_obj); - mp_call_method_n_kw(1, 0, write_m); - arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj)); - arr->items = org_items; - arr->len = 1; - nlr_pop(); - } else { - mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val); - } - } -} - -STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) { - mp_int_t idx = 0; - if (n_args == 2) { - idx = mp_obj_get_int(args[1]); - } - - if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) { - mp_raise_ValueError("invalid dupterm index"); - } - - mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]); - if (previous_obj == MP_OBJ_NULL) { - previous_obj = mp_const_none; - } - if (args[0] == mp_const_none) { - MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL; - } else { - MP_STATE_VM(dupterm_objs[idx]) = args[0]; - if (MP_STATE_VM(dupterm_arr_obj) == MP_OBJ_NULL) { - MP_STATE_VM(dupterm_arr_obj) = mp_obj_new_bytearray(1, ""); - } - } - - return previous_obj; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm); - -#endif diff --git a/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c index db7906c1..d536e648 100644 --- a/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c +++ b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.c @@ -5,6 +5,7 @@ * * Copyright (c) 2013-2016 Damien P. George * Copyright (c) 2016 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,6 +37,7 @@ #include "py/runtime.h" #include "extmod/utime_mphal.h" +// Sleep for number of seconds (given as float) //------------------------------------------------------------------ STATIC mp_obj_t time_sleep(mp_uint_t n_args, const mp_obj_t *args) { #if MICROPY_PY_BUILTINS_FLOAT @@ -54,6 +56,8 @@ STATIC mp_obj_t time_sleep(mp_uint_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_utime_sleep_obj, 1, 2, time_sleep); +// Sleep for number of milliseconds (given as integer) +// If the 2nd (optional) argument is set to True, return actual number of sleep ms //--------------------------------------------------------------------- STATIC mp_obj_t time_sleep_ms(mp_uint_t n_args, const mp_obj_t *args) { mp_int_t ms = mp_obj_get_int(args[0]); @@ -65,6 +69,7 @@ STATIC mp_obj_t time_sleep_ms(mp_uint_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_utime_sleep_ms_obj, 1, 2, time_sleep_ms); +// Sleep for number of microseconds (given as integer) //------------------------------------------- STATIC mp_obj_t time_sleep_us(mp_obj_t arg) { mp_int_t us = mp_obj_get_int(arg); @@ -75,7 +80,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us); //----------------------------------- STATIC mp_obj_t time_ticks_ms(void) { - return mp_obj_new_int_from_ull(mp_hal_ticks_ms()); + return mp_obj_new_int_from_ull(mp_hal_ticks_ms()); } MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms); @@ -102,7 +107,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff); //---------------------------------------------------------------------- STATIC mp_obj_t time_tickscpu_diff(mp_obj_t end_in, mp_obj_t start_in) { - // we assume that the arguments come from ticks_xx so are small ints + // we assume that the arguments come from ticks_cpu so are small integers mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in); mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in); // Optimized formula avoiding if conditions. We adjust difference "forward", @@ -115,7 +120,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_tickscpu_diff_obj, time_tickscpu_diff); //-------------------------------------------------------------------- STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { - // we assume that first argument come from ticks_xx so is 64-bit int + // both arguments can be 64-bit integers uint64_t tickin = mp_obj_get_int64(ticks_in); uint64_t delta = mp_obj_get_int64(delta_in); int64_t addtick = tickin + delta; diff --git a/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h index bc517e96..acb1b78d 100644 --- a/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h +++ b/MicroPython_BUILD/components/micropython/extmod/utime_mphal.h @@ -5,6 +5,7 @@ * * Copyright (c) 2013-2016 Damien P. George * Copyright (c) 2016 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/extmod/uzlib/tinflate.c b/MicroPython_BUILD/components/micropython/extmod/uzlib/tinflate.c index 58850eb4..21558af5 100644 --- a/MicroPython_BUILD/components/micropython/extmod/uzlib/tinflate.c +++ b/MicroPython_BUILD/components/micropython/extmod/uzlib/tinflate.c @@ -394,9 +394,11 @@ static int tinf_inflate_uncompressed_block(TINF_DATA *d) unsigned int length, invlength; /* get length */ - length = uzlib_get_byte(d) + 256 * uzlib_get_byte(d); + length = uzlib_get_byte(d); + length += 256 * uzlib_get_byte(d); /* get one's complement of length */ - invlength = uzlib_get_byte(d) + 256 * uzlib_get_byte(d); + invlength = uzlib_get_byte(d); + invlength += 256 * uzlib_get_byte(d); /* check length */ if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs.c b/MicroPython_BUILD/components/micropython/extmod/vfs.c index 64fef2e0..5de21f55 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs.c +++ b/MicroPython_BUILD/components/micropython/extmod/vfs.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2017 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -126,8 +127,26 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) { if (mp_obj_get_type(vfs->obj) == &mp_native_vfs_type) { return native_vfs_import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out); } - // TODO delegate to vfs.stat() method - return MP_IMPORT_STAT_NO_EXIST; + + // delegate to vfs.stat() method + mp_obj_t path_o = mp_obj_new_str(path_out, strlen(path_out)); + mp_obj_t stat; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + stat = mp_vfs_proxy_call(vfs, MP_QSTR_stat, 1, &path_o); + nlr_pop(); + } else { + // assume an exception means that the path is not found + return MP_IMPORT_STAT_NO_EXIST; + } + mp_obj_t *items; + mp_obj_get_array_fixed_n(stat, 10, &items); + mp_int_t st_mode = mp_obj_get_int(items[0]); + if (st_mode & MP_S_IFDIR) { + return MP_IMPORT_STAT_DIR; + } else { + return MP_IMPORT_STAT_FILE; + } } mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -257,7 +276,7 @@ mp_obj_t mp_vfs_chdir(mp_obj_t path_in) { // subsequent relative paths begin at the root of that VFS. for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { if (vfs->len == 1) { - mp_obj_t root = mp_obj_new_str("/", 1, false); + mp_obj_t root = MP_OBJ_NEW_QSTR(MP_QSTR__slash_); mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &root); break; } @@ -314,7 +333,7 @@ STATIC mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) { self->cur.vfs = vfs->next; if (vfs->len == 1) { // vfs is mounted at root dir, delegate to it - mp_obj_t root = mp_obj_new_str("/", 1, false); + mp_obj_t root = MP_OBJ_NEW_QSTR(MP_QSTR__slash_); self->is_iter = true; self->cur.iter = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &root); return mp_iternext(self->cur.iter); @@ -362,9 +381,7 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) { mp_obj_t dir_list = mp_obj_new_list(0, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { - mp_obj_t *items; - mp_obj_get_array_fixed_n(next, 3, &items); - mp_obj_list_append(dir_list, items[0]); + mp_obj_list_append(dir_list, mp_obj_subscr(next, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL)); } return dir_list; } diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native.c b/MicroPython_BUILD/components/micropython/extmod/vfs_native.c index a76180af..64029e23 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs_native.c +++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native.c @@ -52,7 +52,8 @@ #include "driver/sdmmc_defs.h" #include "diskio.h" #include -#include "diskio_spiflash.h" +//#include "diskio_spiflash.h" +#include "diskio_wl.h" #include "esp_partition.h" #include "py/nlr.h" @@ -62,10 +63,13 @@ #include "lib/timeutils/timeutils.h" #include "sdkconfig.h" +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 2 +#include "libs/littleflash.h" +#endif // esp32 partition configuration static esp_partition_t * fs_partition = NULL; -#if !MICROPY_USE_SPIFFS +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 1 static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; #endif @@ -103,18 +107,24 @@ STATIC const byte fresult_to_errno_table[20] = { STATIC const char *TAG = "vfs_native"; sdcard_config_t sdcard_config = { +#if CONFIG_SDCARD_MODE == 1 + SDMMC_FREQ_DEFAULT, +#else + SDMMC_FREQ_HIGHSPEED, +#endif CONFIG_SDCARD_MODE, #if CONFIG_SDCARD_MODE == 1 CONFIG_SDCARD_CLK, CONFIG_SDCARD_MOSI, CONFIG_SDCARD_MISO, - CONFIG_SDCARD_CS + CONFIG_SDCARD_CS, #else -1, -1, -1, - -1 + -1, #endif + VSPI_HOST }; bool native_vfs_mounted[2] = {false, false}; @@ -487,10 +497,29 @@ STATIC mp_obj_t native_vfs_getcwd(mp_obj_t vfs_in) { return mp_const_none; } - return mp_obj_new_str(buf, strlen(buf), false); + return mp_obj_new_str(buf, strlen(buf)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(native_vfs_getcwd_obj, native_vfs_getcwd); +/// Get the current drive. +//------------------------------------- +STATIC mp_obj_t native_vfs_getdrive() { + + char drive[32]; + + if (MP_STATE_VM(vfs_cur) == MP_VFS_ROOT) { + sprintf(drive, "/"); + } + else { + if (strstr(cwd, VFS_NATIVE_MOUNT_POINT) != NULL) sprintf(drive, VFS_NATIVE_INTERNAL_MP); + else if (strstr(cwd, VFS_NATIVE_SDCARD_MOUNT_POINT) != NULL) sprintf(drive, VFS_NATIVE_EXTERNAL_MP); + else sprintf(drive, "/"); + } + + return mp_obj_new_str(drive, strlen(drive)); +} +MP_DEFINE_CONST_FUN_OBJ_0(native_vfs_getdrive_obj, native_vfs_getdrive); + /// \function stat(path) /// Get the status of a file or directory. //------------------------------------------------------------------ @@ -516,9 +545,9 @@ STATIC mp_obj_t native_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { buf.st_ctime = buf.st_atime; // Jan 1, 2000 buf.st_mode = MP_S_IFDIR; if (self->device == VFS_NATIVE_TYPE_SPIFLASH) { - #if MICROPY_USE_SPIFFS + #if CONFIG_MICROPY_FILESYSTEM_TYPE == 0 uint32_t total, used; - esp_spiffs_info("internalfs", &total, &used); + esp_spiffs_info(VFS_NATIVE_INTERNAL_PART_LABEL, &total, &used); buf.st_size = total; #else FRESULT res=0; @@ -579,13 +608,19 @@ STATIC mp_obj_t native_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) { DWORD fre_clust; if (self->device == VFS_NATIVE_TYPE_SPIFLASH) { - #if MICROPY_USE_SPIFFS + #if CONFIG_MICROPY_FILESYSTEM_TYPE == 0 uint32_t total, used; - esp_spiffs_info("internalfs", &total, &used); + esp_spiffs_info(VFS_NATIVE_INTERNAL_PART_LABEL, &total, &used); f_bsize = 256; //SPIFFS_LOG_PAGE_SIZE; f_blocks = total / 256; //SPIFFS_LOG_PAGE_SIZE; f_bfree = (total-used) / 256; //SPIFFS_LOG_PAGE_SIZE; maxlfn = CONFIG_SPIFFS_OBJ_NAME_LEN; + #elif CONFIG_MICROPY_FILESYSTEM_TYPE == 2 + maxlfn = LFS_NAME_MAX; + uint32_t used = littleFlash_getUsedBlocks(); + f_bsize = littleFlash.lfs_cfg.block_size; + f_blocks = littleFlash.lfs_cfg.block_count; + f_bfree = f_blocks - used; #else res = f_getfree(VFS_NATIVE_MOUNT_POINT, &fre_clust, &fatfs); goto is_fat; @@ -593,7 +628,7 @@ STATIC mp_obj_t native_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) { } else if (self->device == VFS_NATIVE_TYPE_SDCARD) { res = f_getfree(VFS_NATIVE_SDCARD_MOUNT_POINT, &fre_clust, &fatfs); -#if !MICROPY_USE_SPIFFS +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 1 is_fat: #endif if (res != 0) { @@ -673,17 +708,59 @@ STATIC void sdcard_print_info(const sdmmc_card_t* card, int mode) else if (mode == 3) { printf(" Mode: Unknown\n"); } - printf(" Name: %s\n", card->cid.name); - printf(" Type: %s\n", (card->ocr & SD_OCR_SDHC_CAP)?"SDHC/SDXC":"SDSC"); - printf("Speed: %s (%d MHz)\n", (card->csd.tr_speed > 25000000)?"high speed":"default speed", card->csd.tr_speed/1000000); - printf(" Size: %u MB\n", (uint32_t)(((uint64_t) card->csd.capacity) * card->csd.sector_size / (1024 * 1024))); - printf(" CSD: ver=%d, sector_size=%d, capacity=%d read_bl_len=%d\n", + printf(" Name: %s\n", card->cid.name); + printf(" Type: %s\n", (card->ocr & SD_OCR_SDHC_CAP)?"SDHC/SDXC":"SDSC"); + printf(" Speed: %s (%d MHz)\n", (card->csd.tr_speed > 25000000)?"high speed":"default speed", card->csd.tr_speed/1000000); + if (mode == 1) printf("SPI speed: %d MHz\n", card->host.max_freq_khz / 1000); + printf(" Size: %u MB\n", (uint32_t)(((uint64_t) card->csd.capacity) * card->csd.sector_size / (1024 * 1024))); + printf(" CSD: ver=%d, sector_size=%d, capacity=%d read_bl_len=%d\n", card->csd.csd_ver, card->csd.sector_size, card->csd.capacity, card->csd.read_block_len); - printf(" SCR: sd_spec=%d, bus_width=%d\n\n", card->scr.sd_spec, card->scr.bus_width); + printf(" SCR: sd_spec=%d, bus_width=%d\n\n", card->scr.sd_spec, card->scr.bus_width); #endif } +//-------------------------------------------------------------------------------------------- +static void _setPins(int8_t miso, int8_t mosi, int8_t clk, int8_t cs, int8_t dat1, int8_t dat2) +{ + if (miso >= 0) { // miso/dat0/dO + gpio_pad_select_gpio(miso); + gpio_set_direction(miso, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_pull_mode(miso, GPIO_PULLUP_ONLY); + gpio_set_level(miso, 1); + } + if (mosi >= 0) { // mosi/cmd/dI + gpio_pad_select_gpio(mosi); + gpio_set_direction(mosi, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_pull_mode(mosi, GPIO_PULLUP_ONLY); + gpio_set_level(mosi, 1); + } + if (clk >= 0) { // clk/sck + gpio_pad_select_gpio(clk); + gpio_set_direction(clk, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_pull_mode(clk, GPIO_PULLUP_ONLY); + gpio_set_level(clk, 1); + } + if (cs >= 0) { // cs/dat3 + gpio_pad_select_gpio(cs); + gpio_set_direction(cs, GPIO_MODE_INPUT_OUTPUT); + gpio_set_pull_mode(cs, GPIO_PULLUP_ONLY); + gpio_set_level(cs, 1); + } + if (dat1 >= 0) { // dat1 + gpio_pad_select_gpio(dat1); + gpio_set_direction(dat1, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_pull_mode(dat1, GPIO_PULLUP_ONLY); + gpio_set_level(dat1, 1); + } + if (dat2 >= 0) { // dat2 + gpio_pad_select_gpio(dat2); + gpio_set_direction(dat2, GPIO_MODE_INPUT_OUTPUT_OD); + gpio_set_pull_mode(dat2, GPIO_PULLUP_ONLY); + gpio_set_level(dat2, 1); + } +} + //------------------------- static void _sdcard_mount() { @@ -691,7 +768,8 @@ static void _sdcard_mount() esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = false, - .max_files = CONFIG_MICROPY_FATFS_MAX_OPEN_FILES + .max_files = CONFIG_MICROPY_FATFS_MAX_OPEN_FILES, + .allocation_unit_size = 0 }; // Configure sdmmc interface @@ -699,18 +777,11 @@ static void _sdcard_mount() // Use SPI mode sdmmc_host_t host = SDSPI_HOST_DEFAULT(); sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); - host.slot = VSPI_HOST; - + host.slot = sdcard_config.host; + host.max_freq_khz = sdcard_config.max_speed; slot_config.dma_channel = 2; - gpio_pad_select_gpio(sdcard_config.miso); - gpio_pad_select_gpio(sdcard_config.mosi); - gpio_pad_select_gpio(sdcard_config.clk); - gpio_pad_select_gpio(sdcard_config.cs); - gpio_set_direction(sdcard_config.miso, GPIO_MODE_INPUT); - gpio_set_pull_mode(sdcard_config.miso, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(sdcard_config.clk, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(sdcard_config.mosi, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(sdcard_config.cs, GPIO_PULLUP_ONLY); + _setPins(sdcard_config.miso, sdcard_config.mosi, sdcard_config.clk, sdcard_config.cs, -1, -1); + slot_config.gpio_miso = sdcard_config.miso; slot_config.gpio_mosi = sdcard_config.mosi; slot_config.gpio_sck = sdcard_config.clk; @@ -720,22 +791,20 @@ static void _sdcard_mount() else { sdmmc_host_t host = SDMMC_HOST_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - if (sdcard_config.mode == 1) { + host.max_freq_khz = sdcard_config.max_speed; //(sdcard_config.max_speed > SDMMC_FREQ_DEFAULT) ? SDMMC_FREQ_HIGHSPEED : SDMMC_FREQ_DEFAULT; + if (sdcard_config.mode == 2) { // Use 1-line SD mode - gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(14, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); + // miso,mosi,clk,cs,dat1,dat2 + _setPins(2, 15, 14, 13, -1, -1); host.flags = SDMMC_HOST_FLAG_1BIT; slot_config.width = 1; } else { // Use 4-line SD mode - gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(14, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); + // miso,mosi,clk,cs,dat1,dat2 + _setPins(2, 15, 14, 13, 4, 12); + host.flags = SDMMC_HOST_FLAG_4BIT; + slot_config.width = 4; } ret = esp_vfs_fat_sdmmc_mount(VFS_NATIVE_SDCARD_MOUNT_POINT, &host, &slot_config, &mount_config, &sdmmc_card); } @@ -784,28 +853,48 @@ STATIC mp_obj_t native_vfs_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t m if (self->device == VFS_NATIVE_TYPE_SPIFLASH) { // spiflash device esp_err_t ret; - #if MICROPY_USE_SPIFFS - fs_partition = (esp_partition_t *)esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "internalfs"); + #if CONFIG_MICROPY_FILESYSTEM_TYPE == 0 + fs_partition = (esp_partition_t *)esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, VFS_NATIVE_INTERNAL_PART_LABEL); if (fs_partition == NULL) { printf("\nInternal SPIFFS: File system partition definition not found!\n"); return mp_const_none; } esp_vfs_spiffs_conf_t conf = { .base_path = VFS_NATIVE_MOUNT_POINT, - .partition_label = "internalfs", + .partition_label = VFS_NATIVE_INTERNAL_PART_LABEL, .max_files = CONFIG_MICROPY_FATFS_MAX_OPEN_FILES, .format_if_mount_failed = true }; ret = esp_vfs_spiffs_register(&conf); //if (spiffs_is_mounted == 0) { - if ((ret != ESP_OK) || (!esp_spiffs_mounted("internalfs"))) { + if ((ret != ESP_OK) || (!esp_spiffs_mounted(VFS_NATIVE_INTERNAL_PART_LABEL))) { ESP_LOGE(TAG, "Failed to mount Flash partition as SPIFFS."); return mp_const_false; } native_vfs_mounted[self->device] = true; checkBoot_py(); + #elif CONFIG_MICROPY_FILESYSTEM_TYPE == 2 + fs_partition = (esp_partition_t *)esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, VFS_NATIVE_INTERNAL_PART_LABEL); + if (fs_partition == NULL) { + printf("\nInternal LittleFS: File system partition definition not found!\n"); + return mp_const_none; + } + const little_flash_config_t little_cfg = { + .part = fs_partition, + .base_path = VFS_NATIVE_MOUNT_POINT, + .open_files = CONFIG_MICROPY_FATFS_MAX_OPEN_FILES, + .auto_format = true, + .lookahead = 32 + }; + ret = littleFlash_init(&little_cfg); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to mount Flash partition as LittleFS."); + return mp_const_false; + } + native_vfs_mounted[self->device] = true; + checkBoot_py(); #else - fs_partition = (esp_partition_t *)esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "internalfs"); + fs_partition = (esp_partition_t *)esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, VFS_NATIVE_INTERNAL_PART_LABEL); if (fs_partition == NULL) { printf("\nInternal FatFS: File system partition definition not found!\n"); return mp_const_none; @@ -814,9 +903,10 @@ STATIC mp_obj_t native_vfs_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t m const esp_vfs_fat_mount_config_t mount_config = { .format_if_mount_failed = true, .max_files = CONFIG_MICROPY_FATFS_MAX_OPEN_FILES, + .allocation_unit_size = 0, }; // Mount spi Flash filesystem using configuration from sdkconfig.h - esp_err_t err = esp_vfs_fat_spiflash_mount(VFS_NATIVE_MOUNT_POINT, "internalfs", &mount_config, &s_wl_handle); + esp_err_t err = esp_vfs_fat_spiflash_mount(VFS_NATIVE_MOUNT_POINT, VFS_NATIVE_INTERNAL_PART_LABEL, &mount_config, &s_wl_handle); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to mount Flash partition as FatFS(%d)", err); @@ -830,15 +920,22 @@ STATIC mp_obj_t native_vfs_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t m int f_bsize=0, f_blocks=0, f_bfree=0; ret = ESP_FAIL; printf("\nInternal FS "); - #if MICROPY_USE_SPIFFS + #if CONFIG_MICROPY_FILESYSTEM_TYPE == 0 printf("(SPIFFS): "); uint32_t total, used; - if (esp_spiffs_info("internalfs", &total, &used) == ESP_OK) { + if (esp_spiffs_info(VFS_NATIVE_INTERNAL_PART_LABEL, &total, &used) == ESP_OK) { f_bsize = 256; f_blocks = total / 256; f_bfree = (total-used) / 256; ret = ESP_OK; } + #elif CONFIG_MICROPY_FILESYSTEM_TYPE == 2 + printf("(LittleFS ver %d.%d): ", LFS_VERSION_MAJOR, LFS_VERSION_MINOR); + uint32_t used = littleFlash_getUsedBlocks(); + f_bsize = littleFlash.lfs_cfg.block_size; + f_blocks = littleFlash.lfs_cfg.block_count; + f_bfree = f_blocks - used; + ret = ESP_OK; #else printf("(FatFS): "); if (fs_partition->encrypted) printf("[Encrypted] "); @@ -898,9 +995,11 @@ int internalUmount() { int res = 0; if (native_vfs_mounted[VFS_NATIVE_TYPE_SPIFLASH]) { - #if MICROPY_USE_SPIFFS - res = esp_vfs_spiffs_unregister("internalfs"); + #if CONFIG_MICROPY_FILESYSTEM_TYPE == 0 + res = esp_vfs_spiffs_unregister(VFS_NATIVE_INTERNAL_PART_LABEL); if (res) res = 0; + #elif CONFIG_MICROPY_FILESYSTEM_TYPE == 2 + littleFlash_term(VFS_NATIVE_INTERNAL_PART_LABEL); #else if (s_wl_handle != WL_INVALID_HANDLE) res = wl_unmount(s_wl_handle); if (res) res = 0; @@ -946,7 +1045,7 @@ int mount_vfs(int type, char *chdir_to) // mount flash file system args2[0] = vfso; - args2[1] = mp_obj_new_str(mp, strlen(mp), false); + args2[1] = mp_obj_new_str(mp, strlen(mp)); mp_call_function_n_kw(MP_OBJ_FROM_PTR(&mp_vfs_mount_obj), 2, 0, args2); if (native_vfs_mounted[type]) { @@ -960,21 +1059,23 @@ int mount_vfs(int type, char *chdir_to) return 0; } + //=============================================================== STATIC const mp_rom_map_elem_t native_vfs_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&native_vfs_mkfs_obj) }, - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&native_vfs_open_obj) }, - { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&native_vfs_ilistdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&native_vfs_mkdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&native_vfs_rmdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&native_vfs_chdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&native_vfs_getcwd_obj) }, - { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&native_vfs_remove_obj) }, - { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&native_vfs_rename_obj) }, - { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&native_vfs_stat_obj) }, - { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&native_vfs_statvfs_obj) }, - { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&native_vfs_mount_obj) }, - { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&native_vfs_umount_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&native_vfs_mkfs_obj) }, + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&native_vfs_open_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&native_vfs_ilistdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&native_vfs_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&native_vfs_rmdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&native_vfs_chdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&native_vfs_getcwd_obj) }, + { MP_ROM_QSTR(MP_QSTR_getdrive), MP_ROM_PTR(&native_vfs_getdrive_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&native_vfs_remove_obj) }, + { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&native_vfs_rename_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&native_vfs_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&native_vfs_statvfs_obj) }, + { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&native_vfs_mount_obj) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&native_vfs_umount_obj) }, }; STATIC MP_DEFINE_CONST_DICT(native_vfs_locals_dict, native_vfs_locals_dict_table); diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native.h b/MicroPython_BUILD/components/micropython/extmod/vfs_native.h index 569aa4e5..f9c41578 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs_native.h +++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native.h @@ -31,19 +31,21 @@ * */ -// ======== CD Card support =========================================================================== - +#include "sdkconfig.h" #include "py/lexer.h" #include "py/obj.h" #include "py/objint.h" #include "extmod/vfs.h" -#if MICROPY_USE_SPIFFS +#if CONFIG_MICROPY_FILESYSTEM_TYPE == 0 #define VFS_NATIVE_MOUNT_POINT "/_#!#_spiffs" +#elif CONFIG_MICROPY_FILESYSTEM_TYPE == 2 +#define VFS_NATIVE_MOUNT_POINT "/_#!#_littlefs" #else #define VFS_NATIVE_MOUNT_POINT "/_#!#_spiflash" #endif #define VFS_NATIVE_SDCARD_MOUNT_POINT "/_#!#_sdcard" +#define VFS_NATIVE_INTERNAL_PART_LABEL "internalfs" #define VFS_NATIVE_INTERNAL_MP "/flash" #define VFS_NATIVE_EXTERNAL_MP "/sd" #define VFS_NATIVE_TYPE_SPIFLASH 0 @@ -56,11 +58,13 @@ typedef struct _fs_user_mount_t { } fs_user_mount_t; typedef struct _sdcard_config_t { + int32_t max_speed; uint8_t mode; int8_t clk; int8_t mosi; int8_t miso; int8_t cs; + uint8_t host; } sdcard_config_t; extern const mp_obj_type_t mp_native_vfs_type; @@ -76,6 +80,7 @@ mp_import_stat_t native_vfs_import_stat(struct _fs_user_mount_t *vfs, const char mp_obj_t nativefs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode); int mount_vfs(int type, char *chdir_to); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); +MP_DECLARE_CONST_FUN_OBJ_0(native_vfs_getdrive_obj); //MP_DECLARE_CONST_FUN_OBJ_2(native_vfs_chdir_obj); int internalUmount(); diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c b/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c index cd80a297..e75e8327 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c +++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native_file.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -151,7 +152,19 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, // fsync() not implemented. return 0; - } else { + } else if (request == MP_STREAM_CLOSE) { + // if fs==NULL then the file is closed and in that case this method is a no-op + if (self->fd != -1) { + int res = close(self->fd); + self->fd = -1; + if (res < 0) { + *errcode = errno; + return MP_STREAM_ERROR; + } + } + return 0; + + } else { ESP_LOGD(TAG, "ioctl(%d, %d, ..): error %d", self->fd, request, MP_EINVAL); *errcode = MP_EINVAL; return MP_STREAM_ERROR; diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c b/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c index f2f9a316..2de7299e 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c +++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native_misc.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -79,7 +80,7 @@ STATIC mp_obj_t mp_vfs_native_ilistdir_it_iternext(mp_obj_t self_in) { // make 3-tuple with info about this entry mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); if (self->is_str) { - t->items[0] = mp_obj_new_str(fn, strlen(fn), false); + t->items[0] = mp_obj_new_str(fn, strlen(fn)); } else { t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn)); } diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c b/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c index 891098aa..e1ee45a3 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c +++ b/MicroPython_BUILD/components/micropython/extmod/vfs_reader.c @@ -71,7 +71,7 @@ STATIC void mp_reader_vfs_close(void *data) { void mp_reader_new_file(mp_reader_t *reader, const char *filename) { mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t); - mp_obj_t arg = mp_obj_new_str(filename, strlen(filename), false); + mp_obj_t arg = mp_obj_new_str(filename, strlen(filename)); rf->file = mp_vfs_open(1, &arg, (mp_map_t*)&mp_const_empty_map); int errcode; rf->len = mp_stream_rw(rf->file, rf->buf, sizeof(rf->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); diff --git a/MicroPython_BUILD/components/micropython/genhdr/qstrdefs.generated.h b/MicroPython_BUILD/components/micropython/genhdr/qstrdefs.generated.h index 27b04078..7b9081fb 100644 --- a/MicroPython_BUILD/components/micropython/genhdr/qstrdefs.generated.h +++ b/MicroPython_BUILD/components/micropython/genhdr/qstrdefs.generated.h @@ -2,6 +2,7 @@ QDEF(MP_QSTR_NULL, (const byte*)"\x00\x00\x00" "") QDEF(MP_QSTR_, (const byte*)"\x05\x15\x00" "") +QDEF(MP_QSTR___dir__, (const byte*)"\x7a\x8f\x07" "__dir__") QDEF(MP_QSTR___abs__, (const byte*)"\x95\xd6\x07" "__abs__") QDEF(MP_QSTR___add__, (const byte*)"\xc4\x82\x07" "__add__") QDEF(MP_QSTR___aenter__, (const byte*)"\x4c\x84\x0a" "__aenter__") @@ -67,6 +68,7 @@ QDEF(MP_QSTR__slash_, (const byte*)"\x8a\xb5\x01" "/") QDEF(MP_QSTR__percent__hash_o, (const byte*)"\x6c\x1a\x03" "%#o") QDEF(MP_QSTR__percent__hash_x, (const byte*)"\x7b\x1a\x03" "%#x") QDEF(MP_QSTR__brace_open__colon__hash_b_brace_close_, (const byte*)"\x58\x37\x05" "{:#b}") +QDEF(MP_QSTR__space_, (const byte*)"\x85\xb5\x01" " ") QDEF(MP_QSTR__0x0a_, (const byte*)"\xaf\xb5\x01" "\x0a") QDEF(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded, (const byte*)"\x73\x1e\x20" "maximum recursion depth exceeded") QDEF(MP_QSTR__lt_module_gt_, (const byte*)"\xbd\x94\x08" "") @@ -88,7 +90,6 @@ QDEF(MP_QSTR_ATTN_0DB, (const byte*)"\x23\x45\x08" "ATTN_0DB") QDEF(MP_QSTR_ATTN_11DB, (const byte*)"\x13\x1d\x09" "ATTN_11DB") QDEF(MP_QSTR_ATTN_2_5DB, (const byte*)"\xeb\xf6\x0a" "ATTN_2_5DB") QDEF(MP_QSTR_ATTN_6DB, (const byte*)"\x25\x2d\x08" "ATTN_6DB") -QDEF(MP_QSTR_AUTH_MAX, (const byte*)"\x66\x8d\x08" "AUTH_MAX") QDEF(MP_QSTR_AUTH_OPEN, (const byte*)"\x46\xb3\x09" "AUTH_OPEN") QDEF(MP_QSTR_AUTH_WEP, (const byte*)"\xf0\x0d\x08" "AUTH_WEP") QDEF(MP_QSTR_AUTH_WPA2_PSK, (const byte*)"\xf1\xfe\x0d" "AUTH_WPA2_PSK") @@ -113,18 +114,29 @@ QDEF(MP_QSTR_BOTTOM, (const byte*)"\x6a\x29\x06" "BOTTOM") QDEF(MP_QSTR_BaseException, (const byte*)"\x07\x92\x0d" "BaseException") QDEF(MP_QSTR_BufferedWriter, (const byte*)"\xeb\x2c\x0e" "BufferedWriter") QDEF(MP_QSTR_BytesIO, (const byte*)"\x1a\xb7\x07" "BytesIO") +QDEF(MP_QSTR_CBTYPE_ADDR, (const byte*)"\x10\xc2\x0b" "CBTYPE_ADDR") QDEF(MP_QSTR_CBTYPE_DATA, (const byte*)"\xb3\x6c\x0b" "CBTYPE_DATA") QDEF(MP_QSTR_CBTYPE_ERROR, (const byte*)"\xbb\xe6\x0c" "CBTYPE_ERROR") +QDEF(MP_QSTR_CBTYPE_NONE, (const byte*)"\x29\xbd\x0b" "CBTYPE_NONE") QDEF(MP_QSTR_CBTYPE_PATTERN, (const byte*)"\xab\xb3\x0e" "CBTYPE_PATTERN") -QDEF(MP_QSTR_CB_DATA, (const byte*)"\x6b\x50\x07" "CB_DATA") -QDEF(MP_QSTR_CB_READ, (const byte*)"\x49\x33\x07" "CB_READ") -QDEF(MP_QSTR_CB_WRITE, (const byte*)"\xc6\xca\x08" "CB_WRITE") +QDEF(MP_QSTR_CBTYPE_RXDATA, (const byte*)"\x39\x5f\x0d" "CBTYPE_RXDATA") +QDEF(MP_QSTR_CBTYPE_TXDATA, (const byte*)"\x7f\xd1\x0d" "CBTYPE_TXDATA") QDEF(MP_QSTR_CENTER, (const byte*)"\x8e\xdb\x06" "CENTER") +QDEF(MP_QSTR_CHANNEL_ALL_LEFT, (const byte*)"\x3c\x9f\x10" "CHANNEL_ALL_LEFT") +QDEF(MP_QSTR_CHANNEL_ALL_RIGHT, (const byte*)"\x27\x8e\x11" "CHANNEL_ALL_RIGHT") +QDEF(MP_QSTR_CHANNEL_ONLY_LEFT, (const byte*)"\xc9\xd5\x11" "CHANNEL_ONLY_LEFT") +QDEF(MP_QSTR_CHANNEL_ONLY_RIGHT, (const byte*)"\x72\x22\x12" "CHANNEL_ONLY_RIGHT") +QDEF(MP_QSTR_CHANNEL_RIGHT_LEFT, (const byte*)"\xbd\xd0\x12" "CHANNEL_RIGHT_LEFT") QDEF(MP_QSTR_CHRONO, (const byte*)"\x32\xd2\x06" "CHRONO") +QDEF(MP_QSTR_CIRCULAR, (const byte*)"\xb4\x76\x08" "CIRCULAR") QDEF(MP_QSTR_COLOR_BITS16, (const byte*)"\x8c\x23\x0c" "COLOR_BITS16") QDEF(MP_QSTR_COLOR_BITS24, (const byte*)"\xad\x23\x0c" "COLOR_BITS24") QDEF(MP_QSTR_CYAN, (const byte*)"\x10\x26\x04" "CYAN") QDEF(MP_QSTR_DAC, (const byte*)"\x03\xba\x03" "DAC") +QDEF(MP_QSTR_DAC_BOTH_EN, (const byte*)"\xb9\xa2\x0b" "DAC_BOTH_EN") +QDEF(MP_QSTR_DAC_DISABLE, (const byte*)"\x68\x5c\x0b" "DAC_DISABLE") +QDEF(MP_QSTR_DAC_LEFT_EN, (const byte*)"\xf3\xeb\x0b" "DAC_LEFT_EN") +QDEF(MP_QSTR_DAC_RIGHT_EN, (const byte*)"\xe8\xbe\x0c" "DAC_RIGHT_EN") QDEF(MP_QSTR_DARKCYAN, (const byte*)"\x0c\xab\x08" "DARKCYAN") QDEF(MP_QSTR_DARKGREEN, (const byte*)"\x42\x23\x09" "DARKGREEN") QDEF(MP_QSTR_DARKGREY, (const byte*)"\x90\xf1\x08" "DARKGREY") @@ -158,6 +170,10 @@ QDEF(MP_QSTR_EOPNOTSUPP, (const byte*)"\xac\x97\x0a" "EOPNOTSUPP") QDEF(MP_QSTR_EPERM, (const byte*)"\xea\x7f\x05" "EPERM") QDEF(MP_QSTR_ETIMEDOUT, (const byte*)"\xff\xf8\x09" "ETIMEDOUT") QDEF(MP_QSTR_EXIT, (const byte*)"\x45\xc7\x04" "EXIT") +QDEF(MP_QSTR_EXT1_ALLHIGH, (const byte*)"\x0d\x4a\x0c" "EXT1_ALLHIGH") +QDEF(MP_QSTR_EXT1_ALLLOW, (const byte*)"\x77\xa6\x0b" "EXT1_ALLLOW") +QDEF(MP_QSTR_EXT1_ANYHIGH, (const byte*)"\x1a\xc2\x0c" "EXT1_ANYHIGH") +QDEF(MP_QSTR_EXT1_ANYLOW, (const byte*)"\x40\xb0\x0b" "EXT1_ANYLOW") QDEF(MP_QSTR_EXTBASE, (const byte*)"\x19\x3d\x07" "EXTBASE") QDEF(MP_QSTR_EXTENDED, (const byte*)"\x42\x69\x08" "EXTENDED") QDEF(MP_QSTR_Ellipsis, (const byte*)"\xf0\xe0\x08" "Ellipsis") @@ -174,34 +190,47 @@ QDEF(MP_QSTR_FONT_Minya, (const byte*)"\x3b\xc1\x0a" "FONT_Minya") QDEF(MP_QSTR_FONT_Small, (const byte*)"\x16\x43\x0a" "FONT_Small") QDEF(MP_QSTR_FONT_Tooney, (const byte*)"\xef\xf6\x0b" "FONT_Tooney") QDEF(MP_QSTR_FONT_Ubuntu, (const byte*)"\xa4\xfb\x0b" "FONT_Ubuntu") +QDEF(MP_QSTR_FORMAT_I2S, (const byte*)"\xf1\xeb\x0a" "FORMAT_I2S") +QDEF(MP_QSTR_FORMAT_I2S_LSB, (const byte*)"\xb3\xd6\x0e" "FORMAT_I2S_LSB") +QDEF(MP_QSTR_FORMAT_I2S_MSB, (const byte*)"\xb2\xda\x0e" "FORMAT_I2S_MSB") +QDEF(MP_QSTR_FORMAT_PCM, (const byte*)"\x27\xc3\x0a" "FORMAT_PCM") +QDEF(MP_QSTR_FORMAT_PCM_LONG, (const byte*)"\x52\x80\x0f" "FORMAT_PCM_LONG") +QDEF(MP_QSTR_FORMAT_PCM_SHORT, (const byte*)"\x8a\x75\x10" "FORMAT_PCM_SHORT") QDEF(MP_QSTR_FileIO, (const byte*)"\xc5\x15\x06" "FileIO") -QDEF(MP_QSTR_FrameBuffer, (const byte*)"\xd8\xbe\x0b" "FrameBuffer") -QDEF(MP_QSTR_FrameBuffer1, (const byte*)"\xe9\x99\x0c" "FrameBuffer1") -QDEF(MP_QSTR_GENERIC, (const byte*)"\x54\x0c\x07" "GENERIC") QDEF(MP_QSTR_GRAY, (const byte*)"\x08\xc6\x04" "GRAY") QDEF(MP_QSTR_GREEN, (const byte*)"\xde\x98\x05" "GREEN") QDEF(MP_QSTR_GREENYELLOW, (const byte*)"\xda\x02\x0b" "GREENYELLOW") -QDEF(MP_QSTR_GS4_HMSB, (const byte*)"\x6e\x73\x08" "GS4_HMSB") QDEF(MP_QSTR_GeneratorExit, (const byte*)"\x16\x62\x0d" "GeneratorExit") QDEF(MP_QSTR_HALL, (const byte*)"\x4c\x8d\x04" "HALL") QDEF(MP_QSTR_HSBtoRGB, (const byte*)"\xd0\x92\x08" "HSBtoRGB") QDEF(MP_QSTR_HSBtoRGBint, (const byte*)"\xe3\xfa\x0b" "HSBtoRGBint") QDEF(MP_QSTR_HSPI, (const byte*)"\xc7\xe9\x04" "HSPI") QDEF(MP_QSTR_I2C, (const byte*)"\x5d\xdf\x03" "I2C") -QDEF(MP_QSTR_ILI9341, (const byte*)"\x86\x05\x07" "ILI9341") -QDEF(MP_QSTR_ILI9488, (const byte*)"\x84\x12\x07" "ILI9488") +QDEF(MP_QSTR_I2S, (const byte*)"\x4d\xdf\x03" "I2S") +QDEF(MP_QSTR_I2S_NUM_0, (const byte*)"\x4b\x7f\x09" "I2S_NUM_0") +QDEF(MP_QSTR_I2S_NUM_1, (const byte*)"\x4a\x7f\x09" "I2S_NUM_1") QDEF(MP_QSTR_IN, (const byte*)"\x22\x73\x02" "IN") QDEF(MP_QSTR_INCL, (const byte*)"\x0d\xbb\x04" "INCL") +QDEF(MP_QSTR_INOUT, (const byte*)"\xcc\x4f\x05" "INOUT") +QDEF(MP_QSTR_INOUT_OD, (const byte*)"\xf8\xd2\x08" "INOUT_OD") QDEF(MP_QSTR_INT16, (const byte*)"\x91\x76\x05" "INT16") QDEF(MP_QSTR_INT32, (const byte*)"\x57\x76\x05" "INT32") QDEF(MP_QSTR_INT64, (const byte*)"\xf4\x75\x05" "INT64") QDEF(MP_QSTR_INT8, (const byte*)"\xce\xbd\x04" "INT8") +QDEF(MP_QSTR_INV_CTS, (const byte*)"\x8f\x67\x07" "INV_CTS") +QDEF(MP_QSTR_INV_NONE, (const byte*)"\xa1\x85\x08" "INV_NONE") +QDEF(MP_QSTR_INV_RTS, (const byte*)"\x5e\xac\x07" "INV_RTS") +QDEF(MP_QSTR_INV_RX, (const byte*)"\x61\xde\x06" "INV_RX") +QDEF(MP_QSTR_INV_TX, (const byte*)"\xa7\xde\x06" "INV_TX") QDEF(MP_QSTR_IPPROTO_IP, (const byte*)"\x0c\x8e\x0a" "IPPROTO_IP") QDEF(MP_QSTR_IPPROTO_TCP, (const byte*)"\xb2\xde\x0b" "IPPROTO_TCP") QDEF(MP_QSTR_IPPROTO_UDP, (const byte*)"\x54\xdb\x0b" "IPPROTO_UDP") QDEF(MP_QSTR_IP_ADD_MEMBERSHIP, (const byte*)"\x6f\x5b\x11" "IP_ADD_MEMBERSHIP") -QDEF(MP_QSTR_IRQ, (const byte*)"\xaf\xda\x03" "IRQ") +QDEF(MP_QSTR_IRQ_ANYEDGE, (const byte*)"\x05\x5a\x0b" "IRQ_ANYEDGE") +QDEF(MP_QSTR_IRQ_DISABLE, (const byte*)"\x84\x61\x0b" "IRQ_DISABLE") QDEF(MP_QSTR_IRQ_FALLING, (const byte*)"\x37\xc0\x0b" "IRQ_FALLING") +QDEF(MP_QSTR_IRQ_HILEVEL, (const byte*)"\xe7\x05\x0b" "IRQ_HILEVEL") +QDEF(MP_QSTR_IRQ_LOLEVEL, (const byte*)"\x25\xb6\x0b" "IRQ_LOLEVEL") QDEF(MP_QSTR_IRQ_RISING, (const byte*)"\x78\xed\x0a" "IRQ_RISING") QDEF(MP_QSTR_ImportError, (const byte*)"\x20\x9c\x0b" "ImportError") QDEF(MP_QSTR_IndentationError, (const byte*)"\x5c\x20\x10" "IndentationError") @@ -209,7 +238,6 @@ QDEF(MP_QSTR_IndexError, (const byte*)"\x83\xad\x0a" "IndexError") QDEF(MP_QSTR_JPG, (const byte*)"\x38\xe7\x03" "JPG") QDEF(MP_QSTR_KeyError, (const byte*)"\xea\x00\x08" "KeyError") QDEF(MP_QSTR_KeyboardInterrupt, (const byte*)"\xaf\xe2\x11" "KeyboardInterrupt") -QDEF(MP_QSTR_LAN, (const byte*)"\x06\xdc\x03" "LAN") QDEF(MP_QSTR_LANDSCAPE, (const byte*)"\xa6\x7b\x09" "LANDSCAPE") QDEF(MP_QSTR_LANDSCAPE_FLIP, (const byte*)"\xca\x5c\x0e" "LANDSCAPE_FLIP") QDEF(MP_QSTR_LASTX, (const byte*)"\x57\x45\x05" "LASTX") @@ -225,23 +253,34 @@ QDEF(MP_QSTR_LOG_VERBOSE, (const byte*)"\x24\xbd\x0b" "LOG_VERBOSE") QDEF(MP_QSTR_LOG_WARN, (const byte*)"\x54\xad\x08" "LOG_WARN") QDEF(MP_QSTR_LSB, (const byte*)"\xd8\xde\x03" "LSB") QDEF(MP_QSTR_LookupError, (const byte*)"\xff\x69\x0b" "LookupError") +QDEF(MP_QSTR_M5Button, (const byte*)"\x8b\x85\x08" "M5Button") +QDEF(MP_QSTR_M5Circle, (const byte*)"\x4f\x9f\x08" "M5Circle") +QDEF(MP_QSTR_M5Img, (const byte*)"\x9e\x2f\x05" "M5Img") +QDEF(MP_QSTR_M5Rect, (const byte*)"\x9d\x5a\x06" "M5Rect") QDEF(MP_QSTR_M5STACK, (const byte*)"\x13\xad\x07" "M5STACK") +QDEF(MP_QSTR_M5TextBox, (const byte*)"\x15\xdd\x09" "M5TextBox") +QDEF(MP_QSTR_M5Title, (const byte*)"\xdd\x18\x07" "M5Title") +QDEF(MP_QSTR_M5UI_Deinit, (const byte*)"\x65\x1f\x0b" "M5UI_Deinit") QDEF(MP_QSTR_MAGENTA, (const byte*)"\xf0\xf0\x07" "MAGENTA") QDEF(MP_QSTR_MAROON, (const byte*)"\x95\x40\x06" "MAROON") QDEF(MP_QSTR_MASTER, (const byte*)"\x39\x8d\x06" "MASTER") QDEF(MP_QSTR_MODE_11B, (const byte*)"\xfb\x44\x08" "MODE_11B") QDEF(MP_QSTR_MODE_11G, (const byte*)"\xfe\x44\x08" "MODE_11G") QDEF(MP_QSTR_MODE_11N, (const byte*)"\xf7\x44\x08" "MODE_11N") -QDEF(MP_QSTR_MONO_HLSB, (const byte*)"\x4c\x98\x09" "MONO_HLSB") -QDEF(MP_QSTR_MONO_HMSB, (const byte*)"\xcd\x83\x09" "MONO_HMSB") -QDEF(MP_QSTR_MONO_VLSB, (const byte*)"\x12\xfc\x09" "MONO_VLSB") +QDEF(MP_QSTR_MODE_ADC_BUILT_IN, (const byte*)"\xfe\x2e\x11" "MODE_ADC_BUILT_IN") +QDEF(MP_QSTR_MODE_DAC_BUILT_IN, (const byte*)"\x1e\xd8\x11" "MODE_DAC_BUILT_IN") +QDEF(MP_QSTR_MODE_MASTER, (const byte*)"\x05\xc4\x0b" "MODE_MASTER") +QDEF(MP_QSTR_MODE_PDM, (const byte*)"\x00\xcb\x08" "MODE_PDM") +QDEF(MP_QSTR_MODE_RX, (const byte*)"\x73\x16\x07" "MODE_RX") +QDEF(MP_QSTR_MODE_SLAVE, (const byte*)"\xd4\xd6\x0a" "MODE_SLAVE") +QDEF(MP_QSTR_MODE_TX, (const byte*)"\x35\x16\x07" "MODE_TX") QDEF(MP_QSTR_MSB, (const byte*)"\x59\xca\x03" "MSB") -QDEF(MP_QSTR_MVLSB, (const byte*)"\x03\x14\x05" "MVLSB") QDEF(MP_QSTR_MemoryError, (const byte*)"\xdc\x83\x0b" "MemoryError") QDEF(MP_QSTR_Message, (const byte*)"\x8e\x9c\x07" "Message") -QDEF(MP_QSTR_Mqtt, (const byte*)"\x19\x7f\x04" "Mqtt") QDEF(MP_QSTR_NATIVE, (const byte*)"\x04\x8e\x06" "NATIVE") QDEF(MP_QSTR_NAVY, (const byte*)"\xc5\x57\x04" "NAVY") +QDEF(MP_QSTR_NOISE, (const byte*)"\xbb\xf4\x05" "NOISE") +QDEF(MP_QSTR_NORMAL, (const byte*)"\xf6\x79\x06" "NORMAL") QDEF(MP_QSTR_NameError, (const byte*)"\xba\x2d\x09" "NameError") QDEF(MP_QSTR_Neopixel, (const byte*)"\x49\x42\x08" "Neopixel") QDEF(MP_QSTR_NoneType, (const byte*)"\x17\x68\x08" "NoneType") @@ -249,17 +288,15 @@ QDEF(MP_QSTR_NotImplemented, (const byte*)"\x3e\xc6\x0e" "NotImplemented") QDEF(MP_QSTR_NotImplementedError, (const byte*)"\xc6\x98\x13" "NotImplementedError") QDEF(MP_QSTR_OLIVE, (const byte*)"\x7c\xb1\x05" "OLIVE") QDEF(MP_QSTR_ONE_SHOT, (const byte*)"\x5e\xff\x08" "ONE_SHOT") -QDEF(MP_QSTR_OPEN_DRAIN, (const byte*)"\x5e\x48\x0a" "OPEN_DRAIN") QDEF(MP_QSTR_ORANGE, (const byte*)"\xf5\xc1\x06" "ORANGE") QDEF(MP_QSTR_OSError, (const byte*)"\xa1\x65\x07" "OSError") QDEF(MP_QSTR_OUT, (const byte*)"\x0b\xe3\x03" "OUT") +QDEF(MP_QSTR_OUT_OD, (const byte*)"\x1f\x2a\x06" "OUT_OD") QDEF(MP_QSTR_Onewire, (const byte*)"\x48\x3b\x07" "Onewire") QDEF(MP_QSTR_OrderedDict, (const byte*)"\xf0\x7e\x0b" "OrderedDict") QDEF(MP_QSTR_OverflowError, (const byte*)"\x81\xe1\x0d" "OverflowError") QDEF(MP_QSTR_PAUSE, (const byte*)"\xf7\xdd\x05" "PAUSE") QDEF(MP_QSTR_PERIODIC, (const byte*)"\x0a\x35\x08" "PERIODIC") -QDEF(MP_QSTR_PHY_LAN8720, (const byte*)"\xf5\x1f\x0b" "PHY_LAN8720") -QDEF(MP_QSTR_PHY_TLK110, (const byte*)"\x98\xf7\x0a" "PHY_TLK110") QDEF(MP_QSTR_PINK, (const byte*)"\x19\x12\x04" "PINK") QDEF(MP_QSTR_POLLERR, (const byte*)"\xdf\xc0\x07" "POLLERR") QDEF(MP_QSTR_POLLHUP, (const byte*)"\x77\x8a\x07" "POLLHUP") @@ -269,48 +306,42 @@ QDEF(MP_QSTR_PORTRAIT, (const byte*)"\xf2\xcd\x08" "PORTRAIT") QDEF(MP_QSTR_PORTRAIT_FLIP, (const byte*)"\x1e\xf2\x0d" "PORTRAIT_FLIP") QDEF(MP_QSTR_PTR, (const byte*)"\xb3\x0c\x03" "PTR") QDEF(MP_QSTR_PULL_DOWN, (const byte*)"\xad\xfb\x09" "PULL_DOWN") +QDEF(MP_QSTR_PULL_FLOAT, (const byte*)"\x0f\x42\x0a" "PULL_FLOAT") QDEF(MP_QSTR_PULL_UP, (const byte*)"\xba\x5e\x07" "PULL_UP") +QDEF(MP_QSTR_PULL_UPDOWN, (const byte*)"\x88\xf3\x0b" "PULL_UPDOWN") QDEF(MP_QSTR_PURPLE, (const byte*)"\x0b\x40\x06" "PURPLE") QDEF(MP_QSTR_PWM, (const byte*)"\x4f\x0d\x03" "PWM") QDEF(MP_QSTR_Pin, (const byte*)"\x12\x14\x03" "Pin") QDEF(MP_QSTR_PinBase, (const byte*)"\x47\x43\x07" "PinBase") +QDEF(MP_QSTR_RAMP, (const byte*)"\x2b\xea\x04" "RAMP") QDEF(MP_QSTR_READ, (const byte*)"\xb7\xd8\x04" "READ") QDEF(MP_QSTR_RED, (const byte*)"\x96\x06\x03" "RED") QDEF(MP_QSTR_RESUME, (const byte*)"\x1c\x5c\x06" "RESUME") -QDEF(MP_QSTR_RGB565, (const byte*)"\x64\xcc\x06" "RGB565") QDEF(MP_QSTR_RGBtoHSB, (const byte*)"\x10\x1d\x08" "RGBtoHSB") QDEF(MP_QSTR_RIGHT, (const byte*)"\xc5\x79\x05" "RIGHT") QDEF(MP_QSTR_RTC, (const byte*)"\xa0\x04\x03" "RTC") QDEF(MP_QSTR_RUNNING, (const byte*)"\x42\x45\x07" "RUNNING") QDEF(MP_QSTR_RuntimeError, (const byte*)"\x61\xf1\x0c" "RuntimeError") +QDEF(MP_QSTR_SAWTOOTH, (const byte*)"\xa8\xe3\x08" "SAWTOOTH") QDEF(MP_QSTR_SDMODE_1LINE, (const byte*)"\x91\xff\x0c" "SDMODE_1LINE") QDEF(MP_QSTR_SDMODE_4LINE, (const byte*)"\x94\xbe\x0c" "SDMODE_4LINE") QDEF(MP_QSTR_SDMODE_SPI, (const byte*)"\x24\xb9\x0a" "SDMODE_SPI") QDEF(MP_QSTR_SILVER, (const byte*)"\x52\xdb\x06" "SILVER") +QDEF(MP_QSTR_SINE, (const byte*)"\xf4\xa6\x04" "SINE") QDEF(MP_QSTR_SLAVE, (const byte*)"\x68\x15\x05" "SLAVE") -QDEF(MP_QSTR_SMS_ALL, (const byte*)"\xf6\x3e\x07" "SMS_ALL") -QDEF(MP_QSTR_SMS_READ, (const byte*)"\x65\x95\x08" "SMS_READ") -QDEF(MP_QSTR_SMS_UNREAD, (const byte*)"\xde\x94\x0a" "SMS_UNREAD") -QDEF(MP_QSTR_SMTP, (const byte*)"\xbf\x95\x04" "SMTP") -QDEF(MP_QSTR_SMTPS, (const byte*)"\xcc\x4d\x05" "SMTPS") QDEF(MP_QSTR_SOCK_DGRAM, (const byte*)"\xb3\x14\x0a" "SOCK_DGRAM") QDEF(MP_QSTR_SOCK_RAW, (const byte*)"\xca\x96\x08" "SOCK_RAW") QDEF(MP_QSTR_SOCK_STREAM, (const byte*)"\x32\xbe\x0b" "SOCK_STREAM") QDEF(MP_QSTR_SOL_SOCKET, (const byte*)"\x0f\xdf\x0a" "SOL_SOCKET") -QDEF(MP_QSTR_SORT_ASC, (const byte*)"\xb1\x7b\x08" "SORT_ASC") -QDEF(MP_QSTR_SORT_DESC, (const byte*)"\xf1\x54\x09" "SORT_DESC") -QDEF(MP_QSTR_SORT_NONE, (const byte*)"\xca\xb5\x09" "SORT_NONE") QDEF(MP_QSTR_SO_REUSEADDR, (const byte*)"\x21\x53\x0c" "SO_REUSEADDR") QDEF(MP_QSTR_SPI, (const byte*)"\xef\x11\x03" "SPI") -QDEF(MP_QSTR_ST7735, (const byte*)"\x24\x22\x06" "ST7735") -QDEF(MP_QSTR_ST7735B, (const byte*)"\xe6\x66\x07" "ST7735B") -QDEF(MP_QSTR_ST7735R, (const byte*)"\xf6\x66\x07" "ST7735R") -QDEF(MP_QSTR_ST7789, (const byte*)"\x03\x23\x06" "ST7789") QDEF(MP_QSTR_STATUS, (const byte*)"\x31\xf4\x06" "STATUS") QDEF(MP_QSTR_STA_IF, (const byte*)"\xb3\x1b\x06" "STA_IF") QDEF(MP_QSTR_STOP, (const byte*)"\x5d\x3f\x04" "STOP") QDEF(MP_QSTR_SUSPEND, (const byte*)"\x0f\x79\x07" "SUSPEND") QDEF(MP_QSTR_SUSPENDED, (const byte*)"\xae\xef\x09" "SUSPENDED") +QDEF(MP_QSTR_SetHeapSize, (const byte*)"\x1e\x9f\x0b" "SetHeapSize") +QDEF(MP_QSTR_SetStackSize, (const byte*)"\xcc\x52\x0c" "SetStackSize") QDEF(MP_QSTR_Signal, (const byte*)"\x9b\xe4\x06" "Signal") QDEF(MP_QSTR_StopAsyncIteration, (const byte*)"\xec\xf0\x12" "StopAsyncIteration") QDEF(MP_QSTR_StopIteration, (const byte*)"\xea\x1c\x0d" "StopIteration") @@ -320,20 +351,7 @@ QDEF(MP_QSTR_SystemExit, (const byte*)"\x20\xff\x0a" "SystemExit") QDEF(MP_QSTR_TEAL, (const byte*)"\x79\xd1\x04" "TEAL") QDEF(MP_QSTR_TERMINATED, (const byte*)"\x78\xca\x0a" "TERMINATED") QDEF(MP_QSTR_TFT, (const byte*)"\x63\xff\x03" "TFT") -QDEF(MP_QSTR_TOUCH_NONE, (const byte*)"\xb5\x0a\x0a" "TOUCH_NONE") -QDEF(MP_QSTR_TOUCH_STMPE, (const byte*)"\xc0\x76\x0b" "TOUCH_STMPE") -QDEF(MP_QSTR_TOUCH_XPT, (const byte*)"\x43\x32\x09" "TOUCH_XPT") -QDEF(MP_QSTR_TRACE_ALL, (const byte*)"\xba\x6e\x09" "TRACE_ALL") -QDEF(MP_QSTR_TRACE_AUTH, (const byte*)"\xf3\x39\x0a" "TRACE_AUTH") -QDEF(MP_QSTR_TRACE_CONN, (const byte*)"\x77\x5a\x0a" "TRACE_CONN") -QDEF(MP_QSTR_TRACE_ERROR, (const byte*)"\xc3\x1c\x0b" "TRACE_ERROR") -QDEF(MP_QSTR_TRACE_KEX, (const byte*)"\x4d\x56\x09" "TRACE_KEX") -QDEF(MP_QSTR_TRACE_NONE, (const byte*)"\x51\xad\x0a" "TRACE_NONE") -QDEF(MP_QSTR_TRACE_PUBLICKEY, (const byte*)"\xcd\x1a\x0f" "TRACE_PUBLICKEY") -QDEF(MP_QSTR_TRACE_SCP, (const byte*)"\x9b\x33\x09" "TRACE_SCP") -QDEF(MP_QSTR_TRACE_SFTP, (const byte*)"\xea\xc3\x0a" "TRACE_SFTP") -QDEF(MP_QSTR_TRACE_SOCKET, (const byte*)"\x7e\xcb\x0c" "TRACE_SOCKET") -QDEF(MP_QSTR_TRACE_TRANS, (const byte*)"\xe1\xf8\x0b" "TRACE_TRANS") +QDEF(MP_QSTR_TRIANGLE, (const byte*)"\xeb\x82\x08" "TRIANGLE") QDEF(MP_QSTR_TYPE_RGB, (const byte*)"\x95\xd4\x08" "TYPE_RGB") QDEF(MP_QSTR_TYPE_RGBW, (const byte*)"\x62\x67\x09" "TYPE_RGBW") QDEF(MP_QSTR_TextIOWrapper, (const byte*)"\xad\x8d\x0d" "TextIOWrapper") @@ -353,12 +371,14 @@ QDEF(MP_QSTR_VSPI, (const byte*)"\x19\x7e\x04" "VSPI") QDEF(MP_QSTR_ValueError, (const byte*)"\x96\x87\x0a" "ValueError") QDEF(MP_QSTR_VfsNative, (const byte*)"\x07\xdf\x09" "VfsNative") QDEF(MP_QSTR_WAITING, (const byte*)"\x8e\xdc\x07" "WAITING") +QDEF(MP_QSTR_WDT, (const byte*)"\x62\x03\x03" "WDT") QDEF(MP_QSTR_WHITE, (const byte*)"\xa2\xc2\x05" "WHITE") QDEF(MP_QSTR_WIDTH_10BIT, (const byte*)"\xc2\x7c\x0b" "WIDTH_10BIT") QDEF(MP_QSTR_WIDTH_11BIT, (const byte*)"\xa3\xdf\x0b" "WIDTH_11BIT") QDEF(MP_QSTR_WIDTH_12BIT, (const byte*)"\x80\xa4\x0b" "WIDTH_12BIT") QDEF(MP_QSTR_WIDTH_9BIT, (const byte*)"\x5a\x2c\x0a" "WIDTH_9BIT") QDEF(MP_QSTR_WLAN, (const byte*)"\x11\x94\x04" "WLAN") +QDEF(MP_QSTR_WLANcallback, (const byte*)"\x58\x3c\x0c" "WLANcallback") QDEF(MP_QSTR_WRITE, (const byte*)"\xf8\xa8\x05" "WRITE") QDEF(MP_QSTR_YELLOW, (const byte*)"\x41\x49\x06" "YELLOW") QDEF(MP_QSTR_ZeroDivisionError, (const byte*)"\xb6\x27\x11" "ZeroDivisionError") @@ -370,8 +390,9 @@ QDEF(MP_QSTR_accepted, (const byte*)"\x24\x02\x08" "accepted") QDEF(MP_QSTR_acos, (const byte*)"\x1b\xa0\x04" "acos") QDEF(MP_QSTR_acosh, (const byte*)"\x13\xa3\x05" "acosh") QDEF(MP_QSTR_active, (const byte*)"\x69\xea\x06" "active") +QDEF(MP_QSTR_acttime, (const byte*)"\x46\x4d\x07" "acttime") +QDEF(MP_QSTR_adc_enable, (const byte*)"\xfd\x74\x0a" "adc_enable") QDEF(MP_QSTR_add, (const byte*)"\x44\x32\x03" "add") -QDEF(MP_QSTR_addService, (const byte*)"\xd9\x55\x0a" "addService") QDEF(MP_QSTR_addr, (const byte*)"\xb6\x7a\x04" "addr") QDEF(MP_QSTR_address, (const byte*)"\x73\x53\x07" "address") QDEF(MP_QSTR_addressof, (const byte*)"\x5a\xf9\x09" "addressof") @@ -382,30 +403,30 @@ QDEF(MP_QSTR_alloc_emergency_exception_buf, (const byte*)"\x78\x2a\x1d" "alloc_e QDEF(MP_QSTR_allowsuspend, (const byte*)"\x76\xc3\x0c" "allowsuspend") QDEF(MP_QSTR_angle, (const byte*)"\x84\x2c\x05" "angle") QDEF(MP_QSTR_any, (const byte*)"\x13\x33\x03" "any") -QDEF(MP_QSTR_apn, (const byte*)"\xda\x34\x03" "apn") QDEF(MP_QSTR_append, (const byte*)"\x6b\x97\x06" "append") QDEF(MP_QSTR_arc, (const byte*)"\x95\x34\x03" "arc") QDEF(MP_QSTR_arg, (const byte*)"\x91\x34\x03" "arg") QDEF(MP_QSTR_args, (const byte*)"\xc2\xc6\x04" "args") QDEF(MP_QSTR_argv, (const byte*)"\xc7\xc6\x04" "argv") QDEF(MP_QSTR_array, (const byte*)"\x7c\x72\x05" "array") +QDEF(MP_QSTR_asc, (const byte*)"\x74\x35\x03" "asc") QDEF(MP_QSTR_asin, (const byte*)"\x50\xe5\x04" "asin") QDEF(MP_QSTR_asinh, (const byte*)"\x38\x8f\x05" "asinh") QDEF(MP_QSTR_asnum, (const byte*)"\x01\x82\x05" "asnum") QDEF(MP_QSTR_atan, (const byte*)"\x1f\xbe\x04" "atan") QDEF(MP_QSTR_atan2, (const byte*)"\xcd\x81\x05" "atan2") QDEF(MP_QSTR_atanh, (const byte*)"\x97\x81\x05" "atanh") -QDEF(MP_QSTR_atcmd, (const byte*)"\xfa\x9a\x05" "atcmd") -QDEF(MP_QSTR_attach, (const byte*)"\x8e\x75\x06" "attach") QDEF(MP_QSTR_atten, (const byte*)"\xaf\x50\x05" "atten") QDEF(MP_QSTR_attrib7seg, (const byte*)"\xdb\x79\x0a" "attrib7seg") QDEF(MP_QSTR_authmode, (const byte*)"\xce\x65\x08" "authmode") -QDEF(MP_QSTR_autoreconnect, (const byte*)"\xe3\x51\x0d" "autoreconnect") QDEF(MP_QSTR_b2a_base64, (const byte*)"\x3c\x8f\x0a" "b2a_base64") QDEF(MP_QSTR_backl_on, (const byte*)"\xbc\x78\x08" "backl_on") QDEF(MP_QSTR_backl_pin, (const byte*)"\xaa\x80\x09" "backl_pin") QDEF(MP_QSTR_backlight, (const byte*)"\xb0\x86\x09" "backlight") QDEF(MP_QSTR_baudrate, (const byte*)"\xf5\xd8\x08" "baudrate") +QDEF(MP_QSTR_bck, (const byte*)"\x2f\x47\x03" "bck") +QDEF(MP_QSTR_bcolor, (const byte*)"\xda\xfe\x06" "bcolor") +QDEF(MP_QSTR_beep, (const byte*)"\x37\x34\x04" "beep") QDEF(MP_QSTR_begin, (const byte*)"\x82\xc1\x05" "begin") QDEF(MP_QSTR_bgcolor, (const byte*)"\xbd\xb6\x07" "bgcolor") QDEF(MP_QSTR_bgr, (const byte*)"\xb2\x46\x03" "bgr") @@ -413,8 +434,7 @@ QDEF(MP_QSTR_bin, (const byte*)"\xe0\x48\x03" "bin") QDEF(MP_QSTR_binascii, (const byte*)"\x91\x3c\x08" "binascii") QDEF(MP_QSTR_bind, (const byte*)"\x84\x64\x04" "bind") QDEF(MP_QSTR_bits, (const byte*)"\x49\x68\x04" "bits") -QDEF(MP_QSTR_blit, (const byte*)"\xf6\x50\x04" "blit") -QDEF(MP_QSTR_bodylen, (const byte*)"\x32\x36\x07" "bodylen") +QDEF(MP_QSTR_block_sleep, (const byte*)"\x1c\x02\x0b" "block_sleep") QDEF(MP_QSTR_bool, (const byte*)"\xeb\x3c\x04" "bool") QDEF(MP_QSTR_bound_method, (const byte*)"\x97\xa2\x0c" "bound_method") QDEF(MP_QSTR_brightness, (const byte*)"\x4c\xc6\x0a" "brightness") @@ -423,8 +443,8 @@ QDEF(MP_QSTR_buf, (const byte*)"\x74\x49\x03" "buf") QDEF(MP_QSTR_buffer, (const byte*)"\xe5\xa0\x06" "buffer") QDEF(MP_QSTR_buffer_size, (const byte*)"\xbf\xd5\x0b" "buffer_size") QDEF(MP_QSTR_buffering, (const byte*)"\x25\xdb\x09" "buffering") -QDEF(MP_QSTR_buffsize, (const byte*)"\x77\xad\x08" "buffsize") QDEF(MP_QSTR_builtins, (const byte*)"\xf7\x31\x08" "builtins") +QDEF(MP_QSTR_byte, (const byte*)"\x4f\xa8\x04" "byte") QDEF(MP_QSTR_bytearray, (const byte*)"\x76\xa3\x09" "bytearray") QDEF(MP_QSTR_bytearray_at, (const byte*)"\x9c\x5c\x0c" "bytearray_at") QDEF(MP_QSTR_bytecode, (const byte*)"\x22\x7d\x08" "bytecode") @@ -435,31 +455,29 @@ QDEF(MP_QSTR_cachesize, (const byte*)"\xcc\x78\x09" "cachesize") QDEF(MP_QSTR_calcsize, (const byte*)"\x4d\x38\x08" "calcsize") QDEF(MP_QSTR_callable, (const byte*)"\x0d\x70\x08" "callable") QDEF(MP_QSTR_callback, (const byte*)"\x4c\xf0\x08" "callback") -QDEF(MP_QSTR_calx, (const byte*)"\x73\xc1\x04" "calx") -QDEF(MP_QSTR_caly, (const byte*)"\x72\xc1\x04" "caly") -QDEF(MP_QSTR_cc, (const byte*)"\xe5\x6e\x02" "cc") QDEF(MP_QSTR_ceil, (const byte*)"\x06\xb0\x04" "ceil") QDEF(MP_QSTR_center, (const byte*)"\x4e\xbf\x06" "center") QDEF(MP_QSTR_cert, (const byte*)"\x25\xb1\x04" "cert") +QDEF(MP_QSTR_changeImg, (const byte*)"\x20\x9a\x09" "changeImg") QDEF(MP_QSTR_channel, (const byte*)"\x26\x91\x07" "channel") +QDEF(MP_QSTR_channel_format, (const byte*)"\xda\x66\x0e" "channel_format") QDEF(MP_QSTR_chdir, (const byte*)"\xb1\xb2\x05" "chdir") -QDEF(MP_QSTR_checkSMS, (const byte*)"\x6e\xc1\x08" "checkSMS") QDEF(MP_QSTR_choice, (const byte*)"\x2e\x33\x06" "choice") QDEF(MP_QSTR_chr, (const byte*)"\xdc\x4c\x03" "chr") QDEF(MP_QSTR_circle, (const byte*)"\xb7\xdd\x06" "circle") QDEF(MP_QSTR_classmethod, (const byte*)"\xb4\x8c\x0b" "classmethod") -QDEF(MP_QSTR_cleansession, (const byte*)"\x7e\x01\x0c" "cleansession") QDEF(MP_QSTR_clear, (const byte*)"\x7c\xa0\x05" "clear") +QDEF(MP_QSTR_clear_bg, (const byte*)"\xe6\x30\x08" "clear_bg") QDEF(MP_QSTR_clearwin, (const byte*)"\xac\xb0\x08" "clearwin") -QDEF(MP_QSTR_clientid, (const byte*)"\x71\x4d\x08" "clientid") QDEF(MP_QSTR_clk, (const byte*)"\x41\x4c\x03" "clk") +QDEF(MP_QSTR_clock_timing, (const byte*)"\x62\xc5\x0c" "clock_timing") QDEF(MP_QSTR_close, (const byte*)"\x33\x67\x05" "close") QDEF(MP_QSTR_closure, (const byte*)"\x74\xca\x07" "closure") QDEF(MP_QSTR_cmath, (const byte*)"\xb6\xf4\x05" "cmath") -QDEF(MP_QSTR_cmd, (const byte*)"\x2f\x4c\x03" "cmd") -QDEF(MP_QSTR_cmddata, (const byte*)"\x3f\xa8\x07" "cmddata") QDEF(MP_QSTR_code, (const byte*)"\x68\xda\x04" "code") QDEF(MP_QSTR_collect, (const byte*)"\x9b\x65\x07" "collect") +QDEF(MP_QSTR_collected, (const byte*)"\x3a\x2c\x09" "collected") +QDEF(MP_QSTR_collectif, (const byte*)"\xb4\x2a\x09" "collectif") QDEF(MP_QSTR_collections, (const byte*)"\xe0\xc8\x0b" "collections") QDEF(MP_QSTR_color, (const byte*)"\xd8\x06\x05" "color") QDEF(MP_QSTR_color_bits, (const byte*)"\x4b\x33\x0a" "color_bits") @@ -469,7 +487,6 @@ QDEF(MP_QSTR_compileFont, (const byte*)"\x47\x0c\x0b" "compileFont") QDEF(MP_QSTR_complex, (const byte*)"\xc5\x9d\x07" "complex") QDEF(MP_QSTR_config, (const byte*)"\x4f\xa2\x06" "config") QDEF(MP_QSTR_connect, (const byte*)"\xdb\x3d\x07" "connect") -QDEF(MP_QSTR_connected_cb, (const byte*)"\xc4\xae\x0c" "connected_cb") QDEF(MP_QSTR_const, (const byte*)"\xc0\xff\x05" "const") QDEF(MP_QSTR_conv_time, (const byte*)"\x3b\x1d\x09" "conv_time") QDEF(MP_QSTR_convert, (const byte*)"\xf2\x9e\x07" "convert") @@ -484,11 +501,14 @@ QDEF(MP_QSTR_crc32, (const byte*)"\x76\xe8\x05" "crc32") QDEF(MP_QSTR_crc8, (const byte*)"\xcf\xef\x04" "crc8") QDEF(MP_QSTR_cs, (const byte*)"\xf5\x6e\x02" "cs") QDEF(MP_QSTR_cts, (const byte*)"\x41\x4d\x03" "cts") -QDEF(MP_QSTR_curl, (const byte*)"\x2d\xf1\x04" "curl") -QDEF(MP_QSTR_data_cb, (const byte*)"\x0b\xc5\x07" "data_cb") +QDEF(MP_QSTR_data, (const byte*)"\x15\xdc\x04" "data") +QDEF(MP_QSTR_data_format, (const byte*)"\xc9\xeb\x0b" "data_format") QDEF(MP_QSTR_data_len, (const byte*)"\xad\x71\x08" "data_len") +QDEF(MP_QSTR_data_timing, (const byte*)"\xda\x83\x0b" "data_timing") QDEF(MP_QSTR_dbgpin, (const byte*)"\x53\x30\x06" "dbgpin") +QDEF(MP_QSTR_dbgpinmode, (const byte*)"\x70\x24\x0a" "dbgpinmode") QDEF(MP_QSTR_dc, (const byte*)"\x82\x6d\x02" "dc") +QDEF(MP_QSTR_debounce, (const byte*)"\x14\xa0\x08" "debounce") QDEF(MP_QSTR_debug, (const byte*)"\xd4\x55\x05" "debug") QDEF(MP_QSTR_decode, (const byte*)"\xa9\x59\x06" "decode") QDEF(MP_QSTR_decompress, (const byte*)"\x62\xfb\x0a" "decompress") @@ -497,10 +517,11 @@ QDEF(MP_QSTR_default, (const byte*)"\xce\x7d\x07" "default") QDEF(MP_QSTR_degrees, (const byte*)"\x02\x41\x07" "degrees") QDEF(MP_QSTR_deinit, (const byte*)"\x9e\x8d\x06" "deinit") QDEF(MP_QSTR_delattr, (const byte*)"\xdb\xc8\x07" "delattr") -QDEF(MP_QSTR_deleteSMS, (const byte*)"\xf1\xf1\x09" "deleteSMS") QDEF(MP_QSTR_deleter, (const byte*)"\x6e\xdb\x07" "deleter") +QDEF(MP_QSTR_deque, (const byte*)"\x05\x99\x05" "deque") QDEF(MP_QSTR_deselect, (const byte*)"\x0c\x9d\x08" "deselect") QDEF(MP_QSTR_device, (const byte*)"\x3d\x93\x06" "device") +QDEF(MP_QSTR_dhcp_hostname, (const byte*)"\xa2\x49\x0d" "dhcp_hostname") QDEF(MP_QSTR_dict, (const byte*)"\x3f\xfc\x04" "dict") QDEF(MP_QSTR_dict_view, (const byte*)"\x2d\xa9\x09" "dict_view") QDEF(MP_QSTR_difference, (const byte*)"\x72\x24\x0a" "difference") @@ -511,14 +532,23 @@ QDEF(MP_QSTR_disable, (const byte*)"\x91\x76\x07" "disable") QDEF(MP_QSTR_disable_irq, (const byte*)"\x04\x3a\x0b" "disable_irq") QDEF(MP_QSTR_discard, (const byte*)"\x0f\x71\x07" "discard") QDEF(MP_QSTR_disconnect, (const byte*)"\xa5\x85\x0a" "disconnect") -QDEF(MP_QSTR_disconnected_cb, (const byte*)"\xfa\x4c\x0f" "disconnected_cb") QDEF(MP_QSTR_display, (const byte*)"\x1f\x55\x07" "display") QDEF(MP_QSTR_dist, (const byte*)"\x2f\xfe\x04" "dist") QDEF(MP_QSTR_divmod, (const byte*)"\xb8\x04\x06" "divmod") +QDEF(MP_QSTR_dma_count, (const byte*)"\x11\x48\x09" "dma_count") +QDEF(MP_QSTR_dma_len, (const byte*)"\x55\xb3\x07" "dma_len") QDEF(MP_QSTR_doc, (const byte*)"\x2d\x1f\x03" "doc") +QDEF(MP_QSTR_drawCircle, (const byte*)"\x77\xb7\x0a" "drawCircle") +QDEF(MP_QSTR_drawLine, (const byte*)"\x8b\xd4\x08" "drawLine") +QDEF(MP_QSTR_drawPixel, (const byte*)"\x8d\xc0\x09" "drawPixel") +QDEF(MP_QSTR_drawRect, (const byte*)"\xa5\x70\x08" "drawRect") +QDEF(MP_QSTR_drawRoundRect, (const byte*)"\x27\xb6\x0d" "drawRoundRect") +QDEF(MP_QSTR_drawTriangle, (const byte*)"\xab\xf1\x0c" "drawTriangle") QDEF(MP_QSTR_ds18x20, (const byte*)"\x61\x26\x07" "ds18x20") +QDEF(MP_QSTR_dump, (const byte*)"\xe9\x2f\x04" "dump") QDEF(MP_QSTR_dumps, (const byte*)"\x7a\x2d\x05" "dumps") QDEF(MP_QSTR_duplex, (const byte*)"\xf5\x7b\x06" "duplex") +QDEF(MP_QSTR_duration, (const byte*)"\x7b\x4b\x08" "duration") QDEF(MP_QSTR_duty, (const byte*)"\x19\x2c\x04" "duty") QDEF(MP_QSTR_e, (const byte*)"\xc0\xb5\x01" "e") QDEF(MP_QSTR_ellipse, (const byte*)"\x0f\xdc\x07" "ellipse") @@ -528,28 +558,34 @@ QDEF(MP_QSTR_encode, (const byte*)"\x43\xca\x06" "encode") QDEF(MP_QSTR_encoding, (const byte*)"\x06\x9c\x08" "encoding") QDEF(MP_QSTR_end, (const byte*)"\x0a\x23\x03" "end") QDEF(MP_QSTR_endswith, (const byte*)"\x1b\xa3\x08" "endswith") -QDEF(MP_QSTR_endtask, (const byte*)"\xe7\x60\x07" "endtask") QDEF(MP_QSTR_enumerate, (const byte*)"\x71\xba\x09" "enumerate") QDEF(MP_QSTR_erf, (const byte*)"\x94\x23\x03" "erf") QDEF(MP_QSTR_erfc, (const byte*)"\x77\x96\x04" "erfc") QDEF(MP_QSTR_errno, (const byte*)"\xc1\x11\x05" "errno") QDEF(MP_QSTR_errorcode, (const byte*)"\x10\xdd\x09" "errorcode") +QDEF(MP_QSTR_espidf_info, (const byte*)"\xd9\x43\x0b" "espidf_info") QDEF(MP_QSTR_essid, (const byte*)"\x4d\xb1\x05" "essid") QDEF(MP_QSTR_eval, (const byte*)"\x9b\xa6\x04" "eval") QDEF(MP_QSTR_eventCB, (const byte*)"\xa8\xf7\x07" "eventCB") QDEF(MP_QSTR_events, (const byte*)"\x9a\xa2\x06" "events") -QDEF(MP_QSTR_exc_info, (const byte*)"\x0a\xff\x08" "exc_info") QDEF(MP_QSTR_exec, (const byte*)"\x1e\xc0\x04" "exec") QDEF(MP_QSTR_execfile, (const byte*)"\x58\x28\x08" "execfile") QDEF(MP_QSTR_exit, (const byte*)"\x85\xbe\x04" "exit") QDEF(MP_QSTR_exp, (const byte*)"\xc8\x24\x03" "exp") QDEF(MP_QSTR_expm1, (const byte*)"\x74\x72\x05" "expm1") +QDEF(MP_QSTR_expwm, (const byte*)"\xf2\x75\x05" "expwm") QDEF(MP_QSTR_extend, (const byte*)"\x63\xe8\x06" "extend") QDEF(MP_QSTR_fabs, (const byte*)"\x93\x12\x04" "fabs") +QDEF(MP_QSTR_factorial, (const byte*)"\xcc\x32\x09" "factorial") +QDEF(MP_QSTR_fgcolor, (const byte*)"\xb9\xc6\x07" "fgcolor") QDEF(MP_QSTR_file, (const byte*)"\xc3\x34\x04" "file") QDEF(MP_QSTR_fileno, (const byte*)"\x82\x76\x06" "fileno") QDEF(MP_QSTR_fill, (const byte*)"\xca\x34\x04" "fill") -QDEF(MP_QSTR_fill_rect, (const byte*)"\x35\xed\x09" "fill_rect") +QDEF(MP_QSTR_fillCircle, (const byte*)"\x58\x13\x0a" "fillCircle") +QDEF(MP_QSTR_fillRect, (const byte*)"\x0a\xd8\x08" "fillRect") +QDEF(MP_QSTR_fillRoundRect, (const byte*)"\x28\xd2\x0d" "fillRoundRect") +QDEF(MP_QSTR_fillScreen, (const byte*)"\xe6\xbb\x0a" "fillScreen") +QDEF(MP_QSTR_fillTriangle, (const byte*)"\x04\x8f\x0c" "fillTriangle") QDEF(MP_QSTR_fillcolor, (const byte*)"\x77\x7f\x09" "fillcolor") QDEF(MP_QSTR_filter, (const byte*)"\x25\xbe\x06" "filter") QDEF(MP_QSTR_find, (const byte*)"\x00\x34\x04" "find") @@ -557,59 +593,53 @@ QDEF(MP_QSTR_firstbit, (const byte*)"\x20\x39\x08" "firstbit") QDEF(MP_QSTR_fixedwidth, (const byte*)"\x35\x36\x0a" "fixedwidth") QDEF(MP_QSTR_flags, (const byte*)"\xfa\x8f\x05" "flags") QDEF(MP_QSTR_float, (const byte*)"\x35\x44\x05" "float") +QDEF(MP_QSTR_float_precision, (const byte*)"\x9c\x70\x0f" "float_precision") QDEF(MP_QSTR_floor, (const byte*)"\x7d\x46\x05" "floor") QDEF(MP_QSTR_flush, (const byte*)"\x61\xc1\x05" "flush") QDEF(MP_QSTR_fmod, (const byte*)"\xe5\x44\x04" "fmod") QDEF(MP_QSTR_font, (const byte*)"\x96\x2b\x04" "font") QDEF(MP_QSTR_fontSize, (const byte*)"\x93\x3e\x08" "fontSize") QDEF(MP_QSTR_format, (const byte*)"\x26\x33\x06" "format") -QDEF(MP_QSTR_framebuf, (const byte*)"\x69\x82\x08" "framebuf") -QDEF(MP_QSTR_free, (const byte*)"\xf1\x3a\x04" "free") QDEF(MP_QSTR_freq, (const byte*)"\xe5\x3a\x04" "freq") QDEF(MP_QSTR_frexp, (const byte*)"\x1c\x98\x05" "frexp") QDEF(MP_QSTR_from_bytes, (const byte*)"\x35\x74\x0a" "from_bytes") -QDEF(MP_QSTR_from_nvs, (const byte*)"\x67\x62\x08" "from_nvs") QDEF(MP_QSTR_fromkeys, (const byte*)"\x37\xbd\x08" "fromkeys") QDEF(MP_QSTR_frozenset, (const byte*)"\xed\x9c\x09" "frozenset") -QDEF(MP_QSTR_ftp, (const byte*)"\x47\x39\x03" "ftp") -QDEF(MP_QSTR_ftp_get, (const byte*)"\xae\x67\x07" "ftp_get") -QDEF(MP_QSTR_ftp_list, (const byte*)"\xda\xd1\x08" "ftp_list") -QDEF(MP_QSTR_ftp_put, (const byte*)"\x69\x22\x07" "ftp_put") QDEF(MP_QSTR_func, (const byte*)"\x1b\x68\x04" "func") QDEF(MP_QSTR_function, (const byte*)"\x27\x02\x08" "function") QDEF(MP_QSTR_gamma, (const byte*)"\x02\x90\x05" "gamma") QDEF(MP_QSTR_gc, (const byte*)"\x61\x6e\x02" "gc") QDEF(MP_QSTR_generator, (const byte*)"\x96\xc3\x09" "generator") QDEF(MP_QSTR_get, (const byte*)"\x33\x3b\x03" "get") -QDEF(MP_QSTR_getCalib, (const byte*)"\xd6\xaf\x08" "getCalib") +QDEF(MP_QSTR_getCursor, (const byte*)"\x99\xb4\x09" "getCursor") +QDEF(MP_QSTR_getMainID, (const byte*)"\x35\xc1\x09" "getMainID") QDEF(MP_QSTR_getReplID, (const byte*)"\xb5\xe5\x09" "getReplID") QDEF(MP_QSTR_getSelfName, (const byte*)"\x68\xaf\x0b" "getSelfName") QDEF(MP_QSTR_getThreadName, (const byte*)"\xba\xa7\x0d" "getThreadName") -QDEF(MP_QSTR_getTouchType, (const byte*)"\x2e\x4a\x0c" "getTouchType") +QDEF(MP_QSTR_get_bg, (const byte*)"\x89\x40\x06" "get_bg") +QDEF(MP_QSTR_get_fg, (const byte*)"\x0d\x40\x06" "get_fg") QDEF(MP_QSTR_get_pwrmode, (const byte*)"\x7a\x71\x0b" "get_pwrmode") QDEF(MP_QSTR_get_res, (const byte*)"\x88\x95\x07" "get_res") QDEF(MP_QSTR_getaddrinfo, (const byte*)"\x6e\x18\x0b" "getaddrinfo") QDEF(MP_QSTR_getattr, (const byte*)"\xc0\x17\x07" "getattr") QDEF(MP_QSTR_getcwd, (const byte*)"\x03\xd0\x06" "getcwd") QDEF(MP_QSTR_getdata, (const byte*)"\x23\xd7\x07" "getdata") +QDEF(MP_QSTR_getdrive, (const byte*)"\x7f\xf6\x08" "getdrive") QDEF(MP_QSTR_getmsg, (const byte*)"\x0a\x1b\x06" "getmsg") QDEF(MP_QSTR_getnotification, (const byte*)"\x3e\xa6\x0f" "getnotification") QDEF(MP_QSTR_getpeercert, (const byte*)"\xb1\x92\x0b" "getpeercert") QDEF(MP_QSTR_getrandbits, (const byte*)"\x66\x7d\x0b" "getrandbits") QDEF(MP_QSTR_getter, (const byte*)"\x90\xb2\x06" "getter") -QDEF(MP_QSTR_gettouch, (const byte*)"\xb6\x12\x08" "gettouch") QDEF(MP_QSTR_getvalue, (const byte*)"\x78\xac\x08" "getvalue") QDEF(MP_QSTR_globals, (const byte*)"\x9d\x49\x07" "globals") QDEF(MP_QSTR_gmtime, (const byte*)"\x5a\x8e\x06" "gmtime") QDEF(MP_QSTR_group, (const byte*)"\xba\xb0\x05" "group") -QDEF(MP_QSTR_gsm, (const byte*)"\xfc\x3c\x03" "gsm") -QDEF(MP_QSTR_gsmnum, (const byte*)"\x6a\x23\x06" "gsmnum") +QDEF(MP_QSTR_h, (const byte*)"\xcd\xb5\x01" "h") QDEF(MP_QSTR_handler, (const byte*)"\xdd\x5d\x07" "handler") QDEF(MP_QSTR_hasattr, (const byte*)"\x8c\xb0\x07" "hasattr") QDEF(MP_QSTR_hash, (const byte*)"\xb7\x70\x04" "hash") QDEF(MP_QSTR_hashlib, (const byte*)"\x10\x6d\x07" "hashlib") QDEF(MP_QSTR_hastouch, (const byte*)"\x7a\x3f\x08" "hastouch") -QDEF(MP_QSTR_hdrlen, (const byte*)"\x7c\xb1\x06" "hdrlen") QDEF(MP_QSTR_heap_info, (const byte*)"\x68\x1d\x09" "heap_info") QDEF(MP_QSTR_heap_lock, (const byte*)"\xad\x8c\x09" "heap_lock") QDEF(MP_QSTR_heap_unlock, (const byte*)"\x56\x2d\x0b" "heap_unlock") @@ -622,10 +652,10 @@ QDEF(MP_QSTR_help, (const byte*)"\x94\x5c\x04" "help") QDEF(MP_QSTR_hex, (const byte*)"\x70\x50\x03" "hex") QDEF(MP_QSTR_hexlify, (const byte*)"\x2a\x7f\x07" "hexlify") QDEF(MP_QSTR_hidden, (const byte*)"\xef\x48\x06" "hidden") -QDEF(MP_QSTR_hline, (const byte*)"\x83\x3c\x05" "hline") -QDEF(MP_QSTR_hostname, (const byte*)"\xc2\x95\x08" "hostname") +QDEF(MP_QSTR_hide, (const byte*)"\x85\x4b\x04" "hide") QDEF(MP_QSTR_hsb2rgb, (const byte*)"\xd9\xce\x07" "hsb2rgb") QDEF(MP_QSTR_hue, (const byte*)"\x7d\x52\x03" "hue") +QDEF(MP_QSTR_hypot, (const byte*)"\x1f\x4f\x05" "hypot") QDEF(MP_QSTR_id, (const byte*)"\x28\x6f\x02" "id") QDEF(MP_QSTR_idle, (const byte*)"\xa1\xdc\x04" "idle") QDEF(MP_QSTR_ifconfig, (const byte*)"\xe0\x41\x08" "ifconfig") @@ -633,22 +663,25 @@ QDEF(MP_QSTR_ilistdir, (const byte*)"\x71\x6a\x08" "ilistdir") QDEF(MP_QSTR_imag, (const byte*)"\x47\xb7\x04" "imag") QDEF(MP_QSTR_image, (const byte*)"\x42\xa0\x05" "image") QDEF(MP_QSTR_implementation, (const byte*)"\x17\x2d\x0e" "implementation") +QDEF(MP_QSTR_in, (const byte*)"\x22\x6f\x02" "in") QDEF(MP_QSTR_index, (const byte*)"\x7b\x28\x05" "index") QDEF(MP_QSTR_info, (const byte*)"\xeb\xb3\x04" "info") QDEF(MP_QSTR_init, (const byte*)"\x1f\xb4\x04" "init") QDEF(MP_QSTR_input, (const byte*)"\x73\x5a\x05" "input") QDEF(MP_QSTR_insert, (const byte*)"\x12\x54\x06" "insert") -QDEF(MP_QSTR_instance, (const byte*)"\x8c\x54\x08" "instance") QDEF(MP_QSTR_int, (const byte*)"\x16\x53\x03" "int") QDEF(MP_QSTR_internal_temp, (const byte*)"\xf1\x46\x0d" "internal_temp") +QDEF(MP_QSTR_internal_vdd, (const byte*)"\x4b\x13\x0c" "internal_vdd") QDEF(MP_QSTR_intersection, (const byte*)"\x28\x2a\x0c" "intersection") QDEF(MP_QSTR_intersection_update, (const byte*)"\x06\xdd\x13" "intersection_update") QDEF(MP_QSTR_invert, (const byte*)"\xb7\x00\x06" "invert") +QDEF(MP_QSTR_inverted, (const byte*)"\x56\x16\x08" "inverted") QDEF(MP_QSTR_invrot, (const byte*)"\x9d\xcb\x06" "invrot") QDEF(MP_QSTR_io, (const byte*)"\x23\x6f\x02" "io") QDEF(MP_QSTR_ioctl, (const byte*)"\x78\xc2\x05" "ioctl") QDEF(MP_QSTR_ipoll, (const byte*)"\x53\x5d\x05" "ipoll") -QDEF(MP_QSTR_irq, (const byte*)"\x8f\x56\x03" "irq") +QDEF(MP_QSTR_irqvalue, (const byte*)"\x84\xf4\x08" "irqvalue") +QDEF(MP_QSTR_is_ready, (const byte*)"\x0b\x00\x08" "is_ready") QDEF(MP_QSTR_isalpha, (const byte*)"\xeb\x37\x07" "isalpha") QDEF(MP_QSTR_isconnected, (const byte*)"\x80\x99\x0b" "isconnected") QDEF(MP_QSTR_isdigit, (const byte*)"\xa8\x9a\x07" "isdigit") @@ -673,7 +706,6 @@ QDEF(MP_QSTR_iterator, (const byte*)"\x47\xbe\x08" "iterator") QDEF(MP_QSTR_join, (const byte*)"\xa7\x5c\x04" "join") QDEF(MP_QSTR_json, (const byte*)"\xfd\xd1\x04" "json") QDEF(MP_QSTR_kbd_intr, (const byte*)"\xf6\x13\x08" "kbd_intr") -QDEF(MP_QSTR_keepalive, (const byte*)"\x69\x05\x09" "keepalive") QDEF(MP_QSTR_keepends, (const byte*)"\x62\x8b\x08" "keepends") QDEF(MP_QSTR_key, (const byte*)"\x32\x6d\x03" "key") QDEF(MP_QSTR_keys, (const byte*)"\x01\x13\x04" "keys") @@ -690,7 +722,6 @@ QDEF(MP_QSTR_list, (const byte*)"\x27\x1d\x04" "list") QDEF(MP_QSTR_listdir, (const byte*)"\x98\xe3\x07" "listdir") QDEF(MP_QSTR_listen, (const byte*)"\xcc\x0e\x06" "listen") QDEF(MP_QSTR_little, (const byte*)"\x89\x6a\x06" "little") -QDEF(MP_QSTR_llist, (const byte*)"\xeb\x40\x05" "llist") QDEF(MP_QSTR_load, (const byte*)"\x63\x24\x04" "load") QDEF(MP_QSTR_loads, (const byte*)"\xb0\xb0\x05" "loads") QDEF(MP_QSTR_locals, (const byte*)"\x3b\xa1\x06" "locals") @@ -702,19 +733,18 @@ QDEF(MP_QSTR_log2, (const byte*)"\x73\x23\x04" "log2") QDEF(MP_QSTR_loglevel, (const byte*)"\x37\x99\x08" "loglevel") QDEF(MP_QSTR_lower, (const byte*)"\xc6\xcb\x05" "lower") QDEF(MP_QSTR_lstrip, (const byte*)"\xe5\xb9\x06" "lstrip") -QDEF(MP_QSTR_mDNS, (const byte*)"\xd1\x48\x04" "mDNS") +QDEF(MP_QSTR_m5flow, (const byte*)"\x0f\xa4\x06" "m5flow") +QDEF(MP_QSTR_m5ui, (const byte*)"\x81\x2b\x04" "m5ui") QDEF(MP_QSTR_mac, (const byte*)"\xaa\x43\x03" "mac") QDEF(MP_QSTR_machine, (const byte*)"\x60\xab\x07" "machine") +QDEF(MP_QSTR_mainAcceptMsg, (const byte*)"\xd7\x44\x0d" "mainAcceptMsg") QDEF(MP_QSTR_makefile, (const byte*)"\xc1\xd5\x08" "makefile") QDEF(MP_QSTR_map, (const byte*)"\xb9\x43\x03" "map") QDEF(MP_QSTR_match, (const byte*)"\x96\x22\x05" "match") QDEF(MP_QSTR_math, (const byte*)"\x35\xbb\x04" "math") QDEF(MP_QSTR_max, (const byte*)"\xb1\x43\x03" "max") -QDEF(MP_QSTR_maxfsize, (const byte*)"\xd2\x89\x08" "maxfsize") -QDEF(MP_QSTR_maxres, (const byte*)"\x55\xbb\x06" "maxres") QDEF(MP_QSTR_maxsize, (const byte*)"\xd4\x70\x07" "maxsize") -QDEF(MP_QSTR_mdc, (const byte*)"\x4f\x44\x03" "mdc") -QDEF(MP_QSTR_mdio, (const byte*)"\x8a\xcc\x04" "mdio") +QDEF(MP_QSTR_maxspeed, (const byte*)"\x56\x75\x08" "maxspeed") QDEF(MP_QSTR_mem, (const byte*)"\x20\x44\x03" "mem") QDEF(MP_QSTR_mem16, (const byte*)"\x07\xca\x05" "mem16") QDEF(MP_QSTR_mem32, (const byte*)"\x41\xca\x05" "mem32") @@ -739,17 +769,17 @@ QDEF(MP_QSTR_modules, (const byte*)"\xec\xd1\x07" "modules") QDEF(MP_QSTR_mosi, (const byte*)"\x1d\xc2\x04" "mosi") QDEF(MP_QSTR_mount, (const byte*)"\xa8\x0d\x05" "mount") QDEF(MP_QSTR_mountsd, (const byte*)"\x5f\x1e\x07" "mountsd") -QDEF(MP_QSTR_mqtt, (const byte*)"\x39\xfb\x04" "mqtt") -QDEF(MP_QSTR_msg, (const byte*)"\x7c\x46\x03" "msg") +QDEF(MP_QSTR_mpycore, (const byte*)"\x7a\xcb\x07" "mpycore") QDEF(MP_QSTR_name, (const byte*)"\xa2\x75\x04" "name") QDEF(MP_QSTR_namedtuple, (const byte*)"\x1e\x16\x0a" "namedtuple") QDEF(MP_QSTR_nbytes, (const byte*)"\xd2\x76\x06" "nbytes") +QDEF(MP_QSTR_nchannels, (const byte*)"\x5b\x93\x09" "nchannels") QDEF(MP_QSTR_network, (const byte*)"\x5b\x28\x07" "network") QDEF(MP_QSTR_next, (const byte*)"\x42\x88\x04" "next") -QDEF(MP_QSTR_nodecode, (const byte*)"\x28\x0f\x08" "nodecode") QDEF(MP_QSTR_nodename, (const byte*)"\x62\xab\x08" "nodename") QDEF(MP_QSTR_notify, (const byte*)"\x06\x1c\x06" "notify") QDEF(MP_QSTR_now, (const byte*)"\xb3\x57\x03" "now") +QDEF(MP_QSTR_nsamples, (const byte*)"\x9e\x6e\x08" "nsamples") QDEF(MP_QSTR_ntp_state, (const byte*)"\x07\xec\x09" "ntp_state") QDEF(MP_QSTR_ntp_sync, (const byte*)"\xd7\xfc\x08" "ntp_sync") QDEF(MP_QSTR_num, (const byte*)"\x73\x5b\x03" "num") @@ -762,32 +792,32 @@ QDEF(MP_QSTR_nvs_setstr, (const byte*)"\xe6\x58\x0a" "nvs_setstr") QDEF(MP_QSTR_object, (const byte*)"\x90\x8d\x06" "object") QDEF(MP_QSTR_oct, (const byte*)"\xfd\x5c\x03" "oct") QDEF(MP_QSTR_off, (const byte*)"\x8a\x5c\x03" "off") +QDEF(MP_QSTR_offset, (const byte*)"\x48\x3c\x06" "offset") QDEF(MP_QSTR_on, (const byte*)"\x64\x6f\x02" "on") QDEF(MP_QSTR_open, (const byte*)"\xd1\x3a\x04" "open") QDEF(MP_QSTR_opt, (const byte*)"\xce\x5e\x03" "opt") QDEF(MP_QSTR_opt_level, (const byte*)"\x87\x67\x09" "opt_level") -QDEF(MP_QSTR_options, (const byte*)"\xf5\x63\x07" "options") QDEF(MP_QSTR_ord, (const byte*)"\x1c\x5e\x03" "ord") QDEF(MP_QSTR_orient, (const byte*)"\x8e\x81\x06" "orient") QDEF(MP_QSTR_os, (const byte*)"\x79\x6f\x02" "os") +QDEF(MP_QSTR_out, (const byte*)"\x2b\x5f\x03" "out") QDEF(MP_QSTR_outline, (const byte*)"\x65\xf7\x07" "outline") QDEF(MP_QSTR_owb, (const byte*)"\x7f\x5f\x03" "owb") QDEF(MP_QSTR_pack, (const byte*)"\xbc\xd1\x04" "pack") QDEF(MP_QSTR_pack_into, (const byte*)"\x1f\xa9\x09" "pack_into") QDEF(MP_QSTR_pagesize, (const byte*)"\x13\x28\x08" "pagesize") -QDEF(MP_QSTR_params, (const byte*)"\x79\xe2\x06" "params") QDEF(MP_QSTR_parity, (const byte*)"\x42\x05\x06" "parity") QDEF(MP_QSTR_partition, (const byte*)"\x87\xe5\x09" "partition") QDEF(MP_QSTR_password, (const byte*)"\x9a\x6f\x08" "password") QDEF(MP_QSTR_path, (const byte*)"\x88\xce\x04" "path") QDEF(MP_QSTR_pattern, (const byte*)"\x2d\xcc\x07" "pattern") QDEF(MP_QSTR_pause, (const byte*)"\xd7\xbd\x05" "pause") +QDEF(MP_QSTR_peek, (const byte*)"\x7e\xc1\x04" "peek") QDEF(MP_QSTR_peektime, (const byte*)"\x8b\x5c\x08" "peektime") +QDEF(MP_QSTR_pend_throw, (const byte*)"\xf3\x74\x0a" "pend_throw") QDEF(MP_QSTR_period, (const byte*)"\xa0\xa0\x06" "period") QDEF(MP_QSTR_phase, (const byte*)"\x6a\xd5\x05" "phase") -QDEF(MP_QSTR_phy_addr, (const byte*)"\xa8\xcc\x08" "phy_addr") QDEF(MP_QSTR_phy_mode, (const byte*)"\x38\xa0\x08" "phy_mode") -QDEF(MP_QSTR_phy_type, (const byte*)"\x83\xc7\x08" "phy_type") QDEF(MP_QSTR_pi, (const byte*)"\x1c\x70\x02" "pi") QDEF(MP_QSTR_pin, (const byte*)"\xf2\x73\x03" "pin") QDEF(MP_QSTR_pins, (const byte*)"\x41\xf2\x04" "pins") @@ -800,27 +830,20 @@ QDEF(MP_QSTR_poll, (const byte*)"\x9a\xd9\x04" "poll") QDEF(MP_QSTR_polygon, (const byte*)"\x29\xf9\x07" "polygon") QDEF(MP_QSTR_pop, (const byte*)"\x2a\x73\x03" "pop") QDEF(MP_QSTR_popitem, (const byte*)"\xbf\x2c\x07" "popitem") -QDEF(MP_QSTR_port, (const byte*)"\x5c\xd8\x04" "port") +QDEF(MP_QSTR_popleft, (const byte*)"\x71\x9a\x07" "popleft") QDEF(MP_QSTR_pos, (const byte*)"\x29\x73\x03" "pos") -QDEF(MP_QSTR_post, (const byte*)"\x3d\xd8\x04" "post") QDEF(MP_QSTR_pow, (const byte*)"\x2d\x73\x03" "pow") -QDEF(MP_QSTR_power, (const byte*)"\xda\xed\x05" "power") QDEF(MP_QSTR_print, (const byte*)"\x54\xc6\x05" "print") QDEF(MP_QSTR_print_exception, (const byte*)"\x1c\x22\x0f" "print_exception") -QDEF(MP_QSTR_printable, (const byte*)"\xbe\x5d\x09" "printable") +QDEF(MP_QSTR_println, (const byte*)"\xd6\xa7\x07" "println") QDEF(MP_QSTR_probereqCB, (const byte*)"\xc8\x0e\x0a" "probereqCB") QDEF(MP_QSTR_progress, (const byte*)"\xd8\x67\x08" "progress") QDEF(MP_QSTR_property, (const byte*)"\xc2\x29\x08" "property") -QDEF(MP_QSTR_protocol, (const byte*)"\x33\xf5\x08" "protocol") -QDEF(MP_QSTR_publish, (const byte*)"\x5c\x6a\x07" "publish") -QDEF(MP_QSTR_published_cb, (const byte*)"\x23\x08\x0c" "published_cb") QDEF(MP_QSTR_pull, (const byte*)"\x80\x7d\x04" "pull") QDEF(MP_QSTR_push, (const byte*)"\xbb\x7e\x04" "push") QDEF(MP_QSTR_put, (const byte*)"\x74\x70\x03" "put") -QDEF(MP_QSTR_qos, (const byte*)"\xe8\x77\x03" "qos") +QDEF(MP_QSTR_qrcode, (const byte*)"\xcb\x8c\x06" "qrcode") QDEF(MP_QSTR_qstr_info, (const byte*)"\xb0\x81\x09" "qstr_info") -QDEF(MP_QSTR_queryHost, (const byte*)"\xaf\x72\x09" "queryHost") -QDEF(MP_QSTR_queryService, (const byte*)"\x52\x9b\x0c" "queryService") QDEF(MP_QSTR_r, (const byte*)"\xd7\xb5\x01" "r") QDEF(MP_QSTR_radians, (const byte*)"\x87\x3f\x07" "radians") QDEF(MP_QSTR_rainbow, (const byte*)"\x8b\xc7\x07" "rainbow") @@ -828,16 +851,15 @@ QDEF(MP_QSTR_randint, (const byte*)"\xaf\xdc\x07" "randint") QDEF(MP_QSTR_random, (const byte*)"\xbe\x2c\x06" "random") QDEF(MP_QSTR_randrange, (const byte*)"\xa3\x3e\x09" "randrange") QDEF(MP_QSTR_range, (const byte*)"\x1a\x5e\x05" "range") -QDEF(MP_QSTR_raw, (const byte*)"\xe1\x8b\x03" "raw") +QDEF(MP_QSTR_rate, (const byte*)"\x47\x08\x04" "rate") QDEF(MP_QSTR_re, (const byte*)"\xd2\x70\x02" "re") QDEF(MP_QSTR_read, (const byte*)"\xb7\xf9\x04" "read") -QDEF(MP_QSTR_readPixel, (const byte*)"\x5f\x5d\x09" "readPixel") -QDEF(MP_QSTR_readSMS, (const byte*)"\x7a\x6a\x07" "readSMS") QDEF(MP_QSTR_read_byte, (const byte*)"\x02\x61\x09" "read_byte") QDEF(MP_QSTR_read_bytes, (const byte*)"\x31\x81\x0a" "read_bytes") QDEF(MP_QSTR_read_string, (const byte*)"\xfd\x18\x0b" "read_string") QDEF(MP_QSTR_read_temp, (const byte*)"\xe4\x2e\x09" "read_temp") QDEF(MP_QSTR_read_tempint, (const byte*)"\x57\x05\x0c" "read_tempint") +QDEF(MP_QSTR_read_timed, (const byte*)"\xf9\xfe\x0a" "read_timed") QDEF(MP_QSTR_readbyte, (const byte*)"\x7d\xf0\x08" "readbyte") QDEF(MP_QSTR_readbytes, (const byte*)"\x6e\x00\x09" "readbytes") QDEF(MP_QSTR_readfrom, (const byte*)"\x41\xb1\x08" "readfrom") @@ -848,6 +870,7 @@ QDEF(MP_QSTR_readinto, (const byte*)"\x4b\xbf\x08" "readinto") QDEF(MP_QSTR_readline, (const byte*)"\xf9\x19\x08" "readline") QDEF(MP_QSTR_readlines, (const byte*)"\x6a\x59\x09" "readlines") QDEF(MP_QSTR_readln, (const byte*)"\x35\x50\x06" "readln") +QDEF(MP_QSTR_readmv, (const byte*)"\x4c\x50\x06" "readmv") QDEF(MP_QSTR_readonly, (const byte*)"\x03\x89\x08" "readonly") QDEF(MP_QSTR_readraw, (const byte*)"\x13\x0a\x07" "readraw") QDEF(MP_QSTR_real, (const byte*)"\xbf\xf9\x04" "real") @@ -858,23 +881,21 @@ QDEF(MP_QSTR_redirectlog, (const byte*)"\x5b\x4c\x0b" "redirectlog") QDEF(MP_QSTR_register, (const byte*)"\xac\xa1\x08" "register") QDEF(MP_QSTR_release, (const byte*)"\xec\x8f\x07" "release") QDEF(MP_QSTR_remove, (const byte*)"\x63\x8a\x06" "remove") -QDEF(MP_QSTR_removeService, (const byte*)"\x5e\xed\x0d" "removeService") QDEF(MP_QSTR_rename, (const byte*)"\x35\x18\x06" "rename") QDEF(MP_QSTR_replAcceptMsg, (const byte*)"\xd7\x84\x0d" "replAcceptMsg") QDEF(MP_QSTR_replace, (const byte*)"\x49\x25\x07" "replace") QDEF(MP_QSTR_repr, (const byte*)"\xd0\xf7\x04" "repr") QDEF(MP_QSTR_reset, (const byte*)"\x10\xf4\x05" "reset") +QDEF(MP_QSTR_resetWDT, (const byte*)"\x97\x2b\x08" "resetWDT") +QDEF(MP_QSTR_resetbusy, (const byte*)"\x2d\x98\x09" "resetbusy") QDEF(MP_QSTR_resetwin, (const byte*)"\x80\xa8\x08" "resetwin") -QDEF(MP_QSTR_reshot, (const byte*)"\x52\xa2\x06" "reshot") -QDEF(MP_QSTR_response, (const byte*)"\xe6\x94\x08" "response") +QDEF(MP_QSTR_reshoot, (const byte*)"\x1d\xeb\x07" "reshoot") QDEF(MP_QSTR_restorelog, (const byte*)"\x09\x2e\x0a" "restorelog") QDEF(MP_QSTR_restorewin, (const byte*)"\x9d\x8d\x0a" "restorewin") QDEF(MP_QSTR_resume, (const byte*)"\x5c\xb9\x06" "resume") -QDEF(MP_QSTR_retain, (const byte*)"\x60\x2b\x06" "retain") QDEF(MP_QSTR_reverse, (const byte*)"\x25\x2a\x07" "reverse") QDEF(MP_QSTR_reversed, (const byte*)"\xa1\x6e\x08" "reversed") QDEF(MP_QSTR_rfind, (const byte*)"\xd2\x9c\x05" "rfind") -QDEF(MP_QSTR_rfoff, (const byte*)"\x5e\xa5\x05" "rfoff") QDEF(MP_QSTR_rindex, (const byte*)"\xe9\x2b\x06" "rindex") QDEF(MP_QSTR_rmdir, (const byte*)"\x45\xa7\x05" "rmdir") QDEF(MP_QSTR_rom_code, (const byte*)"\xa7\x3c\x08" "rom_code") @@ -890,6 +911,8 @@ QDEF(MP_QSTR_rts, (const byte*)"\x50\x89\x03" "rts") QDEF(MP_QSTR_rx, (const byte*)"\xcf\x70\x02" "rx") QDEF(MP_QSTR_ry, (const byte*)"\xce\x70\x02" "ry") QDEF(MP_QSTR_samecore, (const byte*)"\x24\xe0\x08" "samecore") +QDEF(MP_QSTR_sample_rate, (const byte*)"\x7e\x03\x0b" "sample_rate") +QDEF(MP_QSTR_samplerate, (const byte*)"\xc1\x1c\x0a" "samplerate") QDEF(MP_QSTR_saturation, (const byte*)"\x59\x68\x0a" "saturation") QDEF(MP_QSTR_savewin, (const byte*)"\x74\x5e\x07" "savewin") QDEF(MP_QSTR_scale, (const byte*)"\x7d\x51\x05" "scale") @@ -898,19 +921,15 @@ QDEF(MP_QSTR_schedule, (const byte*)"\xe0\xac\x08" "schedule") QDEF(MP_QSTR_sck, (const byte*)"\xfe\x8f\x03" "sck") QDEF(MP_QSTR_scl, (const byte*)"\xf9\x8f\x03" "scl") QDEF(MP_QSTR_screensize, (const byte*)"\x2c\xe1\x0a" "screensize") -QDEF(MP_QSTR_scroll, (const byte*)"\x28\x5a\x06" "scroll") QDEF(MP_QSTR_sda, (const byte*)"\x53\x8f\x03" "sda") QDEF(MP_QSTR_sdconfig, (const byte*)"\xb8\x4d\x08" "sdconfig") QDEF(MP_QSTR_search, (const byte*)"\xab\xc1\x06" "search") QDEF(MP_QSTR_secs, (const byte*)"\x43\x75\x04" "secs") -QDEF(MP_QSTR_secure, (const byte*)"\x12\xd0\x06" "secure") QDEF(MP_QSTR_seed, (const byte*)"\x92\x75\x04" "seed") QDEF(MP_QSTR_seek, (const byte*)"\x9d\x75\x04" "seek") QDEF(MP_QSTR_select, (const byte*)"\x8d\x41\x06" "select") QDEF(MP_QSTR_send, (const byte*)"\xb9\x76\x04" "send") -QDEF(MP_QSTR_sendSMS, (const byte*)"\x34\xcf\x07" "sendSMS") QDEF(MP_QSTR_sendall, (const byte*)"\x38\x9f\x07" "sendall") -QDEF(MP_QSTR_sendmail, (const byte*)"\x70\x62\x08" "sendmail") QDEF(MP_QSTR_sendmsg, (const byte*)"\x40\x8d\x07" "sendmsg") QDEF(MP_QSTR_sendto, (const byte*)"\x22\x03\x06" "sendto") QDEF(MP_QSTR_sep, (const byte*)"\x23\x8f\x03" "sep") @@ -918,12 +937,30 @@ QDEF(MP_QSTR_seq, (const byte*)"\x22\x8f\x03" "seq") QDEF(MP_QSTR_server, (const byte*)"\xc0\x28\x06" "server") QDEF(MP_QSTR_server_hostname, (const byte*)"\x58\xef\x0f" "server_hostname") QDEF(MP_QSTR_server_side, (const byte*)"\x64\xef\x0b" "server_side") -QDEF(MP_QSTR_service, (const byte*)"\x98\x75\x07" "service") QDEF(MP_QSTR_set, (const byte*)"\x27\x8f\x03" "set") -QDEF(MP_QSTR_setCalib, (const byte*)"\x42\x7a\x08" "setCalib") +QDEF(MP_QSTR_setBgColor, (const byte*)"\x9f\xfc\x0a" "setBgColor") +QDEF(MP_QSTR_setBorderColor, (const byte*)"\xd6\x7c\x0e" "setBorderColor") +QDEF(MP_QSTR_setBrightness, (const byte*)"\x0e\xb3\x0d" "setBrightness") +QDEF(MP_QSTR_setColor, (const byte*)"\x5a\xc4\x08" "setColor") +QDEF(MP_QSTR_setCursor, (const byte*)"\x8d\x78\x09" "setCursor") +QDEF(MP_QSTR_setFgColor, (const byte*)"\x9b\x0c\x0a" "setFgColor") +QDEF(MP_QSTR_setFont, (const byte*)"\xd4\x31\x07" "setFont") QDEF(MP_QSTR_setHSB, (const byte*)"\xbe\xcd\x06" "setHSB") QDEF(MP_QSTR_setHSBint, (const byte*)"\xcd\x1a\x09" "setHSBint") +QDEF(MP_QSTR_setPosition, (const byte*)"\x5e\x8d\x0b" "setPosition") +QDEF(MP_QSTR_setRotate, (const byte*)"\x9e\xfb\x09" "setRotate") +QDEF(MP_QSTR_setRotation, (const byte*)"\x33\x25\x0b" "setRotation") +QDEF(MP_QSTR_setSize, (const byte*)"\x62\x9b\x07" "setSize") +QDEF(MP_QSTR_setText, (const byte*)"\xda\x17\x07" "setText") +QDEF(MP_QSTR_setTextColor, (const byte*)"\x47\x4a\x0c" "setTextColor") +QDEF(MP_QSTR_setTitle, (const byte*)"\xe7\x30\x08" "setTitle") +QDEF(MP_QSTR_setWDT, (const byte*)"\xc0\xc0\x06" "setWDT") QDEF(MP_QSTR_setWhite, (const byte*)"\xc0\x4f\x08" "setWhite") +QDEF(MP_QSTR_set_adc_pin, (const byte*)"\x56\x16\x0b" "set_adc_pin") +QDEF(MP_QSTR_set_bg, (const byte*)"\x1d\xe6\x06" "set_bg") +QDEF(MP_QSTR_set_dac_mode, (const byte*)"\xa2\xd0\x0c" "set_dac_mode") +QDEF(MP_QSTR_set_fg, (const byte*)"\x99\xe6\x06" "set_fg") +QDEF(MP_QSTR_set_pin, (const byte*)"\x0f\x6c\x07" "set_pin") QDEF(MP_QSTR_set_res, (const byte*)"\x9c\x65\x07" "set_res") QDEF(MP_QSTR_setattr, (const byte*)"\xd4\xa8\x07" "setattr") QDEF(MP_QSTR_setblocking, (const byte*)"\x6e\x18\x0b" "setblocking") @@ -940,15 +977,16 @@ QDEF(MP_QSTR_sides, (const byte*)"\x4d\xb8\x05" "sides") QDEF(MP_QSTR_sin, (const byte*)"\xb1\x90\x03" "sin") QDEF(MP_QSTR_single, (const byte*)"\x3f\x20\x06" "single") QDEF(MP_QSTR_sinh, (const byte*)"\xb9\xa6\x04" "sinh") +QDEF(MP_QSTR_size, (const byte*)"\x20\xa5\x04" "size") QDEF(MP_QSTR_sizeof, (const byte*)"\x49\x73\x06" "sizeof") QDEF(MP_QSTR_slave_addr, (const byte*)"\xe4\x95\x0a" "slave_addr") QDEF(MP_QSTR_slave_bufflen, (const byte*)"\x07\x8f\x0d" "slave_bufflen") -QDEF(MP_QSTR_slavewrite, (const byte*)"\x35\xca\x0a" "slavewrite") +QDEF(MP_QSTR_slave_busy, (const byte*)"\x2a\x9a\x0a" "slave_busy") +QDEF(MP_QSTR_slave_rolen, (const byte*)"\x0d\x0f\x0b" "slave_rolen") QDEF(MP_QSTR_sleep, (const byte*)"\xea\x27\x05" "sleep") QDEF(MP_QSTR_sleep_ms, (const byte*)"\x0b\x63\x08" "sleep_ms") QDEF(MP_QSTR_sleep_us, (const byte*)"\x13\x60\x08" "sleep_us") QDEF(MP_QSTR_slice, (const byte*)"\xb5\xf4\x05" "slice") -QDEF(MP_QSTR_sms_cb, (const byte*)"\xd6\xca\x06" "sms_cb") QDEF(MP_QSTR_socket, (const byte*)"\x60\xcc\x06" "socket") QDEF(MP_QSTR_sort, (const byte*)"\xbf\x9d\x04" "sort") QDEF(MP_QSTR_sorted, (const byte*)"\x5e\x15\x06" "sorted") @@ -958,17 +996,17 @@ QDEF(MP_QSTR_splash, (const byte*)"\xd0\xcb\x06" "splash") QDEF(MP_QSTR_split, (const byte*)"\xb7\x33\x05" "split") QDEF(MP_QSTR_splitlines, (const byte*)"\x6a\xd3\x0a" "splitlines") QDEF(MP_QSTR_sqrt, (const byte*)"\x21\x44\x04" "sqrt") -QDEF(MP_QSTR_ssh, (const byte*)"\xed\x8d\x03" "ssh") QDEF(MP_QSTR_ssl, (const byte*)"\xe9\x8d\x03" "ssl") -QDEF(MP_QSTR_stack, (const byte*)"\xab\xed\x05" "stack") QDEF(MP_QSTR_stack_size, (const byte*)"\x31\x3b\x0a" "stack_size") QDEF(MP_QSTR_stack_use, (const byte*)"\x97\xf7\x09" "stack_use") QDEF(MP_QSTR_stacksize, (const byte*)"\xce\xdd\x09" "stacksize") QDEF(MP_QSTR_start, (const byte*)"\x85\xef\x05" "start") QDEF(MP_QSTR_start_new_thread, (const byte*)"\xd7\x25\x10" "start_new_thread") +QDEF(MP_QSTR_start_timing, (const byte*)"\x4a\xdd\x0c" "start_timing") QDEF(MP_QSTR_startswith, (const byte*)"\x74\xe8\x0a" "startswith") QDEF(MP_QSTR_stat, (const byte*)"\xd7\x35\x04" "stat") QDEF(MP_QSTR_staticmethod, (const byte*)"\x62\xaf\x0c" "staticmethod") +QDEF(MP_QSTR_stations, (const byte*)"\x2c\x1b\x08" "stations") QDEF(MP_QSTR_status, (const byte*)"\x71\x09\x06" "status") QDEF(MP_QSTR_statvfs, (const byte*)"\x14\x19\x07" "statvfs") QDEF(MP_QSTR_stderr, (const byte*)"\xa3\x58\x06" "stderr") @@ -979,13 +1017,17 @@ QDEF(MP_QSTR_stdout, (const byte*)"\x08\x83\x06" "stdout") QDEF(MP_QSTR_stdout_put, (const byte*)"\xe6\x62\x0a" "stdout_put") QDEF(MP_QSTR_step, (const byte*)"\x57\x36\x04" "step") QDEF(MP_QSTR_stop, (const byte*)"\x9d\x36\x04" "stop") +QDEF(MP_QSTR_stop_timing, (const byte*)"\x52\xed\x0b" "stop_timing") +QDEF(MP_QSTR_stopcollect, (const byte*)"\x03\x04\x0b" "stopcollect") +QDEF(MP_QSTR_stopwave, (const byte*)"\xb8\xf8\x08" "stopwave") QDEF(MP_QSTR_str, (const byte*)"\x50\x8d\x03" "str") QDEF(MP_QSTR_strftime, (const byte*)"\x43\xf0\x08" "strftime") QDEF(MP_QSTR_strip, (const byte*)"\x29\x1e\x05" "strip") QDEF(MP_QSTR_struct, (const byte*)"\x12\x90\x06" "struct") -QDEF(MP_QSTR_subject, (const byte*)"\x19\xce\x07" "subject") -QDEF(MP_QSTR_subscribe, (const byte*)"\x0d\x08\x09" "subscribe") -QDEF(MP_QSTR_subscribed_cb, (const byte*)"\xd7\xbb\x0d" "subscribed_cb") +QDEF(MP_QSTR_stub_led, (const byte*)"\xe7\x8c\x08" "stub_led") +QDEF(MP_QSTR_stub_ledlevel, (const byte*)"\xb1\xff\x0d" "stub_ledlevel") +QDEF(MP_QSTR_stub_ms, (const byte*)"\x14\x88\x07" "stub_ms") +QDEF(MP_QSTR_stub_wait, (const byte*)"\x21\xcd\x09" "stub_wait") QDEF(MP_QSTR_sum, (const byte*)"\x2e\x8d\x03" "sum") QDEF(MP_QSTR_super, (const byte*)"\xc4\xb2\x05" "super") QDEF(MP_QSTR_suspend, (const byte*)"\x6f\xf5\x07" "suspend") @@ -998,10 +1040,11 @@ QDEF(MP_QSTR_tan, (const byte*)"\xfe\x61\x03" "tan") QDEF(MP_QSTR_tanh, (const byte*)"\xd6\xa1\x04" "tanh") QDEF(MP_QSTR_tcs, (const byte*)"\xa1\x61\x03" "tcs") QDEF(MP_QSTR_tell, (const byte*)"\x14\xb1\x04" "tell") -QDEF(MP_QSTR_telnet, (const byte*)"\x67\x4a\x06" "telnet") QDEF(MP_QSTR_text, (const byte*)"\x98\xaf\x04" "text") QDEF(MP_QSTR_textClear, (const byte*)"\x21\x72\x09" "textClear") QDEF(MP_QSTR_textWidth, (const byte*)"\x7e\x9d\x09" "textWidth") +QDEF(MP_QSTR_text_x, (const byte*)"\xdf\xfb\x06" "text_x") +QDEF(MP_QSTR_text_y, (const byte*)"\xde\xfb\x06" "text_y") QDEF(MP_QSTR_tft_deselect, (const byte*)"\x35\x87\x0c" "tft_deselect") QDEF(MP_QSTR_tft_readcmd, (const byte*)"\x44\x21\x0b" "tft_readcmd") QDEF(MP_QSTR_tft_select, (const byte*)"\xb4\xea\x0a" "tft_select") @@ -1024,16 +1067,14 @@ QDEF(MP_QSTR_timeout, (const byte*)"\x3e\x54\x07" "timeout") QDEF(MP_QSTR_timer, (const byte*)"\x82\xff\x05" "timer") QDEF(MP_QSTR_timernum, (const byte*)"\x14\x90\x08" "timernum") QDEF(MP_QSTR_timings, (const byte*)"\xa6\x89\x07" "timings") -QDEF(MP_QSTR_to, (const byte*)"\x9e\x6f\x02" "to") +QDEF(MP_QSTR_title, (const byte*)"\x65\xc0\x05" "title") QDEF(MP_QSTR_to_bytes, (const byte*)"\xd8\x3e\x08" "to_bytes") -QDEF(MP_QSTR_trace, (const byte*)"\xa4\x43\x05" "trace") QDEF(MP_QSTR_transparent, (const byte*)"\xc3\xc2\x0b" "transparent") QDEF(MP_QSTR_triangle, (const byte*)"\xeb\x99\x08" "triangle") QDEF(MP_QSTR_trigger, (const byte*)"\x9d\x8c\x07" "trigger") QDEF(MP_QSTR_trunc, (const byte*)"\x5b\x99\x05" "trunc") QDEF(MP_QSTR_tuple, (const byte*)"\xfd\x41\x05" "tuple") QDEF(MP_QSTR_tx, (const byte*)"\x89\x6f\x02" "tx") -QDEF(MP_QSTR_txdata, (const byte*)"\x99\x3a\x06" "txdata") QDEF(MP_QSTR_type, (const byte*)"\x9d\x7f\x04" "type") QDEF(MP_QSTR_tz, (const byte*)"\x8b\x6f\x02" "tz") QDEF(MP_QSTR_ubinascii, (const byte*)"\xc4\x88\x09" "ubinascii") @@ -1052,21 +1093,18 @@ QDEF(MP_QSTR_unhexlify, (const byte*)"\xb1\xb9\x09" "unhexlify") QDEF(MP_QSTR_uniform, (const byte*)"\x01\xf5\x07" "uniform") QDEF(MP_QSTR_union, (const byte*)"\xf6\x7c\x05" "union") QDEF(MP_QSTR_unique_id, (const byte*)"\x04\x89\x09" "unique_id") +QDEF(MP_QSTR_unit, (const byte*)"\x83\x49\x04" "unit") QDEF(MP_QSTR_unlock, (const byte*)"\x15\x88\x06" "unlock") QDEF(MP_QSTR_unpack, (const byte*)"\x07\x3c\x06" "unpack") QDEF(MP_QSTR_unpack_from, (const byte*)"\x0e\x6d\x0b" "unpack_from") QDEF(MP_QSTR_unregister, (const byte*)"\x17\xd4\x0a" "unregister") -QDEF(MP_QSTR_unsubscribe, (const byte*)"\xd6\xa0\x0b" "unsubscribe") -QDEF(MP_QSTR_unsubscribed_cb, (const byte*)"\x4c\x96\x0f" "unsubscribed_cb") QDEF(MP_QSTR_uos, (const byte*)"\xec\x67\x03" "uos") QDEF(MP_QSTR_update, (const byte*)"\xb4\x76\x06" "update") QDEF(MP_QSTR_update_period, (const byte*)"\x0e\x65\x0d" "update_period") QDEF(MP_QSTR_upper, (const byte*)"\x27\x94\x05" "upper") QDEF(MP_QSTR_urandom, (const byte*)"\xab\xae\x07" "urandom") QDEF(MP_QSTR_ure, (const byte*)"\x87\x63\x03" "ure") -QDEF(MP_QSTR_url, (const byte*)"\x8e\x63\x03" "url") QDEF(MP_QSTR_uselect, (const byte*)"\x58\x8e\x07" "uselect") -QDEF(MP_QSTR_user, (const byte*)"\x54\xf1\x04" "user") QDEF(MP_QSTR_usocket, (const byte*)"\x75\x00\x07" "usocket") QDEF(MP_QSTR_ussl, (const byte*)"\x1c\xf2\x04" "ussl") QDEF(MP_QSTR_ustruct, (const byte*)"\x47\x08\x07" "ustruct") @@ -1075,32 +1113,41 @@ QDEF(MP_QSTR_utimeq, (const byte*)"\xf4\x5a\x06" "utimeq") QDEF(MP_QSTR_uzlib, (const byte*)"\x6d\x9b\x05" "uzlib") QDEF(MP_QSTR_value, (const byte*)"\x4e\x34\x05" "value") QDEF(MP_QSTR_values, (const byte*)"\x7d\xbe\x06" "values") -QDEF(MP_QSTR_verbose, (const byte*)"\x1f\x84\x07" "verbose") QDEF(MP_QSTR_version, (const byte*)"\xbf\xd3\x07" "version") QDEF(MP_QSTR_version_info, (const byte*)"\x6e\x0a\x0c" "version_info") -QDEF(MP_QSTR_vline, (const byte*)"\x1d\xf6\x05" "vline") +QDEF(MP_QSTR_visibility, (const byte*)"\x23\x60\x0a" "visibility") +QDEF(MP_QSTR_volume, (const byte*)"\x6d\x6b\x06" "volume") QDEF(MP_QSTR_vref, (const byte*)"\xe2\x78\x04" "vref") QDEF(MP_QSTR_vref_topin, (const byte*)"\xb1\xaa\x0a" "vref_topin") +QDEF(MP_QSTR_w, (const byte*)"\xd2\xb5\x01" "w") QDEF(MP_QSTR_wait, (const byte*)"\x8e\x55\x04" "wait") QDEF(MP_QSTR_wake_description, (const byte*)"\x04\x8d\x10" "wake_description") QDEF(MP_QSTR_wake_on_ext0, (const byte*)"\x05\xdc\x0c" "wake_on_ext0") QDEF(MP_QSTR_wake_on_ext1, (const byte*)"\x04\xdc\x0c" "wake_on_ext1") QDEF(MP_QSTR_wake_reason, (const byte*)"\x66\xc6\x0b" "wake_reason") +QDEF(MP_QSTR_waveform, (const byte*)"\x36\x6d\x08" "waveform") +QDEF(MP_QSTR_wavplay, (const byte*)"\xc1\x07\x07" "wavplay") QDEF(MP_QSTR_websocket, (const byte*)"\x90\x8d\x09" "websocket") QDEF(MP_QSTR_white, (const byte*)"\x42\xc3\x05" "white") QDEF(MP_QSTR_width, (const byte*)"\x23\x75\x05" "width") +QDEF(MP_QSTR_wifiactive, (const byte*)"\x58\x33\x0a" "wifiactive") +QDEF(MP_QSTR_wifimode, (const byte*)"\x17\x91\x08" "wifimode") QDEF(MP_QSTR_winsize, (const byte*)"\xd0\x0e\x07" "winsize") QDEF(MP_QSTR_wrap, (const byte*)"\x51\xfc\x04" "wrap") QDEF(MP_QSTR_wrap_socket, (const byte*)"\xcb\xf3\x0b" "wrap_socket") QDEF(MP_QSTR_write, (const byte*)"\x98\xa8\x05" "write") +QDEF(MP_QSTR_write_break, (const byte*)"\x78\x98\x0b" "write_break") +QDEF(MP_QSTR_write_buffer, (const byte*)"\xa7\x2e\x0c" "write_buffer") QDEF(MP_QSTR_write_byte, (const byte*)"\x8d\x8d\x0a" "write_byte") QDEF(MP_QSTR_write_bytes, (const byte*)"\x5e\x3f\x0b" "write_bytes") QDEF(MP_QSTR_write_readinto, (const byte*)"\x89\x84\x0e" "write_readinto") QDEF(MP_QSTR_write_string, (const byte*)"\xb2\x83\x0c" "write_string") +QDEF(MP_QSTR_write_timed, (const byte*)"\x96\x4f\x0b" "write_timed") QDEF(MP_QSTR_writebyte, (const byte*)"\xd2\x1e\x09" "writebyte") QDEF(MP_QSTR_writebytes, (const byte*)"\x61\xf9\x0a" "writebytes") QDEF(MP_QSTR_writeto, (const byte*)"\x03\x39\x07" "writeto") QDEF(MP_QSTR_writeto_mem, (const byte*)"\x79\xed\x0b" "writeto_mem") +QDEF(MP_QSTR_ws, (const byte*)"\x61\x70\x02" "ws") QDEF(MP_QSTR_x, (const byte*)"\xdd\xb5\x01" "x") QDEF(MP_QSTR_x1, (const byte*)"\x4c\x71\x02" "x1") QDEF(MP_QSTR_x2, (const byte*)"\x4f\x71\x02" "x2") diff --git a/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h b/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h index 32664201..aa80c095 100644 --- a/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h +++ b/MicroPython_BUILD/components/micropython/lib/berkeley-db-1.xx/btree/btree.h @@ -44,9 +44,13 @@ #include "lib/berkeley-db-1.xx/include/mpool.h" #define DEFMINKEYPAGE (2) /* Minimum keys per page */ +#ifndef MINCACHE #define MINCACHE (5) /* Minimum cached pages */ +#endif #define MINPSIZE (512) /* Minimum page size */ +#ifndef DEFPSIZE #define DEFPSIZE (4096) /* Default page size */ +#endif /* * Page 0 of a btree file contains a copy of the meta-data. This page is also diff --git a/MicroPython_BUILD/components/micropython/lib/libc/string0.c b/MicroPython_BUILD/components/micropython/lib/libc/string0.c deleted file mode 100644 index c2f2abd0..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libc/string0.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * 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 -#include - -#define likely(x) __builtin_expect((x), 1) - -void *memcpy(void *dst, const void *src, size_t n) { - if (likely(!(((uintptr_t)dst) & 3) && !(((uintptr_t)src) & 3))) { - // pointers aligned - uint32_t *d = dst; - const uint32_t *s = src; - - // copy words first - for (size_t i = (n >> 2); i; i--) { - *d++ = *s++; - } - - if (n & 2) { - // copy half-word - *(uint16_t*)d = *(const uint16_t*)s; - d = (uint32_t*)((uint16_t*)d + 1); - s = (const uint32_t*)((const uint16_t*)s + 1); - } - - if (n & 1) { - // copy byte - *((uint8_t*)d) = *((const uint8_t*)s); - } - } else { - // unaligned access, copy bytes - uint8_t *d = dst; - const uint8_t *s = src; - - for (; n; n--) { - *d++ = *s++; - } - } - - return dst; -} - -void *memmove(void *dest, const void *src, size_t n) { - if (src < dest && (uint8_t*)dest < (const uint8_t*)src + n) { - // need to copy backwards - uint8_t *d = (uint8_t*)dest + n - 1; - const uint8_t *s = (const uint8_t*)src + n - 1; - for (; n > 0; n--) { - *d-- = *s--; - } - return dest; - } else { - // can use normal memcpy - return memcpy(dest, src, n); - } -} - -void *memset(void *s, int c, size_t n) { - if (c == 0 && ((uintptr_t)s & 3) == 0) { - // aligned store of 0 - uint32_t *s32 = s; - for (size_t i = n >> 2; i > 0; i--) { - *s32++ = 0; - } - if (n & 2) { - *((uint16_t*)s32) = 0; - s32 = (uint32_t*)((uint16_t*)s32 + 1); - } - if (n & 1) { - *((uint8_t*)s32) = 0; - } - } else { - uint8_t *s2 = s; - for (; n > 0; n--) { - *s2++ = c; - } - } - return s; -} - -int memcmp(const void *s1, const void *s2, size_t n) { - const uint8_t *s1_8 = s1; - const uint8_t *s2_8 = s2; - while (n--) { - char c1 = *s1_8++; - char c2 = *s2_8++; - if (c1 < c2) return -1; - else if (c1 > c2) return 1; - } - return 0; -} - -void *memchr(const void *s, int c, size_t n) { - if (n != 0) { - const unsigned char *p = s; - - do { - if (*p++ == c) - return ((void *)(p - 1)); - } while (--n != 0); - } - return 0; -} - -size_t strlen(const char *str) { - int len = 0; - for (const char *s = str; *s; s++) { - len += 1; - } - return len; -} - -int strcmp(const char *s1, const char *s2) { - while (*s1 && *s2) { - char c1 = *s1++; // XXX UTF8 get char, next char - char c2 = *s2++; // XXX UTF8 get char, next char - if (c1 < c2) return -1; - else if (c1 > c2) return 1; - } - if (*s2) return -1; - else if (*s1) return 1; - else return 0; -} - -int strncmp(const char *s1, const char *s2, size_t n) { - while (*s1 && *s2 && n > 0) { - char c1 = *s1++; // XXX UTF8 get char, next char - char c2 = *s2++; // XXX UTF8 get char, next char - n--; - if (c1 < c2) return -1; - else if (c1 > c2) return 1; - } - if (n == 0) return 0; - else if (*s2) return -1; - else if (*s1) return 1; - else return 0; -} - -char *strcpy(char *dest, const char *src) { - char *d = dest; - while (*src) { - *d++ = *src++; - } - *d = '\0'; - return dest; -} - -// needed because gcc optimises strcpy + strcat to this -char *stpcpy(char *dest, const char *src) { - while (*src) { - *dest++ = *src++; - } - *dest = '\0'; - return dest; -} - -char *strcat(char *dest, const char *src) { - char *d = dest; - while (*d) { - d++; - } - while (*src) { - *d++ = *src++; - } - *d = '\0'; - return dest; -} - -// Public Domain implementation of strchr from: -// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strchr_function -char *strchr(const char *s, int c) -{ - /* Scan s for the character. When this loop is finished, - s will either point to the end of the string or the - character we were looking for. */ - while (*s != '\0' && *s != (char)c) - s++; - return ((*s == c) ? (char *) s : 0); -} - - -// Public Domain implementation of strstr from: -// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strstr_function -char *strstr(const char *haystack, const char *needle) -{ - size_t needlelen; - /* Check for the null needle case. */ - if (*needle == '\0') - return (char *) haystack; - needlelen = strlen(needle); - for (; (haystack = strchr(haystack, *needle)) != 0; haystack++) - if (strncmp(haystack, needle, needlelen) == 0) - return (char *) haystack; - return 0; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libffi/include/ffi_cfi.h b/MicroPython_BUILD/components/micropython/lib/libffi/include/ffi_cfi.h deleted file mode 100644 index 244ce572..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libffi/include/ffi_cfi.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc. - - Conditionally assemble cfi directives. Only necessary for building libffi. - ----------------------------------------------------------------------- */ - -#ifndef FFI_CFI_H -#define FFI_CFI_H - -#ifdef HAVE_AS_CFI_PSEUDO_OP - -# define cfi_startproc .cfi_startproc -# define cfi_endproc .cfi_endproc -# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off -# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg -# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off -# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off -# define cfi_offset(reg, off) .cfi_offset reg, off -# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off -# define cfi_register(r1, r2) .cfi_register r1, r2 -# define cfi_return_column(reg) .cfi_return_column reg -# define cfi_restore(reg) .cfi_restore reg -# define cfi_same_value(reg) .cfi_same_value reg -# define cfi_undefined(reg) .cfi_undefined reg -# define cfi_remember_state .cfi_remember_state -# define cfi_restore_state .cfi_restore_state -# define cfi_window_save .cfi_window_save -# define cfi_personality(enc, exp) .cfi_personality enc, exp -# define cfi_lsda(enc, exp) .cfi_lsda enc, exp -# define cfi_escape(...) .cfi_escape __VA_ARGS__ - -#else - -# define cfi_startproc -# define cfi_endproc -# define cfi_def_cfa(reg, off) -# define cfi_def_cfa_register(reg) -# define cfi_def_cfa_offset(off) -# define cfi_adjust_cfa_offset(off) -# define cfi_offset(reg, off) -# define cfi_rel_offset(reg, off) -# define cfi_register(r1, r2) -# define cfi_return_column(reg) -# define cfi_restore(reg) -# define cfi_same_value(reg) -# define cfi_undefined(reg) -# define cfi_remember_state -# define cfi_restore_state -# define cfi_window_save -# define cfi_personality(enc, exp) -# define cfi_lsda(enc, exp) -# define cfi_escape(...) - -#endif /* HAVE_AS_CFI_PSEUDO_OP */ -#endif /* FFI_CFI_H */ diff --git a/MicroPython_BUILD/components/micropython/lib/libffi/include/ffi_common.h b/MicroPython_BUILD/components/micropython/lib/libffi/include/ffi_common.h deleted file mode 100644 index 37f5a9e9..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libffi/include/ffi_common.h +++ /dev/null @@ -1,132 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi_common.h - Copyright (C) 2011, 2012, 2013 Anthony Green - Copyright (C) 2007 Free Software Foundation, Inc - Copyright (c) 1996 Red Hat, Inc. - - Common internal definitions and macros. Only necessary for building - libffi. - ----------------------------------------------------------------------- */ - -#ifndef FFI_COMMON_H -#define FFI_COMMON_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* Do not move this. Some versions of AIX are very picky about where - this is positioned. */ -#ifdef __GNUC__ -# if HAVE_ALLOCA_H -# include -# else - /* mingw64 defines this already in malloc.h. */ -# ifndef alloca -# define alloca __builtin_alloca -# endif -# endif -# define MAYBE_UNUSED __attribute__((__unused__)) -#else -# define MAYBE_UNUSED -# if HAVE_ALLOCA_H -# include -# else -# ifdef _AIX -# pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -# ifdef _MSC_VER -# define alloca _alloca -# else -char *alloca (); -# endif -# endif -# endif -# endif -#endif - -/* Check for the existence of memcpy. */ -#if STDC_HEADERS -# include -#else -# ifndef HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# endif -#endif - -#if defined(FFI_DEBUG) -#include -#endif - -#ifdef FFI_DEBUG -void ffi_assert(char *expr, char *file, int line); -void ffi_stop_here(void); -void ffi_type_test(ffi_type *a, char *file, int line); - -#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) -#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) -#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__) -#else -#define FFI_ASSERT(x) -#define FFI_ASSERT_AT(x, f, l) -#define FFI_ASSERT_VALID_TYPE(x) -#endif - -#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) -#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a) - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif); -ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, - unsigned int nfixedargs, unsigned int ntotalargs); - -/* Extended cif, used in callback from assembly routine */ -typedef struct -{ - ffi_cif *cif; - void *rvalue; - void **avalue; -} extended_cif; - -/* Terse sized type definitions. */ -#if defined(_MSC_VER) || defined(__sgi) || defined(__SUNPRO_C) -typedef unsigned char UINT8; -typedef signed char SINT8; -typedef unsigned short UINT16; -typedef signed short SINT16; -typedef unsigned int UINT32; -typedef signed int SINT32; -# ifdef _MSC_VER -typedef unsigned __int64 UINT64; -typedef signed __int64 SINT64; -# else -# include -typedef uint64_t UINT64; -typedef int64_t SINT64; -# endif -#else -typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); -typedef signed int SINT8 __attribute__((__mode__(__QI__))); -typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); -typedef signed int SINT16 __attribute__((__mode__(__HI__))); -typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); -typedef signed int SINT32 __attribute__((__mode__(__SI__))); -typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); -typedef signed int SINT64 __attribute__((__mode__(__DI__))); -#endif - -typedef float FLOAT32; - -#ifndef __GNUC__ -#define __builtin_expect(x, expected_value) (x) -#endif -#define LIKELY(x) __builtin_expect(!!(x),1) -#define UNLIKELY(x) __builtin_expect((x)!=0,0) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/ffi.c b/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/ffi.c deleted file mode 100644 index fd94dafb..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/ffi.c +++ /dev/null @@ -1,298 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 2013 Tensilica, Inc. - - XTENSA Foreign Function Interface - - 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 -#include - -/* - |----------------------------------------| - | | - on entry to ffi_call ----> |----------------------------------------| - | caller stack frame for registers a0-a3 | - |----------------------------------------| - | | - | additional arguments | - entry of the function ---> |----------------------------------------| - | copy of function arguments a2-a7 | - | - - - - - - - - - - - - - | - | | - - The area below the entry line becomes the new stack frame for the function. - -*/ - - -#define FFI_TYPE_STRUCT_REGS FFI_TYPE_LAST - - -extern void ffi_call_SYSV(void *rvalue, unsigned rsize, unsigned flags, - void(*fn)(void), unsigned nbytes, extended_cif*); -extern void ffi_closure_SYSV(void) FFI_HIDDEN; - -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - switch(cif->rtype->type) { - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT16: - cif->flags = cif->rtype->type; - break; - case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - cif->flags = FFI_TYPE_UINT32; - break; - case FFI_TYPE_DOUBLE: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - cif->flags = FFI_TYPE_UINT64; // cif->rtype->type; - break; - case FFI_TYPE_STRUCT: - cif->flags = FFI_TYPE_STRUCT; //_REGS; - /* Up to 16 bytes are returned in registers */ - if (cif->rtype->size > 4 * 4) { - /* returned structure is referenced by a register; use 8 bytes - (including 4 bytes for potential additional alignment) */ - cif->flags = FFI_TYPE_STRUCT; - cif->bytes += 8; - } - break; - - default: - cif->flags = FFI_TYPE_UINT32; - break; - } - - /* Round the stack up to a full 4 register frame, just in case - (we use this size in movsp). This way, it's also a multiple of - 8 bytes for 64-bit arguments. */ - cif->bytes = ALIGN(cif->bytes, 16); - - return FFI_OK; -} - -void ffi_prep_args(extended_cif *ecif, unsigned char* stack) -{ - unsigned int i; - unsigned long *addr; - ffi_type **ptr; - - union { - void **v; - char **c; - signed char **sc; - unsigned char **uc; - signed short **ss; - unsigned short **us; - unsigned int **i; - long long **ll; - float **f; - double **d; - } p_argv; - - /* Verify that everything is aligned up properly */ - FFI_ASSERT (((unsigned long) stack & 0x7) == 0); - - p_argv.v = ecif->avalue; - addr = (unsigned long*)stack; - - /* structures with a size greater than 16 bytes are passed in memory */ - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 16) - { - *addr++ = (unsigned long)ecif->rvalue; - } - - for (i = ecif->cif->nargs, ptr = ecif->cif->arg_types; - i > 0; - i--, ptr++, p_argv.v++) - { - switch ((*ptr)->type) - { - case FFI_TYPE_SINT8: - *addr++ = **p_argv.sc; - break; - case FFI_TYPE_UINT8: - *addr++ = **p_argv.uc; - break; - case FFI_TYPE_SINT16: - *addr++ = **p_argv.ss; - break; - case FFI_TYPE_UINT16: - *addr++ = **p_argv.us; - break; - case FFI_TYPE_FLOAT: - case FFI_TYPE_INT: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: - *addr++ = **p_argv.i; - break; - case FFI_TYPE_DOUBLE: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - if (((unsigned long)addr & 4) != 0) - addr++; - *(unsigned long long*)addr = **p_argv.ll; - addr += sizeof(unsigned long long) / sizeof (addr); - break; - - case FFI_TYPE_STRUCT: - { - unsigned long offs; - unsigned long size; - - if (((unsigned long)addr & 4) != 0 && (*ptr)->alignment > 4) - addr++; - - offs = (unsigned long) addr - (unsigned long) stack; - size = (*ptr)->size; - - /* Entire structure must fit the argument registers or referenced */ - if (offs < FFI_REGISTER_NARGS * 4 - && offs + size > FFI_REGISTER_NARGS * 4) - addr = (unsigned long*) (stack + FFI_REGISTER_NARGS * 4); - - memcpy((char*) addr, *p_argv.c, size); - addr += (size + 3) / 4; - break; - } - - default: - FFI_ASSERT(0); - } - } -} - - -void ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - unsigned long rsize = cif->rtype->size; - int flags = cif->flags; - void *alloc = NULL; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* Note that for structures that are returned in registers (size <= 16 bytes) - we allocate a temporary buffer and use memcpy to copy it to the final - destination. The reason is that the target address might be misaligned or - the length not a multiple of 4 bytes. Handling all those cases would be - very complex. */ - - if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL)) - { - alloc = alloca(ALIGN(rsize, 4)); - ecif.rvalue = alloc; - } - else - { - ecif.rvalue = rvalue; - } - - if (cif->abi != FFI_SYSV) - FFI_ASSERT(0); - - ffi_call_SYSV (ecif.rvalue, rsize, cif->flags, fn, cif->bytes, &ecif); - - if (alloc != NULL && rvalue != NULL) - memcpy(rvalue, alloc, rsize); -} - -extern void ffi_trampoline(); -extern void ffi_cacheflush(void* start, void* end); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - /* copye trampoline to stack and patch 'ffi_closure_SYSV' pointer */ - memcpy(closure->tramp, ffi_trampoline, FFI_TRAMPOLINE_SIZE); - *(unsigned int*)(&closure->tramp[8]) = (unsigned int)ffi_closure_SYSV; - - // Do we have this function? - // __builtin___clear_cache(closer->tramp, closer->tramp + FFI_TRAMPOLINE_SIZE) - ffi_cacheflush(closure->tramp, closure->tramp + FFI_TRAMPOLINE_SIZE); - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - return FFI_OK; -} - - -long FFI_HIDDEN -ffi_closure_SYSV_inner(ffi_closure *closure, void **values, void *rvalue) -{ - ffi_cif *cif; - ffi_type **arg_types; - void **avalue; - int i, areg; - - cif = closure->cif; - if (cif->abi != FFI_SYSV) - return FFI_BAD_ABI; - - areg = 0; - - int rtype = cif->rtype->type; - if (rtype == FFI_TYPE_STRUCT && cif->rtype->size > 4 * 4) - { - rvalue = *values; - areg++; - } - - cif = closure->cif; - arg_types = cif->arg_types; - avalue = alloca(cif->nargs * sizeof(void *)); - - for (i = 0; i < cif->nargs; i++) - { - if (arg_types[i]->alignment == 8 && (areg & 1) != 0) - areg++; - - // skip the entry 16,a1 framework, add 16 bytes (4 registers) - if (areg == FFI_REGISTER_NARGS) - areg += 4; - - if (arg_types[i]->type == FFI_TYPE_STRUCT) - { - int numregs = ((arg_types[i]->size + 3) & ~3) / 4; - if (areg < FFI_REGISTER_NARGS && areg + numregs > FFI_REGISTER_NARGS) - areg = FFI_REGISTER_NARGS + 4; - } - - avalue[i] = &values[areg]; - areg += (arg_types[i]->size + 3) / 4; - } - - (closure->fun)(cif, rvalue, avalue, closure->user_data); - - return rtype; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/ffitarget.h b/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/ffitarget.h deleted file mode 100644 index 0ba728bc..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/ffitarget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2013 Tensilica, Inc. - Target configuration macros for XTENSA. - - 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 LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -#ifndef LIBFFI_ASM -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - FFI_SYSV, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_SYSV -} ffi_abi; -#endif - -#define FFI_REGISTER_NARGS 6 - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_NATIVE_RAW_API 0 -#define FFI_TRAMPOLINE_SIZE 24 - -#endif diff --git a/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/sysv.S b/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/sysv.S deleted file mode 100644 index 64e6a091..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libffi/src/xtensa/sysv.S +++ /dev/null @@ -1,253 +0,0 @@ -/* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2013 Tensilica, Inc. - - XTENSA Foreign Function Interface - - 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. - ----------------------------------------------------------------------- */ - -#define LIBFFI_ASM -#include -#include - -#define ENTRY(name) .text; .globl name; .type name,@function; .align 4; name: -#define END(name) .size name , . - name - -/* Assert that the table below is in sync with ffi.h. */ - -#if FFI_TYPE_UINT8 != 5 \ - || FFI_TYPE_SINT8 != 6 \ - || FFI_TYPE_UINT16 != 7 \ - || FFI_TYPE_SINT16 != 8 \ - || FFI_TYPE_UINT32 != 9 \ - || FFI_TYPE_SINT32 != 10 \ - || FFI_TYPE_UINT64 != 11 -#error "xtensa/sysv.S out of sync with ffi.h" -#endif - - -/* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif) - void *rvalue; a2 - unsigned long rbytes; a3 - unsigned flags; a4 - void (*fnaddr)(); a5 - unsigned long bytes; a6 - extended_cif* ecif) a7 -*/ - -ENTRY(ffi_call_SYSV) - - entry a1, 32 # 32 byte frame for using call8 below - - mov a10, a7 # a10(->arg0): ecif - sub a11, a1, a6 # a11(->arg1): stack pointer - mov a7, a1 # fp - movsp a1, a11 # set new sp = old_sp - bytes - - movi a8, ffi_prep_args - callx8 a8 # ffi_prep_args(ecif, stack) - - # prepare to move stack pointer back up to 6 arguments - # note that 'bytes' is already aligned - - movi a10, 6*4 - sub a11, a6, a10 - movgez a6, a10, a11 - add a6, a1, a6 - - - # we can pass up to 6 arguments in registers - # for simplicity, just load 6 arguments - # (the stack size is at least 32 bytes, so no risk to cross boundaries) - - l32i a10, a1, 0 - l32i a11, a1, 4 - l32i a12, a1, 8 - l32i a13, a1, 12 - l32i a14, a1, 16 - l32i a15, a1, 20 - - # move stack pointer - - movsp a1, a6 - - callx8 a5 # (*fn)(args...) - - # Handle return value(s) - - beqz a2, .Lexit - - movi a5, FFI_TYPE_STRUCT - bne a4, a5, .Lstore - movi a5, 16 - blt a5, a3, .Lexit - - s32i a10, a2, 0 - blti a3, 5, .Lexit - addi a3, a3, -1 - s32i a11, a2, 4 - blti a3, 8, .Lexit - s32i a12, a2, 8 - blti a3, 12, .Lexit - s32i a13, a2, 12 - -.Lexit: retw - -.Lstore: - addi a4, a4, -FFI_TYPE_UINT8 - bgei a4, 7, .Lexit # should never happen - movi a6, store_calls - add a4, a4, a4 - addx4 a6, a4, a6 # store_table + idx * 8 - jx a6 - - .align 8 -store_calls: - # UINT8 - s8i a10, a2, 0 - retw - - # SINT8 - .align 8 - s8i a10, a2, 0 - retw - - # UINT16 - .align 8 - s16i a10, a2, 0 - retw - - # SINT16 - .align 8 - s16i a10, a2, 0 - retw - - # UINT32 - .align 8 - s32i a10, a2, 0 - retw - - # SINT32 - .align 8 - s32i a10, a2, 0 - retw - - # UINT64 - .align 8 - s32i a10, a2, 0 - s32i a11, a2, 4 - retw - -END(ffi_call_SYSV) - - -/* - * void ffi_cacheflush (unsigned long start, unsigned long end) - */ - -#define EXTRA_ARGS_SIZE 24 - -ENTRY(ffi_cacheflush) - - entry a1, 16 - -1: dhwbi a2, 0 - ihi a2, 0 - addi a2, a2, 4 - blt a2, a3, 1b - - retw - -END(ffi_cacheflush) - -/* ffi_trampoline is copied to the stack */ - -ENTRY(ffi_trampoline) - - entry a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4) # [ 0] - j 2f # [ 3] - .align 4 # [ 6] -1: .long 0 # [ 8] -2: l32r a15, 1b # [12] - _mov a14, a0 # [15] - callx0 a15 # [18] - # [21] -END(ffi_trampoline) - -/* - * ffi_closure() - * - * a0: closure + 21 - * a14: return address (a0) - */ - -ENTRY(ffi_closure_SYSV) - - /* intentionally omitting entry here */ - - # restore return address (a0) and move pointer to closure to a10 - addi a10, a0, -21 - mov a0, a14 - - # allow up to 4 arguments as return values - addi a11, a1, 4 * 4 - - # save up to 6 arguments to stack (allocated by entry below) - s32i a2, a11, 0 - s32i a3, a11, 4 - s32i a4, a11, 8 - s32i a5, a11, 12 - s32i a6, a11, 16 - s32i a7, a11, 20 - - movi a8, ffi_closure_SYSV_inner - mov a12, a1 - callx8 a8 # .._inner(*closure, **avalue, *rvalue) - - # load up to four return arguments - l32i a2, a1, 0 - l32i a3, a1, 4 - l32i a4, a1, 8 - l32i a5, a1, 12 - - # (sign-)extend return value - movi a11, FFI_TYPE_UINT8 - bne a10, a11, 1f - extui a2, a2, 0, 8 - retw - -1: movi a11, FFI_TYPE_SINT8 - bne a10, a11, 1f - sext a2, a2, 7 - retw - -1: movi a11, FFI_TYPE_UINT16 - bne a10, a11, 1f - extui a2, a2, 0, 16 - retw - -1: movi a11, FFI_TYPE_SINT16 - bne a10, a11, 1f - sext a2, a2, 15 - -1: retw - -END(ffi_closure_SYSV) diff --git a/MicroPython_BUILD/components/micropython/lib/libm/acoshf.c b/MicroPython_BUILD/components/micropython/lib/libm/acoshf.c deleted file mode 100644 index 8a8409f5..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/acoshf.c +++ /dev/null @@ -1,32 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// acoshf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -#include "libm.h" - -#if FLT_EVAL_METHOD==2 -#undef sqrtf -#define sqrtf sqrtl -#elif FLT_EVAL_METHOD==1 -#undef sqrtf -#define sqrtf sqrt -#endif - -/* acosh(x) = log(x + sqrt(x*x-1)) */ -float acoshf(float x) -{ - union {float f; uint32_t i;} u = {x}; - uint32_t a = u.i & 0x7fffffff; - - if (a < 0x3f800000+(1<<23)) - /* |x| < 2, invalid if x < 1 or nan */ - /* up to 2ulp error in [1,1.125] */ - return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1))); - if (a < 0x3f800000+(12<<23)) - /* |x| < 0x1p12 */ - return logf(2*x - 1/(x+sqrtf(x*x-1))); - /* x >= 0x1p12 */ - return logf(x) + 0.693147180559945309417232121458176568f; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/asinfacosf.c b/MicroPython_BUILD/components/micropython/lib/libm/asinfacosf.c deleted file mode 100644 index 07ecad3f..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/asinfacosf.c +++ /dev/null @@ -1,130 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// asinf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/e_asinf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "libm.h" - -// dpgeorge: pio2 was double in original implementation of asinf -static const float -pio2_hi = 1.5707962513e+00, /* 0x3fc90fda */ -pio2_lo = 7.5497894159e-08; /* 0x33a22168 */ - -static const float -/* coefficients for R(x^2) */ -pS0 = 1.6666586697e-01, -pS1 = -4.2743422091e-02, -pS2 = -8.6563630030e-03, -qS1 = -7.0662963390e-01; - -static float R(float z) -{ - float_t p, q; - p = z*(pS0+z*(pS1+z*pS2)); - q = 1.0f+z*qS1; - return p/q; -} - -float asinf(float x) -{ - // dpgeorge: s was double in original implementation - float s,z; - uint32_t hx,ix; - - GET_FLOAT_WORD(hx, x); - ix = hx & 0x7fffffff; - if (ix >= 0x3f800000) { /* |x| >= 1 */ - if (ix == 0x3f800000) /* |x| == 1 */ - return x*pio2_hi + 0x1p-120f; /* asin(+-1) = +-pi/2 with inexact */ - return 0/(x-x); /* asin(|x|>1) is NaN */ - } - if (ix < 0x3f000000) { /* |x| < 0.5 */ - /* if 0x1p-126 <= |x| < 0x1p-12, avoid raising underflow */ - if (ix < 0x39800000 && ix >= 0x00800000) - return x; - return x + x*R(x*x); - } - /* 1 > |x| >= 0.5 */ - z = (1 - fabsf(x))*0.5f; - s = sqrtf(z); - x = pio2_hi - (2*(s+s*R(z)) - pio2_lo); // dpgeorge: use pio2_hi and pio2_lo - if (hx >> 31) - return -x; - return x; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// acosf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/e_acosf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -float acosf(float x) -{ - float z,w,s,c,df; - uint32_t hx,ix; - - GET_FLOAT_WORD(hx, x); - ix = hx & 0x7fffffff; - /* |x| >= 1 or nan */ - if (ix >= 0x3f800000) { - if (ix == 0x3f800000) { - if (hx >> 31) - return 2*pio2_hi + 0x1p-120f; - return 0; - } - return 0/(x-x); - } - /* |x| < 0.5 */ - if (ix < 0x3f000000) { - if (ix <= 0x32800000) /* |x| < 2**-26 */ - return pio2_hi + 0x1p-120f; - return pio2_hi - (x - (pio2_lo-x*R(x*x))); - } - /* x < -0.5 */ - if (hx >> 31) { - z = (1+x)*0.5f; - s = sqrtf(z); - w = R(z)*s-pio2_lo; - return 2*(pio2_hi - (s+w)); - } - /* x > 0.5 */ - z = (1-x)*0.5f; - s = sqrtf(z); - GET_FLOAT_WORD(hx,s); - SET_FLOAT_WORD(df,hx&0xfffff000); - c = (z-df*df)/(s+df); - w = R(z)*s+c; - return 2*(df+w); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/asinhf.c b/MicroPython_BUILD/components/micropython/lib/libm/asinhf.c deleted file mode 100644 index 4bcb3f9a..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/asinhf.c +++ /dev/null @@ -1,34 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// asinhf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -#include "libm.h" - -/* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */ -float asinhf(float x) -{ - union {float f; uint32_t i;} u = {.f = x}; - uint32_t i = u.i & 0x7fffffff; - unsigned s = u.i >> 31; - - /* |x| */ - u.i = i; - x = u.f; - - if (i >= 0x3f800000 + (12<<23)) { - /* |x| >= 0x1p12 or inf or nan */ - x = logf(x) + 0.693147180559945309417232121458176568f; - } else if (i >= 0x3f800000 + (1<<23)) { - /* |x| >= 2 */ - x = logf(2*x + 1/(sqrtf(x*x+1)+x)); - } else if (i >= 0x3f800000 - (12<<23)) { - /* |x| >= 0x1p-12, up to 1.6ulp error in [0.125,0.5] */ - x = log1pf(x + x*x/(sqrtf(x*x+1)+1)); - } else { - /* |x| < 0x1p-12, raise inexact if x!=0 */ - FORCE_EVAL(x + 0x1p120f); - } - return s ? -x : x; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/atan2f.c b/MicroPython_BUILD/components/micropython/lib/libm/atan2f.c deleted file mode 100644 index 03d000c9..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/atan2f.c +++ /dev/null @@ -1,89 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// atan2f from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/e_atan2f.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "libm.h" - -static const float -pi = 3.1415927410e+00, /* 0x40490fdb */ -pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */ - -float atan2f(float y, float x) -{ - float z; - uint32_t m,ix,iy; - - if (isnan(x) || isnan(y)) - return x+y; - GET_FLOAT_WORD(ix, x); - GET_FLOAT_WORD(iy, y); - if (ix == 0x3f800000) /* x=1.0 */ - return atanf(y); - m = ((iy>>31)&1) | ((ix>>30)&2); /* 2*sign(x)+sign(y) */ - ix &= 0x7fffffff; - iy &= 0x7fffffff; - - /* when y = 0 */ - if (iy == 0) { - switch (m) { - case 0: - case 1: return y; /* atan(+-0,+anything)=+-0 */ - case 2: return pi; /* atan(+0,-anything) = pi */ - case 3: return -pi; /* atan(-0,-anything) =-pi */ - } - } - /* when x = 0 */ - if (ix == 0) - return m&1 ? -pi/2 : pi/2; - /* when x is INF */ - if (ix == 0x7f800000) { - if (iy == 0x7f800000) { - switch (m) { - case 0: return pi/4; /* atan(+INF,+INF) */ - case 1: return -pi/4; /* atan(-INF,+INF) */ - case 2: return 3*pi/4; /*atan(+INF,-INF)*/ - case 3: return -3*pi/4; /*atan(-INF,-INF)*/ - } - } else { - switch (m) { - case 0: return 0.0f; /* atan(+...,+INF) */ - case 1: return -0.0f; /* atan(-...,+INF) */ - case 2: return pi; /* atan(+...,-INF) */ - case 3: return -pi; /* atan(-...,-INF) */ - } - } - } - /* |y/x| > 0x1p26 */ - if (ix+(26<<23) < iy || iy == 0x7f800000) - return m&1 ? -pi/2 : pi/2; - - /* z = atan(|y/x|) with correct underflow */ - if ((m&2) && iy+(26<<23) < ix) /*|y/x| < 0x1p-26, x < 0 */ - z = 0.0; - else - z = atanf(fabsf(y/x)); - switch (m) { - case 0: return z; /* atan(+,+) */ - case 1: return -z; /* atan(-,+) */ - case 2: return pi - (z-pi_lo); /* atan(+,-) */ - default: /* case 3 */ - return (z-pi_lo) - pi; /* atan(-,-) */ - } -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/atanf.c b/MicroPython_BUILD/components/micropython/lib/libm/atanf.c deleted file mode 100644 index 053fc1b6..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/atanf.c +++ /dev/null @@ -1,100 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// atanf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/s_atanf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - - -#include "libm.h" - -static const float atanhi[] = { - 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */ - 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */ - 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */ - 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */ -}; - -static const float atanlo[] = { - 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */ - 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */ - 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */ - 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */ -}; - -static const float aT[] = { - 3.3333328366e-01, - -1.9999158382e-01, - 1.4253635705e-01, - -1.0648017377e-01, - 6.1687607318e-02, -}; - -float atanf(float x) -{ - float_t w,s1,s2,z; - uint32_t ix,sign; - int id; - - GET_FLOAT_WORD(ix, x); - sign = ix>>31; - ix &= 0x7fffffff; - if (ix >= 0x4c800000) { /* if |x| >= 2**26 */ - if (isnan(x)) - return x; - z = atanhi[3] + 0x1p-120f; - return sign ? -z : z; - } - if (ix < 0x3ee00000) { /* |x| < 0.4375 */ - if (ix < 0x39800000) { /* |x| < 2**-12 */ - if (ix < 0x00800000) - /* raise underflow for subnormal x */ - FORCE_EVAL(x*x); - return x; - } - id = -1; - } else { - x = fabsf(x); - if (ix < 0x3f980000) { /* |x| < 1.1875 */ - if (ix < 0x3f300000) { /* 7/16 <= |x| < 11/16 */ - id = 0; - x = (2.0f*x - 1.0f)/(2.0f + x); - } else { /* 11/16 <= |x| < 19/16 */ - id = 1; - x = (x - 1.0f)/(x + 1.0f); - } - } else { - if (ix < 0x401c0000) { /* |x| < 2.4375 */ - id = 2; - x = (x - 1.5f)/(1.0f + 1.5f*x); - } else { /* 2.4375 <= |x| < 2**26 */ - id = 3; - x = -1.0f/x; - } - } - } - /* end of argument reduction */ - z = x*x; - w = z*z; - /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ - s1 = z*(aT[0]+w*(aT[2]+w*aT[4])); - s2 = w*(aT[1]+w*aT[3]); - if (id < 0) - return x - x*(s1+s2); - z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); - return sign ? -z : z; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/atanhf.c b/MicroPython_BUILD/components/micropython/lib/libm/atanhf.c deleted file mode 100644 index 6f95f497..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/atanhf.c +++ /dev/null @@ -1,34 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// atanhf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -#include "libm.h" - -/* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ -float atanhf(float x) -{ - union {float f; uint32_t i;} u = {.f = x}; - unsigned s = u.i >> 31; - float_t y; - - /* |x| */ - u.i &= 0x7fffffff; - y = u.f; - - if (u.i < 0x3f800000 - (1<<23)) { - if (u.i < 0x3f800000 - (32<<23)) { - /* handle underflow */ - if (u.i < (1<<23)) - FORCE_EVAL((float)(y*y)); - } else { - /* |x| < 0.5, up to 1.7ulp error */ - y = 0.5f*log1pf(2*y + 2*y*y/(1-y)); - } - } else { - /* avoid overflow */ - y = 0.5f*log1pf(2*(y/(1-y))); - } - return s ? -y : y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/ef_rem_pio2.c b/MicroPython_BUILD/components/micropython/lib/libm/ef_rem_pio2.c deleted file mode 100644 index ca55243f..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/ef_rem_pio2.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* ef_rem_pio2.c -- float version of e_rem_pio2.c - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -/* __ieee754_rem_pio2f(x,y) - * - * return the remainder of x rem pi/2 in y[0]+y[1] - * use __kernel_rem_pio2f() - */ - -#include "fdlibm.h" - -/* - * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi - */ -#ifdef __STDC__ -static const __int32_t two_over_pi[] = { -#else -static __int32_t two_over_pi[] = { -#endif -0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC, -0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62, -0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63, -0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A, -0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09, -0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29, -0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44, -0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41, -0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C, -0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8, -0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11, -0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF, -0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E, -0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5, -0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92, -0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08, -0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0, -0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3, -0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85, -0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80, -0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA, -0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B, -}; - -/* This array is like the one in e_rem_pio2.c, but the numbers are - single precision and the last 8 bits are forced to 0. */ -#ifdef __STDC__ -static const __int32_t npio2_hw[] = { -#else -static __int32_t npio2_hw[] = { -#endif -0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00, -0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00, -0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100, -0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00, -0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00, -0x4242c700, 0x42490f00 -}; - -/* - * invpio2: 24 bits of 2/pi - * pio2_1: first 17 bit of pi/2 - * pio2_1t: pi/2 - pio2_1 - * pio2_2: second 17 bit of pi/2 - * pio2_2t: pi/2 - (pio2_1+pio2_2) - * pio2_3: third 17 bit of pi/2 - * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) - */ - -#ifdef __STDC__ -static const float -#else -static float -#endif -zero = 0.0000000000e+00, /* 0x00000000 */ -half = 5.0000000000e-01, /* 0x3f000000 */ -two8 = 2.5600000000e+02, /* 0x43800000 */ -invpio2 = 6.3661980629e-01, /* 0x3f22f984 */ -pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */ -pio2_1t = 1.0804334124e-05, /* 0x37354443 */ -pio2_2 = 1.0804273188e-05, /* 0x37354400 */ -pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */ -pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */ -pio2_3t = 6.1232342629e-17; /* 0x248d3132 */ - -#ifdef __STDC__ - __int32_t __ieee754_rem_pio2f(float x, float *y) -#else - __int32_t __ieee754_rem_pio2f(x,y) - float x,y[]; -#endif -{ - float z,w,t,r,fn; - float tx[3]; - __int32_t i,j,n,ix,hx; - int e0,nx; - - GET_FLOAT_WORD(hx,x); - ix = hx&0x7fffffff; - if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */ - {y[0] = x; y[1] = 0; return 0;} - if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */ - if(hx>0) { - z = x - pio2_1; - if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ - y[0] = z - pio2_1t; - y[1] = (z-y[0])-pio2_1t; - } else { /* near pi/2, use 24+24+24 bit pi */ - z -= pio2_2; - y[0] = z - pio2_2t; - y[1] = (z-y[0])-pio2_2t; - } - return 1; - } else { /* negative x */ - z = x + pio2_1; - if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ - y[0] = z + pio2_1t; - y[1] = (z-y[0])+pio2_1t; - } else { /* near pi/2, use 24+24+24 bit pi */ - z += pio2_2; - y[0] = z + pio2_2t; - y[1] = (z-y[0])+pio2_2t; - } - return -1; - } - } - if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */ - t = fabsf(x); - n = (__int32_t) (t*invpio2+half); - fn = (float)n; - r = t-fn*pio2_1; - w = fn*pio2_1t; /* 1st round good to 40 bit */ - if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) { - y[0] = r-w; /* quick check no cancellation */ - } else { - __uint32_t high; - j = ix>>23; - y[0] = r-w; - GET_FLOAT_WORD(high,y[0]); - i = j-((high>>23)&0xff); - if(i>8) { /* 2nd iteration needed, good to 57 */ - t = r; - w = fn*pio2_2; - r = t-w; - w = fn*pio2_2t-((t-r)-w); - y[0] = r-w; - GET_FLOAT_WORD(high,y[0]); - i = j-((high>>23)&0xff); - if(i>25) { /* 3rd iteration need, 74 bits acc */ - t = r; /* will cover all possible cases */ - w = fn*pio2_3; - r = t-w; - w = fn*pio2_3t-((t-r)-w); - y[0] = r-w; - } - } - } - y[1] = (r-y[0])-w; - if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} - else return n; - } - /* - * all other (large) arguments - */ - if(!FLT_UWORD_IS_FINITE(ix)) { - y[0]=y[1]=x-x; return 0; - } - /* set z = scalbn(|x|,ilogb(x)-7) */ - e0 = (int)((ix>>23)-134); /* e0 = ilogb(z)-7; */ - SET_FLOAT_WORD(z, ix - ((__int32_t)e0<<23)); - for(i=0;i<2;i++) { - tx[i] = (float)((__int32_t)(z)); - z = (z-tx[i])*two8; - } - tx[2] = z; - nx = 3; - while(tx[nx-1]==zero) nx--; /* skip zero term */ - n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi); - if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} - return n; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/ef_sqrt.c b/MicroPython_BUILD/components/micropython/lib/libm/ef_sqrt.c deleted file mode 100644 index 87484d0b..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/ef_sqrt.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* ef_sqrtf.c -- float version of e_sqrt.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const float one = 1.0, tiny=1.0e-30; -#else -static float one = 1.0, tiny=1.0e-30; -#endif - -// sqrtf is exactly __ieee754_sqrtf when _IEEE_LIBM defined -float sqrtf(float x) -/* -#ifdef __STDC__ - float __ieee754_sqrtf(float x) -#else - float __ieee754_sqrtf(x) - float x; -#endif -*/ -{ - float z; - __uint32_t r,hx; - __int32_t ix,s,q,m,t,i; - - GET_FLOAT_WORD(ix,x); - hx = ix&0x7fffffff; - - /* take care of Inf and NaN */ - if(!FLT_UWORD_IS_FINITE(hx)) - return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf - sqrt(-inf)=sNaN */ - /* take care of zero and -ves */ - if(FLT_UWORD_IS_ZERO(hx)) return x;/* sqrt(+-0) = +-0 */ - if(ix<0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - - /* normalize x */ - m = (ix>>23); - if(FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */ - for(i=0;(ix&0x00800000L)==0;i++) ix<<=1; - m -= i-1; - } - m -= 127; /* unbias exponent */ - ix = (ix&0x007fffffL)|0x00800000L; - if(m&1) /* odd m, double x to make it even */ - ix += ix; - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix += ix; - q = s = 0; /* q = sqrt(x) */ - r = 0x01000000L; /* r = moving bit from right to left */ - - while(r!=0) { - t = s+r; - if(t<=ix) { - s = t+r; - ix -= t; - q += r; - } - ix += ix; - r>>=1; - } - - /* use floating add to find out rounding direction */ - if(ix!=0) { - z = one-tiny; /* trigger inexact flag */ - if (z>=one) { - z = one+tiny; - if (z>one) - q += 2; - else - q += (q&1); - } - } - ix = (q>>1)+0x3f000000L; - ix += (m <<23); - SET_FLOAT_WORD(z,ix); - return z; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/erf_lgamma.c b/MicroPython_BUILD/components/micropython/lib/libm/erf_lgamma.c deleted file mode 100644 index 877816a0..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/erf_lgamma.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* erf_lgamma.c -- float version of er_lgamma.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -#include "fdlibm.h" - -#define __ieee754_logf logf - -#ifdef __STDC__ -static const float -#else -static float -#endif -two23= 8.3886080000e+06, /* 0x4b000000 */ -half= 5.0000000000e-01, /* 0x3f000000 */ -one = 1.0000000000e+00, /* 0x3f800000 */ -pi = 3.1415927410e+00, /* 0x40490fdb */ -a0 = 7.7215664089e-02, /* 0x3d9e233f */ -a1 = 3.2246702909e-01, /* 0x3ea51a66 */ -a2 = 6.7352302372e-02, /* 0x3d89f001 */ -a3 = 2.0580807701e-02, /* 0x3ca89915 */ -a4 = 7.3855509982e-03, /* 0x3bf2027e */ -a5 = 2.8905137442e-03, /* 0x3b3d6ec6 */ -a6 = 1.1927076848e-03, /* 0x3a9c54a1 */ -a7 = 5.1006977446e-04, /* 0x3a05b634 */ -a8 = 2.2086278477e-04, /* 0x39679767 */ -a9 = 1.0801156895e-04, /* 0x38e28445 */ -a10 = 2.5214456400e-05, /* 0x37d383a2 */ -a11 = 4.4864096708e-05, /* 0x383c2c75 */ -tc = 1.4616321325e+00, /* 0x3fbb16c3 */ -tf = -1.2148628384e-01, /* 0xbdf8cdcd */ -/* tt = -(tail of tf) */ -tt = 6.6971006518e-09, /* 0x31e61c52 */ -t0 = 4.8383611441e-01, /* 0x3ef7b95e */ -t1 = -1.4758771658e-01, /* 0xbe17213c */ -t2 = 6.4624942839e-02, /* 0x3d845a15 */ -t3 = -3.2788541168e-02, /* 0xbd064d47 */ -t4 = 1.7970675603e-02, /* 0x3c93373d */ -t5 = -1.0314224288e-02, /* 0xbc28fcfe */ -t6 = 6.1005386524e-03, /* 0x3bc7e707 */ -t7 = -3.6845202558e-03, /* 0xbb7177fe */ -t8 = 2.2596477065e-03, /* 0x3b141699 */ -t9 = -1.4034647029e-03, /* 0xbab7f476 */ -t10 = 8.8108185446e-04, /* 0x3a66f867 */ -t11 = -5.3859531181e-04, /* 0xba0d3085 */ -t12 = 3.1563205994e-04, /* 0x39a57b6b */ -t13 = -3.1275415677e-04, /* 0xb9a3f927 */ -t14 = 3.3552918467e-04, /* 0x39afe9f7 */ -u0 = -7.7215664089e-02, /* 0xbd9e233f */ -u1 = 6.3282704353e-01, /* 0x3f2200f4 */ -u2 = 1.4549225569e+00, /* 0x3fba3ae7 */ -u3 = 9.7771751881e-01, /* 0x3f7a4bb2 */ -u4 = 2.2896373272e-01, /* 0x3e6a7578 */ -u5 = 1.3381091878e-02, /* 0x3c5b3c5e */ -v1 = 2.4559779167e+00, /* 0x401d2ebe */ -v2 = 2.1284897327e+00, /* 0x4008392d */ -v3 = 7.6928514242e-01, /* 0x3f44efdf */ -v4 = 1.0422264785e-01, /* 0x3dd572af */ -v5 = 3.2170924824e-03, /* 0x3b52d5db */ -s0 = -7.7215664089e-02, /* 0xbd9e233f */ -s1 = 2.1498242021e-01, /* 0x3e5c245a */ -s2 = 3.2577878237e-01, /* 0x3ea6cc7a */ -s3 = 1.4635047317e-01, /* 0x3e15dce6 */ -s4 = 2.6642270386e-02, /* 0x3cda40e4 */ -s5 = 1.8402845599e-03, /* 0x3af135b4 */ -s6 = 3.1947532989e-05, /* 0x3805ff67 */ -r1 = 1.3920053244e+00, /* 0x3fb22d3b */ -r2 = 7.2193557024e-01, /* 0x3f38d0c5 */ -r3 = 1.7193385959e-01, /* 0x3e300f6e */ -r4 = 1.8645919859e-02, /* 0x3c98bf54 */ -r5 = 7.7794247773e-04, /* 0x3a4beed6 */ -r6 = 7.3266842264e-06, /* 0x36f5d7bd */ -w0 = 4.1893854737e-01, /* 0x3ed67f1d */ -w1 = 8.3333335817e-02, /* 0x3daaaaab */ -w2 = -2.7777778450e-03, /* 0xbb360b61 */ -w3 = 7.9365057172e-04, /* 0x3a500cfd */ -w4 = -5.9518753551e-04, /* 0xba1c065c */ -w5 = 8.3633989561e-04, /* 0x3a5b3dd2 */ -w6 = -1.6309292987e-03; /* 0xbad5c4e8 */ - -#ifdef __STDC__ -static const float zero= 0.0000000000e+00; -#else -static float zero= 0.0000000000e+00; -#endif - -#ifdef __STDC__ - static float sin_pif(float x) -#else - static float sin_pif(x) - float x; -#endif -{ - float y,z; - __int32_t n,ix; - - GET_FLOAT_WORD(ix,x); - ix &= 0x7fffffff; - - if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0); - y = -x; /* x is assume negative */ - - /* - * argument reduction, make sure inexact flag not raised if input - * is an integer - */ - z = floorf(y); - if(z!=y) { /* inexact anyway */ - y *= (float)0.5; - y = (float)2.0*(y - floorf(y)); /* y = |x| mod 2.0 */ - n = (__int32_t) (y*(float)4.0); - } else { - if(ix>=0x4b800000) { - y = zero; n = 0; /* y must be even */ - } else { - if(ix<0x4b000000) z = y+two23; /* exact */ - GET_FLOAT_WORD(n,z); - n &= 1; - y = n; - n<<= 2; - } - } - switch (n) { - case 0: y = __kernel_sinf(pi*y,zero,0); break; - case 1: - case 2: y = __kernel_cosf(pi*((float)0.5-y),zero); break; - case 3: - case 4: y = __kernel_sinf(pi*(one-y),zero,0); break; - case 5: - case 6: y = -__kernel_cosf(pi*(y-(float)1.5),zero); break; - default: y = __kernel_sinf(pi*(y-(float)2.0),zero,0); break; - } - return -y; -} - - -#ifdef __STDC__ - float __ieee754_lgammaf_r(float x, int *signgamp) -#else - float __ieee754_lgammaf_r(x,signgamp) - float x; int *signgamp; -#endif -{ - float t,y,z,nadj = 0.0,p,p1,p2,p3,q,r,w; - __int32_t i,hx,ix; - - GET_FLOAT_WORD(hx,x); - - /* purge off +-inf, NaN, +-0, and negative arguments */ - *signgamp = 1; - ix = hx&0x7fffffff; - if(ix>=0x7f800000) return x*x; - if(ix==0) return one/zero; - if(ix<0x1c800000) { /* |x|<2**-70, return -log(|x|) */ - if(hx<0) { - *signgamp = -1; - return -__ieee754_logf(-x); - } else return -__ieee754_logf(x); - } - if(hx<0) { - if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */ - return one/zero; - t = sin_pif(x); - if(t==zero) return one/zero; /* -integer */ - nadj = __ieee754_logf(pi/fabsf(t*x)); - if(t=0x3f3b4a20) {y = one-x; i= 0;} - else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;} - else {y = x; i=2;} - } else { - r = zero; - if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */ - else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */ - else {y=x-one;i=2;} - } - switch(i) { - case 0: - z = y*y; - p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); - p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); - p = y*p1+p2; - r += (p-(float)0.5*y); break; - case 1: - z = y*y; - w = z*y; - p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ - p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); - p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); - p = z*p1-(tt-w*(p2+y*p3)); - r += (tf + p); break; - case 2: - p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); - p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); - r += (-(float)0.5*y + p1/p2); - } - } - else if(ix<0x41000000) { /* x < 8.0 */ - i = (__int32_t)x; - t = zero; - y = x-(float)i; - p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); - q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); - r = half*y+p/q; - z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ - switch(i) { - case 7: z *= (y+(float)6.0); /* FALLTHRU */ - case 6: z *= (y+(float)5.0); /* FALLTHRU */ - case 5: z *= (y+(float)4.0); /* FALLTHRU */ - case 4: z *= (y+(float)3.0); /* FALLTHRU */ - case 3: z *= (y+(float)2.0); /* FALLTHRU */ - r += __ieee754_logf(z); break; - } - /* 8.0 <= x < 2**58 */ - } else if (ix < 0x5c800000) { - t = __ieee754_logf(x); - z = one/x; - y = z*z; - w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); - r = (x-half)*(t-one)+w; - } else - /* 2**58 <= x <= inf */ - r = x*(__ieee754_logf(x)-one); - if(hx<0) r = nadj - r; - return r; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/fdlibm.h b/MicroPython_BUILD/components/micropython/lib/libm/fdlibm.h deleted file mode 100644 index ace3b2da..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/fdlibm.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * This file is adapted from from newlib-nano-2, the newlib/libm/common/fdlib.h, - * available from https://github.com/32bitmicro/newlib-nano-2. The main change - * is removal of anything to do with double precision. - * - * Appropriate copyright headers are reproduced below. - */ - -/* @(#)fdlibm.h 5.1 93/09/24 */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include - -/* Default to XOPEN_MODE. */ -#define _XOPEN_MODE - -/* Most routines need to check whether a float is finite, infinite, or not a - number, and many need to know whether the result of an operation will - overflow. These conditions depend on whether the largest exponent is - used for NaNs & infinities, or whether it's used for finite numbers. The - macros below wrap up that kind of information: - - FLT_UWORD_IS_FINITE(X) - True if a positive float with bitmask X is finite. - - FLT_UWORD_IS_NAN(X) - True if a positive float with bitmask X is not a number. - - FLT_UWORD_IS_INFINITE(X) - True if a positive float with bitmask X is +infinity. - - FLT_UWORD_MAX - The bitmask of FLT_MAX. - - FLT_UWORD_HALF_MAX - The bitmask of FLT_MAX/2. - - FLT_UWORD_EXP_MAX - The bitmask of the largest finite exponent (129 if the largest - exponent is used for finite numbers, 128 otherwise). - - FLT_UWORD_LOG_MAX - The bitmask of log(FLT_MAX), rounded down. This value is the largest - input that can be passed to exp() without producing overflow. - - FLT_UWORD_LOG_2MAX - The bitmask of log(2*FLT_MAX), rounded down. This value is the - largest input than can be passed to cosh() without producing - overflow. - - FLT_LARGEST_EXP - The largest biased exponent that can be used for finite numbers - (255 if the largest exponent is used for finite numbers, 254 - otherwise) */ - -#ifdef _FLT_LARGEST_EXPONENT_IS_NORMAL -#define FLT_UWORD_IS_FINITE(x) 1 -#define FLT_UWORD_IS_NAN(x) 0 -#define FLT_UWORD_IS_INFINITE(x) 0 -#define FLT_UWORD_MAX 0x7fffffff -#define FLT_UWORD_EXP_MAX 0x43010000 -#define FLT_UWORD_LOG_MAX 0x42b2d4fc -#define FLT_UWORD_LOG_2MAX 0x42b437e0 -#define HUGE ((float)0X1.FFFFFEP128) -#else -#define FLT_UWORD_IS_FINITE(x) ((x)<0x7f800000L) -#define FLT_UWORD_IS_NAN(x) ((x)>0x7f800000L) -#define FLT_UWORD_IS_INFINITE(x) ((x)==0x7f800000L) -#define FLT_UWORD_MAX 0x7f7fffffL -#define FLT_UWORD_EXP_MAX 0x43000000 -#define FLT_UWORD_LOG_MAX 0x42b17217 -#define FLT_UWORD_LOG_2MAX 0x42b2d4fc -#define HUGE ((float)3.40282346638528860e+38) -#endif -#define FLT_UWORD_HALF_MAX (FLT_UWORD_MAX-(1L<<23)) -#define FLT_LARGEST_EXP (FLT_UWORD_MAX>>23) - -/* Many routines check for zero and subnormal numbers. Such things depend - on whether the target supports denormals or not: - - FLT_UWORD_IS_ZERO(X) - True if a positive float with bitmask X is +0. Without denormals, - any float with a zero exponent is a +0 representation. With - denormals, the only +0 representation is a 0 bitmask. - - FLT_UWORD_IS_SUBNORMAL(X) - True if a non-zero positive float with bitmask X is subnormal. - (Routines should check for zeros first.) - - FLT_UWORD_MIN - The bitmask of the smallest float above +0. Call this number - REAL_FLT_MIN... - - FLT_UWORD_EXP_MIN - The bitmask of the float representation of REAL_FLT_MIN's exponent. - - FLT_UWORD_LOG_MIN - The bitmask of |log(REAL_FLT_MIN)|, rounding down. - - FLT_SMALLEST_EXP - REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported, - -22 if they are). -*/ - -#ifdef _FLT_NO_DENORMALS -#define FLT_UWORD_IS_ZERO(x) ((x)<0x00800000L) -#define FLT_UWORD_IS_SUBNORMAL(x) 0 -#define FLT_UWORD_MIN 0x00800000 -#define FLT_UWORD_EXP_MIN 0x42fc0000 -#define FLT_UWORD_LOG_MIN 0x42aeac50 -#define FLT_SMALLEST_EXP 1 -#else -#define FLT_UWORD_IS_ZERO(x) ((x)==0) -#define FLT_UWORD_IS_SUBNORMAL(x) ((x)<0x00800000L) -#define FLT_UWORD_MIN 0x00000001 -#define FLT_UWORD_EXP_MIN 0x43160000 -#define FLT_UWORD_LOG_MIN 0x42cff1b5 -#define FLT_SMALLEST_EXP -22 -#endif - -#ifdef __STDC__ -#undef __P -#define __P(p) p -#else -#define __P(p) () -#endif - -/* - * set X_TLOSS = pi*2**52, which is possibly defined in - * (one may replace the following line by "#include ") - */ - -#define X_TLOSS 1.41484755040568800000e+16 - -/* Functions that are not documented, and are not in . */ - -/* Undocumented float functions. */ -#ifdef _SCALB_INT -extern float scalbf __P((float, int)); -#else -extern float scalbf __P((float, float)); -#endif -extern float significandf __P((float)); - -/* ieee style elementary float functions */ -extern float __ieee754_sqrtf __P((float)); -extern float __ieee754_acosf __P((float)); -extern float __ieee754_acoshf __P((float)); -extern float __ieee754_logf __P((float)); -extern float __ieee754_atanhf __P((float)); -extern float __ieee754_asinf __P((float)); -extern float __ieee754_atan2f __P((float,float)); -extern float __ieee754_expf __P((float)); -extern float __ieee754_coshf __P((float)); -extern float __ieee754_fmodf __P((float,float)); -extern float __ieee754_powf __P((float,float)); -extern float __ieee754_lgammaf_r __P((float,int *)); -extern float __ieee754_gammaf_r __P((float,int *)); -extern float __ieee754_log10f __P((float)); -extern float __ieee754_sinhf __P((float)); -extern float __ieee754_hypotf __P((float,float)); -extern float __ieee754_j0f __P((float)); -extern float __ieee754_j1f __P((float)); -extern float __ieee754_y0f __P((float)); -extern float __ieee754_y1f __P((float)); -extern float __ieee754_jnf __P((int,float)); -extern float __ieee754_ynf __P((int,float)); -extern float __ieee754_remainderf __P((float,float)); -extern __int32_t __ieee754_rem_pio2f __P((float,float*)); -#ifdef _SCALB_INT -extern float __ieee754_scalbf __P((float,int)); -#else -extern float __ieee754_scalbf __P((float,float)); -#endif - -/* float versions of fdlibm kernel functions */ -extern float __kernel_sinf __P((float,float,int)); -extern float __kernel_cosf __P((float,float)); -extern float __kernel_tanf __P((float,float,int)); -extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const __int32_t*)); - -/* A union which permits us to convert between a float and a 32 bit - int. */ - -typedef union -{ - float value; - __uint32_t word; -} ieee_float_shape_type; - -/* Get a 32 bit int from a float. */ - -#define GET_FLOAT_WORD(i,d) \ -do { \ - ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ -} while (0) - -/* Set a float from a 32 bit int. */ - -#define SET_FLOAT_WORD(d,i) \ -do { \ - ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ -} while (0) - -/* Macros to avoid undefined behaviour that can arise if the amount - of a shift is exactly equal to the size of the shifted operand. */ - -#define SAFE_LEFT_SHIFT(op,amt) \ - (((amt) < 8 * sizeof(op)) ? ((op) << (amt)) : 0) - -#define SAFE_RIGHT_SHIFT(op,amt) \ - (((amt) < 8 * sizeof(op)) ? ((op) >> (amt)) : 0) diff --git a/MicroPython_BUILD/components/micropython/lib/libm/fmodf.c b/MicroPython_BUILD/components/micropython/lib/libm/fmodf.c deleted file mode 100644 index 69a9ad91..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/fmodf.c +++ /dev/null @@ -1,70 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// fmodf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -#include "libm.h" - -float fmodf(float x, float y) -{ - union {float f; uint32_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>23 & 0xff; - int ey = uy.i>>23 & 0xff; - uint32_t sx = ux.i & 0x80000000; - uint32_t i; - uint32_t uxi = ux.i; - - if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) - return (x*y)/(x*y); - if (uxi<<1 <= uy.i<<1) { - if (uxi<<1 == uy.i<<1) - return 0*x; - return x; - } - - /* normalize x and y */ - if (!ex) { - for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1U >> 9; - uxi |= 1U << 23; - } - if (!ey) { - for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1U >> 9; - uy.i |= 1U << 23; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - for (; uxi>>23 == 0; uxi <<= 1, ex--); - - /* scale result up */ - if (ex > 0) { - uxi -= 1U << 23; - uxi |= (uint32_t)ex << 23; - } else { - uxi >>= -ex + 1; - } - uxi |= sx; - ux.i = uxi; - return ux.f; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/kf_cos.c b/MicroPython_BUILD/components/micropython/lib/libm/kf_cos.c deleted file mode 100644 index 691f9842..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/kf_cos.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* kf_cos.c -- float version of k_cos.c - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const float -#else -static float -#endif -one = 1.0000000000e+00, /* 0x3f800000 */ -C1 = 4.1666667908e-02, /* 0x3d2aaaab */ -C2 = -1.3888889225e-03, /* 0xbab60b61 */ -C3 = 2.4801587642e-05, /* 0x37d00d01 */ -C4 = -2.7557314297e-07, /* 0xb493f27c */ -C5 = 2.0875723372e-09, /* 0x310f74f6 */ -C6 = -1.1359647598e-11; /* 0xad47d74e */ - -#ifdef __STDC__ - float __kernel_cosf(float x, float y) -#else - float __kernel_cosf(x, y) - float x,y; -#endif -{ - float a,hz,z,r,qx; - __int32_t ix; - GET_FLOAT_WORD(ix,x); - ix &= 0x7fffffff; /* ix = |x|'s high word*/ - if(ix<0x32000000) { /* if x < 2**27 */ - if(((int)x)==0) return one; /* generate inexact */ - } - z = x*x; - r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); - if(ix < 0x3e99999a) /* if |x| < 0.3 */ - return one - ((float)0.5*z - (z*r - x*y)); - else { - if(ix > 0x3f480000) { /* x > 0.78125 */ - qx = (float)0.28125; - } else { - SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */ - } - hz = (float)0.5*z-qx; - a = one-qx; - return a - (hz - (z*r-x*y)); - } -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/kf_rem_pio2.c b/MicroPython_BUILD/components/micropython/lib/libm/kf_rem_pio2.c deleted file mode 100644 index c7e94795..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/kf_rem_pio2.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* kf_rem_pio2.c -- float version of k_rem_pio2.c - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -/* In the float version, the input parameter x contains 8 bit - integers, not 24 bit integers. 113 bit precision is not supported. */ - -#ifdef __STDC__ -static const int init_jk[] = {4,7,9}; /* initial value for jk */ -#else -static int init_jk[] = {4,7,9}; -#endif - -#ifdef __STDC__ -static const float PIo2[] = { -#else -static float PIo2[] = { -#endif - 1.5703125000e+00, /* 0x3fc90000 */ - 4.5776367188e-04, /* 0x39f00000 */ - 2.5987625122e-05, /* 0x37da0000 */ - 7.5437128544e-08, /* 0x33a20000 */ - 6.0026650317e-11, /* 0x2e840000 */ - 7.3896444519e-13, /* 0x2b500000 */ - 5.3845816694e-15, /* 0x27c20000 */ - 5.6378512969e-18, /* 0x22d00000 */ - 8.3009228831e-20, /* 0x1fc40000 */ - 3.2756352257e-22, /* 0x1bc60000 */ - 6.3331015649e-25, /* 0x17440000 */ -}; - -#ifdef __STDC__ -static const float -#else -static float -#endif -zero = 0.0, -one = 1.0, -two8 = 2.5600000000e+02, /* 0x43800000 */ -twon8 = 3.9062500000e-03; /* 0x3b800000 */ - -#ifdef __STDC__ - int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const __int32_t *ipio2) -#else - int __kernel_rem_pio2f(x,y,e0,nx,prec,ipio2) - float x[], y[]; int e0,nx,prec; __int32_t ipio2[]; -#endif -{ - __int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; - float z,fw,f[20],fq[20],q[20]; - - /* initialize jk*/ - jk = init_jk[prec]; - jp = jk; - - /* determine jx,jv,q0, note that 3>q0 */ - jx = nx-1; - jv = (e0-3)/8; if(jv<0) jv=0; - q0 = e0-8*(jv+1); - - /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ - j = jv-jx; m = jx+jk; - for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j]; - - /* compute q[0],q[1],...q[jk] */ - for (i=0;i<=jk;i++) { - for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; - q[i] = fw; - } - - jz = jk; -recompute: - /* distill q[] into iq[] reversingly */ - for(i=0,j=jz,z=q[jz];j>0;i++,j--) { - fw = (float)((__int32_t)(twon8* z)); - iq[i] = (__int32_t)(z-two8*fw); - z = q[j-1]+fw; - } - - /* compute n */ - z = scalbnf(z,(int)q0); /* actual value of z */ - z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */ - n = (__int32_t) z; - z -= (float)n; - ih = 0; - if(q0>0) { /* need iq[jz-1] to determine n */ - i = (iq[jz-1]>>(8-q0)); n += i; - iq[jz-1] -= i<<(8-q0); - ih = iq[jz-1]>>(7-q0); - } - else if(q0==0) ih = iq[jz-1]>>8; - else if(z>=(float)0.5) ih=2; - - if(ih>0) { /* q > 0.5 */ - n += 1; carry = 0; - for(i=0;i0) { /* rare case: chance is 1 in 12 */ - switch(q0) { - case 1: - iq[jz-1] &= 0x7f; break; - case 2: - iq[jz-1] &= 0x3f; break; - } - } - if(ih==2) { - z = one - z; - if(carry!=0) z -= scalbnf(one,(int)q0); - } - } - - /* check if recomputation is needed */ - if(z==zero) { - j = 0; - for (i=jz-1;i>=jk;i--) j |= iq[i]; - if(j==0) { /* need recomputation */ - for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ - - for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ - f[jx+i] = (float) ipio2[jv+i]; - for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; - q[i] = fw; - } - jz += k; - goto recompute; - } - } - - /* chop off zero terms */ - if(z==(float)0.0) { - jz -= 1; q0 -= 8; - while(iq[jz]==0) { jz--; q0-=8;} - } else { /* break z into 8-bit if necessary */ - z = scalbnf(z,-(int)q0); - if(z>=two8) { - fw = (float)((__int32_t)(twon8*z)); - iq[jz] = (__int32_t)(z-two8*fw); - jz += 1; q0 += 8; - iq[jz] = (__int32_t) fw; - } else iq[jz] = (__int32_t) z ; - } - - /* convert integer "bit" chunk to floating-point value */ - fw = scalbnf(one,(int)q0); - for(i=jz;i>=0;i--) { - q[i] = fw*(float)iq[i]; fw*=twon8; - } - - /* compute PIo2[0,...,jp]*q[jz,...,0] */ - for(i=jz;i>=0;i--) { - for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; - fq[jz-i] = fw; - } - - /* compress fq[] into y[] */ - switch(prec) { - case 0: - fw = 0.0; - for (i=jz;i>=0;i--) fw += fq[i]; - y[0] = (ih==0)? fw: -fw; - break; - case 1: - case 2: - fw = 0.0; - for (i=jz;i>=0;i--) fw += fq[i]; - y[0] = (ih==0)? fw: -fw; - fw = fq[0]-fw; - for (i=1;i<=jz;i++) fw += fq[i]; - y[1] = (ih==0)? fw: -fw; - break; - case 3: /* painful */ - for (i=jz;i>0;i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (i=jz;i>1;i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; - if(ih==0) { - y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; - } else { - y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; - } - } - return n&7; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/kf_sin.c b/MicroPython_BUILD/components/micropython/lib/libm/kf_sin.c deleted file mode 100644 index 07ea9934..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/kf_sin.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* kf_sin.c -- float version of k_sin.c - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const float -#else -static float -#endif -half = 5.0000000000e-01,/* 0x3f000000 */ -S1 = -1.6666667163e-01, /* 0xbe2aaaab */ -S2 = 8.3333337680e-03, /* 0x3c088889 */ -S3 = -1.9841270114e-04, /* 0xb9500d01 */ -S4 = 2.7557314297e-06, /* 0x3638ef1b */ -S5 = -2.5050759689e-08, /* 0xb2d72f34 */ -S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */ - -#ifdef __STDC__ - float __kernel_sinf(float x, float y, int iy) -#else - float __kernel_sinf(x, y, iy) - float x,y; int iy; /* iy=0 if y is zero */ -#endif -{ - float z,r,v; - __int32_t ix; - GET_FLOAT_WORD(ix,x); - ix &= 0x7fffffff; /* high word of x */ - if(ix<0x32000000) /* |x| < 2**-27 */ - {if((int)x==0) return x;} /* generate inexact */ - z = x*x; - v = z*x; - r = S2+z*(S3+z*(S4+z*(S5+z*S6))); - if(iy==0) return x+v*(S1+z*r); - else return x-((z*(half*y-v*r)-y)-v*S1); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/kf_tan.c b/MicroPython_BUILD/components/micropython/lib/libm/kf_tan.c deleted file mode 100644 index 6da9bd81..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/kf_tan.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* kf_tan.c -- float version of k_tan.c - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "libm.h" -#ifdef __STDC__ -static const float -#else -static float -#endif -one = 1.0000000000e+00, /* 0x3f800000 */ -pio4 = 7.8539812565e-01, /* 0x3f490fda */ -pio4lo= 3.7748947079e-08, /* 0x33222168 */ -T[] = { - 3.3333334327e-01, /* 0x3eaaaaab */ - 1.3333334029e-01, /* 0x3e088889 */ - 5.3968254477e-02, /* 0x3d5d0dd1 */ - 2.1869488060e-02, /* 0x3cb327a4 */ - 8.8632395491e-03, /* 0x3c11371f */ - 3.5920790397e-03, /* 0x3b6b6916 */ - 1.4562094584e-03, /* 0x3abede48 */ - 5.8804126456e-04, /* 0x3a1a26c8 */ - 2.4646313977e-04, /* 0x398137b9 */ - 7.8179444245e-05, /* 0x38a3f445 */ - 7.1407252108e-05, /* 0x3895c07a */ - -1.8558637748e-05, /* 0xb79bae5f */ - 2.5907305826e-05, /* 0x37d95384 */ -}; - -#ifdef __STDC__ - float __kernel_tanf(float x, float y, int iy) -#else - float __kernel_tanf(x, y, iy) - float x,y; int iy; -#endif -{ - float z,r,v,w,s; - __int32_t ix,hx; - GET_FLOAT_WORD(hx,x); - ix = hx&0x7fffffff; /* high word of |x| */ - if(ix<0x31800000) /* x < 2**-28 */ - {if((int)x==0) { /* generate inexact */ - if((ix|(iy+1))==0) return one/fabsf(x); - else return (iy==1)? x: -one/x; - } - } - if(ix>=0x3f2ca140) { /* |x|>=0.6744 */ - if(hx<0) {x = -x; y = -y;} - z = pio4-x; - w = pio4lo-y; - x = z+w; y = 0.0; - } - z = x*x; - w = z*z; - /* Break x^5*(T[1]+x^2*T[2]+...) into - * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + - * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) - */ - r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11])))); - v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12]))))); - s = z*x; - r = y + z*(s*(r+v)+y); - r += T[0]*s; - w = x+r; - if(ix>=0x3f2ca140) { - v = (float)iy; - return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r))); - } - if(iy==1) return w; - else { /* if allow error up to 2 ulp, - simply return -1.0/(x+r) here */ - /* compute -1.0/(x+r) accurately */ - float a,t; - __int32_t i; - z = w; - GET_FLOAT_WORD(i,z); - SET_FLOAT_WORD(z,i&0xfffff000); - v = r-(z - x); /* z+v = r+x */ - t = a = -(float)1.0/w; /* a = -1.0/w */ - GET_FLOAT_WORD(i,t); - SET_FLOAT_WORD(t,i&0xfffff000); - s = (float)1.0+t*z; - return t+a*(s+t*v); - } -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/libm.h b/MicroPython_BUILD/components/micropython/lib/libm/libm.h deleted file mode 100644 index f782249e..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/libm.h +++ /dev/null @@ -1,54 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// portions extracted from musl-0.9.15 libm.h -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include -#include - -#define FLT_EVAL_METHOD 0 - -#define FORCE_EVAL(x) do { \ - if (sizeof(x) == sizeof(float)) { \ - volatile float __x; \ - __x = (x); \ - (void)__x; \ - } else if (sizeof(x) == sizeof(double)) { \ - volatile double __x; \ - __x = (x); \ - (void)__x; \ - } else { \ - volatile long double __x; \ - __x = (x); \ - (void)__x; \ - } \ -} while(0) - -/* Get a 32 bit int from a float. */ -#define GET_FLOAT_WORD(w,d) \ -do { \ - union {float f; uint32_t i;} __u; \ - __u.f = (d); \ - (w) = __u.i; \ -} while (0) - -/* Set a float from a 32 bit int. */ -#define SET_FLOAT_WORD(d,w) \ -do { \ - union {float f; uint32_t i;} __u; \ - __u.i = (w); \ - (d) = __u.f; \ -} while (0) diff --git a/MicroPython_BUILD/components/micropython/lib/libm/log1pf.c b/MicroPython_BUILD/components/micropython/lib/libm/log1pf.c deleted file mode 100644 index 0d32b0a2..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/log1pf.c +++ /dev/null @@ -1,83 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// log1pf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/s_log1pf.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "libm.h" - -static const float -ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ -ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ -/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ -Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ -Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ -Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ -Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ - -float log1pf(float x) -{ - union {float f; uint32_t i;} u = {x}; - float_t hfsq,f,c,s,z,R,w,t1,t2,dk; - uint32_t ix,iu; - int k; - - ix = u.i; - k = 1; - if (ix < 0x3ed413d0 || ix>>31) { /* 1+x < sqrt(2)+ */ - if (ix >= 0xbf800000) { /* x <= -1.0 */ - if (x == -1) - return x/0.0f; /* log1p(-1)=+inf */ - return (x-x)/0.0f; /* log1p(x<-1)=NaN */ - } - if (ix<<1 < 0x33800000<<1) { /* |x| < 2**-24 */ - /* underflow if subnormal */ - if ((ix&0x7f800000) == 0) - FORCE_EVAL(x*x); - return x; - } - if (ix <= 0xbe95f619) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ - k = 0; - c = 0; - f = x; - } - } else if (ix >= 0x7f800000) - return x; - if (k) { - u.f = 1 + x; - iu = u.i; - iu += 0x3f800000 - 0x3f3504f3; - k = (int)(iu>>23) - 0x7f; - /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ - if (k < 25) { - c = k >= 2 ? 1-(u.f-x) : x-(u.f-1); - c /= u.f; - } else - c = 0; - /* reduce u into [sqrt(2)/2, sqrt(2)] */ - iu = (iu&0x007fffff) + 0x3f3504f3; - u.i = iu; - f = u.f - 1; - } - s = f/(2.0f + f); - z = s*s; - w = z*z; - t1= w*(Lg2+w*Lg4); - t2= z*(Lg1+w*Lg3); - R = t2 + t1; - hfsq = 0.5f*f*f; - dk = k; - return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/math.c b/MicroPython_BUILD/components/micropython/lib/libm/math.c deleted file mode 100644 index 6b65202c..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/math.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * 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 "libm.h" - -typedef float float_t; -typedef union { - float f; - struct { - uint64_t m : 23; - uint64_t e : 8; - uint64_t s : 1; - }; -} float_s_t; - -#ifndef NDEBUG -float copysignf(float x, float y) { - float_s_t fx={.f = x}; - float_s_t fy={.f = y}; - - // copy sign bit; - fx.s = fy.s; - - return fx.f; -} -#endif - -static const float _M_LN10 = 2.30258509299404; // 0x40135d8e -float log10f(float x) { return logf(x) / (float)_M_LN10; } - -float tanhf(float x) { - if (isinf(x)) { - return copysignf(1, x); - } - return sinhf(x) / coshf(x); -} - -/*****************************************************************************/ -/*****************************************************************************/ -// __fpclassifyf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -int __fpclassifyf(float x) -{ - union {float f; uint32_t i;} u = {x}; - int e = u.i>>23 & 0xff; - if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; - if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE; - return FP_NORMAL; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// scalbnf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -float scalbnf(float x, int n) -{ - union {float f; uint32_t i;} u; - float_t y = x; - - if (n > 127) { - y *= 0x1p127f; - n -= 127; - if (n > 127) { - y *= 0x1p127f; - n -= 127; - if (n > 127) - n = 127; - } - } else if (n < -126) { - y *= 0x1p-126f; - n += 126; - if (n < -126) { - y *= 0x1p-126f; - n += 126; - if (n < -126) - n = -126; - } - } - u.i = (uint32_t)(0x7f+n)<<23; - x = y * u.f; - return x; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// powf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/e_powf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -static const float -bp[] = {1.0, 1.5,}, -dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */ -dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */ -two24 = 16777216.0, /* 0x4b800000 */ -huge = 1.0e30, -tiny = 1.0e-30, -/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ -L1 = 6.0000002384e-01, /* 0x3f19999a */ -L2 = 4.2857143283e-01, /* 0x3edb6db7 */ -L3 = 3.3333334327e-01, /* 0x3eaaaaab */ -L4 = 2.7272811532e-01, /* 0x3e8ba305 */ -L5 = 2.3066075146e-01, /* 0x3e6c3255 */ -L6 = 2.0697501302e-01, /* 0x3e53f142 */ -P1 = 1.6666667163e-01, /* 0x3e2aaaab */ -P2 = -2.7777778450e-03, /* 0xbb360b61 */ -P3 = 6.6137559770e-05, /* 0x388ab355 */ -P4 = -1.6533901999e-06, /* 0xb5ddea0e */ -P5 = 4.1381369442e-08, /* 0x3331bb4c */ -lg2 = 6.9314718246e-01, /* 0x3f317218 */ -lg2_h = 6.93145752e-01, /* 0x3f317200 */ -lg2_l = 1.42860654e-06, /* 0x35bfbe8c */ -ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */ -cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */ -cp_h = 9.6191406250e-01, /* 0x3f764000 =12b cp */ -cp_l = -1.1736857402e-04, /* 0xb8f623c6 =tail of cp_h */ -ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */ -ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/ -ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/ - -float powf(float x, float y) -{ - float z,ax,z_h,z_l,p_h,p_l; - float y1,t1,t2,r,s,sn,t,u,v,w; - int32_t i,j,k,yisint,n; - int32_t hx,hy,ix,iy,is; - - GET_FLOAT_WORD(hx, x); - GET_FLOAT_WORD(hy, y); - ix = hx & 0x7fffffff; - iy = hy & 0x7fffffff; - - /* x**0 = 1, even if x is NaN */ - if (iy == 0) - return 1.0f; - /* 1**y = 1, even if y is NaN */ - if (hx == 0x3f800000) - return 1.0f; - /* NaN if either arg is NaN */ - if (ix > 0x7f800000 || iy > 0x7f800000) - return x + y; - - /* determine if y is an odd int when x < 0 - * yisint = 0 ... y is not an integer - * yisint = 1 ... y is an odd int - * yisint = 2 ... y is an even int - */ - yisint = 0; - if (hx < 0) { - if (iy >= 0x4b800000) - yisint = 2; /* even integer y */ - else if (iy >= 0x3f800000) { - k = (iy>>23) - 0x7f; /* exponent */ - j = iy>>(23-k); - if ((j<<(23-k)) == iy) - yisint = 2 - (j & 1); - } - } - - /* special value of y */ - if (iy == 0x7f800000) { /* y is +-inf */ - if (ix == 0x3f800000) /* (-1)**+-inf is 1 */ - return 1.0f; - else if (ix > 0x3f800000) /* (|x|>1)**+-inf = inf,0 */ - return hy >= 0 ? y : 0.0f; - else if (ix != 0) /* (|x|<1)**+-inf = 0,inf if x!=0 */ - return hy >= 0 ? 0.0f: -y; - } - if (iy == 0x3f800000) /* y is +-1 */ - return hy >= 0 ? x : 1.0f/x; - if (hy == 0x40000000) /* y is 2 */ - return x*x; - if (hy == 0x3f000000) { /* y is 0.5 */ - if (hx >= 0) /* x >= +0 */ - return sqrtf(x); - } - - ax = fabsf(x); - /* special value of x */ - if (ix == 0x7f800000 || ix == 0 || ix == 0x3f800000) { /* x is +-0,+-inf,+-1 */ - z = ax; - if (hy < 0) /* z = (1/|x|) */ - z = 1.0f/z; - if (hx < 0) { - if (((ix-0x3f800000)|yisint) == 0) { - z = (z-z)/(z-z); /* (-1)**non-int is NaN */ - } else if (yisint == 1) - z = -z; /* (x<0)**odd = -(|x|**odd) */ - } - return z; - } - - sn = 1.0f; /* sign of result */ - if (hx < 0) { - if (yisint == 0) /* (x<0)**(non-int) is NaN */ - return (x-x)/(x-x); - if (yisint == 1) /* (x<0)**(odd int) */ - sn = -1.0f; - } - - /* |y| is huge */ - if (iy > 0x4d000000) { /* if |y| > 2**27 */ - /* over/underflow if x is not close to one */ - if (ix < 0x3f7ffff8) - return hy < 0 ? sn*huge*huge : sn*tiny*tiny; - if (ix > 0x3f800007) - return hy > 0 ? sn*huge*huge : sn*tiny*tiny; - /* now |1-x| is tiny <= 2**-20, suffice to compute - log(x) by x-x^2/2+x^3/3-x^4/4 */ - t = ax - 1; /* t has 20 trailing zeros */ - w = (t*t)*(0.5f - t*(0.333333333333f - t*0.25f)); - u = ivln2_h*t; /* ivln2_h has 16 sig. bits */ - v = t*ivln2_l - w*ivln2; - t1 = u + v; - GET_FLOAT_WORD(is, t1); - SET_FLOAT_WORD(t1, is & 0xfffff000); - t2 = v - (t1-u); - } else { - float s2,s_h,s_l,t_h,t_l; - n = 0; - /* take care subnormal number */ - if (ix < 0x00800000) { - ax *= two24; - n -= 24; - GET_FLOAT_WORD(ix, ax); - } - n += ((ix)>>23) - 0x7f; - j = ix & 0x007fffff; - /* determine interval */ - ix = j | 0x3f800000; /* normalize ix */ - if (j <= 0x1cc471) /* |x|>1) & 0xfffff000) | 0x20000000; - SET_FLOAT_WORD(t_h, is + 0x00400000 + (k<<21)); - t_l = ax - (t_h - bp[k]); - s_l = v*((u - s_h*t_h) - s_h*t_l); - /* compute log(ax) */ - s2 = s*s; - r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); - r += s_l*(s_h+s); - s2 = s_h*s_h; - t_h = 3.0f + s2 + r; - GET_FLOAT_WORD(is, t_h); - SET_FLOAT_WORD(t_h, is & 0xfffff000); - t_l = r - ((t_h - 3.0f) - s2); - /* u+v = s*(1+...) */ - u = s_h*t_h; - v = s_l*t_h + t_l*s; - /* 2/(3log2)*(s+...) */ - p_h = u + v; - GET_FLOAT_WORD(is, p_h); - SET_FLOAT_WORD(p_h, is & 0xfffff000); - p_l = v - (p_h - u); - z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ - z_l = cp_l*p_h + p_l*cp+dp_l[k]; - /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ - t = (float)n; - t1 = (((z_h + z_l) + dp_h[k]) + t); - GET_FLOAT_WORD(is, t1); - SET_FLOAT_WORD(t1, is & 0xfffff000); - t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); - } - - /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ - GET_FLOAT_WORD(is, y); - SET_FLOAT_WORD(y1, is & 0xfffff000); - p_l = (y-y1)*t1 + y*t2; - p_h = y1*t1; - z = p_l + p_h; - GET_FLOAT_WORD(j, z); - if (j > 0x43000000) /* if z > 128 */ - return sn*huge*huge; /* overflow */ - else if (j == 0x43000000) { /* if z == 128 */ - if (p_l + ovt > z - p_h) - return sn*huge*huge; /* overflow */ - } else if ((j&0x7fffffff) > 0x43160000) /* z < -150 */ // FIXME: check should be (uint32_t)j > 0xc3160000 - return sn*tiny*tiny; /* underflow */ - else if (j == 0xc3160000) { /* z == -150 */ - if (p_l <= z-p_h) - return sn*tiny*tiny; /* underflow */ - } - /* - * compute 2**(p_h+p_l) - */ - i = j & 0x7fffffff; - k = (i>>23) - 0x7f; - n = 0; - if (i > 0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */ - n = j + (0x00800000>>(k+1)); - k = ((n&0x7fffffff)>>23) - 0x7f; /* new k for n */ - SET_FLOAT_WORD(t, n & ~(0x007fffff>>k)); - n = ((n&0x007fffff)|0x00800000)>>(23-k); - if (j < 0) - n = -n; - p_h -= t; - } - t = p_l + p_h; - GET_FLOAT_WORD(is, t); - SET_FLOAT_WORD(t, is & 0xffff8000); - u = t*lg2_h; - v = (p_l-(t-p_h))*lg2 + t*lg2_l; - z = u + v; - w = v - (z - u); - t = z*z; - t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); - r = (z*t1)/(t1-2.0f) - (w+z*w); - z = 1.0f - (r - z); - GET_FLOAT_WORD(j, z); - j += n<<23; - if ((j>>23) <= 0) /* subnormal output */ - z = scalbnf(z, n); - else - SET_FLOAT_WORD(z, j); - return sn*z; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// expf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/e_expf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -static const float -half[2] = {0.5,-0.5}, -ln2hi = 6.9314575195e-1f, /* 0x3f317200 */ -ln2lo = 1.4286067653e-6f, /* 0x35bfbe8e */ -invln2 = 1.4426950216e+0f, /* 0x3fb8aa3b */ -/* - * Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]: - * |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74 - */ -expf_P1 = 1.6666625440e-1f, /* 0xaaaa8f.0p-26 */ -expf_P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */ - -float expf(float x) -{ - float_t hi, lo, c, xx, y; - int k, sign; - uint32_t hx; - - GET_FLOAT_WORD(hx, x); - sign = hx >> 31; /* sign bit of x */ - hx &= 0x7fffffff; /* high word of |x| */ - - /* special cases */ - if (hx >= 0x42aeac50) { /* if |x| >= -87.33655f or NaN */ - if (hx >= 0x42b17218 && !sign) { /* x >= 88.722839f */ - /* overflow */ - x *= 0x1p127f; - return x; - } - if (sign) { - /* underflow */ - FORCE_EVAL(-0x1p-149f/x); - if (hx >= 0x42cff1b5) /* x <= -103.972084f */ - return 0; - } - } - - /* argument reduction */ - if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ - if (hx > 0x3f851592) /* if |x| > 1.5 ln2 */ - k = invln2*x + half[sign]; - else - k = 1 - sign - sign; - hi = x - k*ln2hi; /* k*ln2hi is exact here */ - lo = k*ln2lo; - x = hi - lo; - } else if (hx > 0x39000000) { /* |x| > 2**-14 */ - k = 0; - hi = x; - lo = 0; - } else { - /* raise inexact */ - FORCE_EVAL(0x1p127f + x); - return 1 + x; - } - - /* x is now in primary range */ - xx = x*x; - c = x - xx*(expf_P1+xx*expf_P2); - y = 1 + (x*c/(2-c) - lo + hi); - if (k == 0) - return y; - return scalbnf(y, k); -} - -/*****************************************************************************/ -/*****************************************************************************/ -// expm1f from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/s_expm1f.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -static const float -o_threshold = 8.8721679688e+01, /* 0x42b17180 */ -ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ -ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ -//invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */ -/* - * Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]: - * |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04 - * Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c): - */ -Q1 = -3.3333212137e-2, /* -0x888868.0p-28 */ -Q2 = 1.5807170421e-3; /* 0xcf3010.0p-33 */ - -float expm1f(float x) -{ - float_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk; - union {float f; uint32_t i;} u = {x}; - uint32_t hx = u.i & 0x7fffffff; - int k, sign = u.i >> 31; - - /* filter out huge and non-finite argument */ - if (hx >= 0x4195b844) { /* if |x|>=27*ln2 */ - if (hx > 0x7f800000) /* NaN */ - return x; - if (sign) - return -1; - if (x > o_threshold) { - x *= 0x1p127f; - return x; - } - } - - /* argument reduction */ - if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ - if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ - if (!sign) { - hi = x - ln2_hi; - lo = ln2_lo; - k = 1; - } else { - hi = x + ln2_hi; - lo = -ln2_lo; - k = -1; - } - } else { - k = invln2*x + (sign ? -0.5f : 0.5f); - t = k; - hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ - lo = t*ln2_lo; - } - x = hi-lo; - c = (hi-x)-lo; - } else if (hx < 0x33000000) { /* when |x|<2**-25, return x */ - if (hx < 0x00800000) - FORCE_EVAL(x*x); - return x; - } else - k = 0; - - /* x is now in primary range */ - hfx = 0.5f*x; - hxs = x*hfx; - r1 = 1.0f+hxs*(Q1+hxs*Q2); - t = 3.0f - r1*hfx; - e = hxs*((r1-t)/(6.0f - x*t)); - if (k == 0) /* c is 0 */ - return x - (x*e-hxs); - e = x*(e-c) - c; - e -= hxs; - /* exp(x) ~ 2^k (x_reduced - e + 1) */ - if (k == -1) - return 0.5f*(x-e) - 0.5f; - if (k == 1) { - if (x < -0.25f) - return -2.0f*(e-(x+0.5f)); - return 1.0f + 2.0f*(x-e); - } - u.i = (0x7f+k)<<23; /* 2^k */ - twopk = u.f; - if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */ - y = x - e + 1.0f; - if (k == 128) - y = y*2.0f*0x1p127f; - else - y = y*twopk; - return y - 1.0f; - } - u.i = (0x7f-k)<<23; /* 2^-k */ - if (k < 23) - y = (x-e+(1-u.f))*twopk; - else - y = (x-(e+u.f)+1)*twopk; - return y; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// __expo2f from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */ -static const int k = 235; -static const float kln2 = 0x1.45c778p+7f; - -/* expf(x)/2 for x >= log(FLT_MAX), slightly better than 0.5f*expf(x/2)*expf(x/2) */ -float __expo2f(float x) -{ - float scale; - - /* note that k is odd and scale*scale overflows */ - SET_FLOAT_WORD(scale, (uint32_t)(0x7f + k/2) << 23); - /* exp(x - k ln2) * 2**(k-1) */ - return expf(x - kln2) * scale * scale; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// logf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -/* origin: FreeBSD /usr/src/lib/msun/src/e_logf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -static const float -/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ -Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ -Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ -Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ -Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ - -float logf(float x) -{ - union {float f; uint32_t i;} u = {x}; - float_t hfsq,f,s,z,R,w,t1,t2,dk; - uint32_t ix; - int k; - - ix = u.i; - k = 0; - if (ix < 0x00800000 || ix>>31) { /* x < 2**-126 */ - if (ix<<1 == 0) - return -1/(x*x); /* log(+-0)=-inf */ - if (ix>>31) - return (x-x)/0.0f; /* log(-#) = NaN */ - /* subnormal number, scale up x */ - k -= 25; - x *= 0x1p25f; - u.f = x; - ix = u.i; - } else if (ix >= 0x7f800000) { - return x; - } else if (ix == 0x3f800000) - return 0; - - /* reduce x into [sqrt(2)/2, sqrt(2)] */ - ix += 0x3f800000 - 0x3f3504f3; - k += (int)(ix>>23) - 0x7f; - ix = (ix&0x007fffff) + 0x3f3504f3; - u.i = ix; - x = u.f; - - f = x - 1.0f; - s = f/(2.0f + f); - z = s*s; - w = z*z; - t1= w*(Lg2+w*Lg4); - t2= z*(Lg1+w*Lg3); - R = t2 + t1; - hfsq = 0.5f*f*f; - dk = k; - return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// coshf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -float coshf(float x) -{ - union {float f; uint32_t i;} u = {.f = x}; - uint32_t w; - float t; - - /* |x| */ - u.i &= 0x7fffffff; - x = u.f; - w = u.i; - - /* |x| < log(2) */ - if (w < 0x3f317217) { - if (w < 0x3f800000 - (12<<23)) { - FORCE_EVAL(x + 0x1p120f); - return 1; - } - t = expm1f(x); - return 1 + t*t/(2*(1+t)); - } - - /* |x| < log(FLT_MAX) */ - if (w < 0x42b17217) { - t = expf(x); - return 0.5f*(t + 1/t); - } - - /* |x| > log(FLT_MAX) or nan */ - t = __expo2f(x); - return t; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// sinhf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -float sinhf(float x) -{ - union {float f; uint32_t i;} u = {.f = x}; - uint32_t w; - float t, h, absx; - - h = 0.5; - if (u.i >> 31) - h = -h; - /* |x| */ - u.i &= 0x7fffffff; - absx = u.f; - w = u.i; - - /* |x| < log(FLT_MAX) */ - if (w < 0x42b17217) { - t = expm1f(absx); - if (w < 0x3f800000) { - if (w < 0x3f800000 - (12<<23)) - return x; - return h*(2*t - t*t/(t+1)); - } - return h*(t + t/(t+1)); - } - - /* |x| > logf(FLT_MAX) or nan */ - t = 2*h*__expo2f(absx); - return t; -} - -/*****************************************************************************/ -/*****************************************************************************/ -// ceilf, floorf and truncf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -float ceilf(float x) -{ - union {float f; uint32_t i;} u = {x}; - int e = (int)(u.i >> 23 & 0xff) - 0x7f; - uint32_t m; - - if (e >= 23) - return x; - if (e >= 0) { - m = 0x007fffff >> e; - if ((u.i & m) == 0) - return x; - FORCE_EVAL(x + 0x1p120f); - if (u.i >> 31 == 0) - u.i += m; - u.i &= ~m; - } else { - FORCE_EVAL(x + 0x1p120f); - if (u.i >> 31) - u.f = -0.0; - else if (u.i << 1) - u.f = 1.0; - } - return u.f; -} - -float floorf(float x) -{ - union {float f; uint32_t i;} u = {x}; - int e = (int)(u.i >> 23 & 0xff) - 0x7f; - uint32_t m; - - if (e >= 23) - return x; - if (e >= 0) { - m = 0x007fffff >> e; - if ((u.i & m) == 0) - return x; - FORCE_EVAL(x + 0x1p120f); - if (u.i >> 31) - u.i += m; - u.i &= ~m; - } else { - FORCE_EVAL(x + 0x1p120f); - if (u.i >> 31 == 0) - u.i = 0; - else if (u.i << 1) - u.f = -1.0; - } - return u.f; -} - -float truncf(float x) -{ - union {float f; uint32_t i;} u = {x}; - int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9; - uint32_t m; - - if (e >= 23 + 9) - return x; - if (e < 9) - e = 1; - m = -1U >> e; - if ((u.i & m) == 0) - return x; - FORCE_EVAL(x + 0x1p120f); - u.i &= ~m; - return u.f; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/nearbyintf.c b/MicroPython_BUILD/components/micropython/lib/libm/nearbyintf.c deleted file mode 100644 index 1c354594..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/nearbyintf.c +++ /dev/null @@ -1,21 +0,0 @@ -// adapted from the rintf() function from musl-1.1.16 - -#include "libm.h" - -float nearbyintf(float x) -{ - union {float f; uint32_t i;} u = {x}; - int e = u.i>>23 & 0xff; - int s = u.i>>31; - float_t y; - - if (e >= 0x7f+23) - return x; - if (s) - y = x - 0x1p23f + 0x1p23f; - else - y = x + 0x1p23f - 0x1p23f; - if (y == 0) - return s ? -0.0f : 0.0f; - return y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/roundf.c b/MicroPython_BUILD/components/micropython/lib/libm/roundf.c deleted file mode 100644 index 3da1f059..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/roundf.c +++ /dev/null @@ -1,33 +0,0 @@ -/*****************************************************************************/ -/*****************************************************************************/ -// roundf from musl-0.9.15 -/*****************************************************************************/ -/*****************************************************************************/ - -#include "libm.h" - -float roundf(float x) -{ - union {float f; uint32_t i;} u = {x}; - int e = u.i >> 23 & 0xff; - float_t y; - - if (e >= 0x7f+23) - return x; - if (u.i >> 31) - x = -x; - if (e < 0x7f-1) { - FORCE_EVAL(x + 0x1p23f); - return 0*u.f; - } - y = (float)(x + 0x1p23f) - 0x1p23f - x; - if (y > 0.5f) - y = y + x - 1; - else if (y <= -0.5f) - y = y + x + 1; - else - y = y + x; - if (u.i >> 31) - y = -y; - return y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/sf_cos.c b/MicroPython_BUILD/components/micropython/lib/libm/sf_cos.c deleted file mode 100644 index fabb129c..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/sf_cos.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* sf_cos.c -- float version of s_cos.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - float cosf(float x) -#else - float cosf(x) - float x; -#endif -{ - float y[2],z=0.0; - __int32_t n,ix; - - GET_FLOAT_WORD(ix,x); - - /* |x| ~< pi/4 */ - ix &= 0x7fffffff; - if(ix <= 0x3f490fd8) return __kernel_cosf(x,z); - - /* cos(Inf or NaN) is NaN */ - else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2f(x,y); - switch(n&3) { - case 0: return __kernel_cosf(y[0],y[1]); - case 1: return -__kernel_sinf(y[0],y[1],1); - case 2: return -__kernel_cosf(y[0],y[1]); - default: - return __kernel_sinf(y[0],y[1],1); - } - } -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double cos(double x) -#else - double cos(x) - double x; -#endif -{ - return (double) cosf((float) x); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/sf_erf.c b/MicroPython_BUILD/components/micropython/lib/libm/sf_erf.c deleted file mode 100644 index 3f0172c6..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/sf_erf.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* sf_erf.c -- float version of s_erf.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#define __ieee754_expf expf - -#ifdef __v810__ -#define const -#endif - -#ifdef __STDC__ -static const float -#else -static float -#endif -tiny = 1e-30, -half= 5.0000000000e-01, /* 0x3F000000 */ -one = 1.0000000000e+00, /* 0x3F800000 */ -two = 2.0000000000e+00, /* 0x40000000 */ - /* c = (subfloat)0.84506291151 */ -erx = 8.4506291151e-01, /* 0x3f58560b */ -/* - * Coefficients for approximation to erf on [0,0.84375] - */ -efx = 1.2837916613e-01, /* 0x3e0375d4 */ -efx8= 1.0270333290e+00, /* 0x3f8375d4 */ -pp0 = 1.2837916613e-01, /* 0x3e0375d4 */ -pp1 = -3.2504209876e-01, /* 0xbea66beb */ -pp2 = -2.8481749818e-02, /* 0xbce9528f */ -pp3 = -5.7702702470e-03, /* 0xbbbd1489 */ -pp4 = -2.3763017452e-05, /* 0xb7c756b1 */ -qq1 = 3.9791721106e-01, /* 0x3ecbbbce */ -qq2 = 6.5022252500e-02, /* 0x3d852a63 */ -qq3 = 5.0813062117e-03, /* 0x3ba68116 */ -qq4 = 1.3249473704e-04, /* 0x390aee49 */ -qq5 = -3.9602282413e-06, /* 0xb684e21a */ -/* - * Coefficients for approximation to erf in [0.84375,1.25] - */ -pa0 = -2.3621185683e-03, /* 0xbb1acdc6 */ -pa1 = 4.1485610604e-01, /* 0x3ed46805 */ -pa2 = -3.7220788002e-01, /* 0xbebe9208 */ -pa3 = 3.1834661961e-01, /* 0x3ea2fe54 */ -pa4 = -1.1089469492e-01, /* 0xbde31cc2 */ -pa5 = 3.5478305072e-02, /* 0x3d1151b3 */ -pa6 = -2.1663755178e-03, /* 0xbb0df9c0 */ -qa1 = 1.0642088205e-01, /* 0x3dd9f331 */ -qa2 = 5.4039794207e-01, /* 0x3f0a5785 */ -qa3 = 7.1828655899e-02, /* 0x3d931ae7 */ -qa4 = 1.2617121637e-01, /* 0x3e013307 */ -qa5 = 1.3637083583e-02, /* 0x3c5f6e13 */ -qa6 = 1.1984500103e-02, /* 0x3c445aa3 */ -/* - * Coefficients for approximation to erfc in [1.25,1/0.35] - */ -ra0 = -9.8649440333e-03, /* 0xbc21a093 */ -ra1 = -6.9385856390e-01, /* 0xbf31a0b7 */ -ra2 = -1.0558626175e+01, /* 0xc128f022 */ -ra3 = -6.2375331879e+01, /* 0xc2798057 */ -ra4 = -1.6239666748e+02, /* 0xc322658c */ -ra5 = -1.8460508728e+02, /* 0xc3389ae7 */ -ra6 = -8.1287437439e+01, /* 0xc2a2932b */ -ra7 = -9.8143291473e+00, /* 0xc11d077e */ -sa1 = 1.9651271820e+01, /* 0x419d35ce */ -sa2 = 1.3765776062e+02, /* 0x4309a863 */ -sa3 = 4.3456588745e+02, /* 0x43d9486f */ -sa4 = 6.4538726807e+02, /* 0x442158c9 */ -sa5 = 4.2900814819e+02, /* 0x43d6810b */ -sa6 = 1.0863500214e+02, /* 0x42d9451f */ -sa7 = 6.5702495575e+00, /* 0x40d23f7c */ -sa8 = -6.0424413532e-02, /* 0xbd777f97 */ -/* - * Coefficients for approximation to erfc in [1/.35,28] - */ -rb0 = -9.8649431020e-03, /* 0xbc21a092 */ -rb1 = -7.9928326607e-01, /* 0xbf4c9dd4 */ -rb2 = -1.7757955551e+01, /* 0xc18e104b */ -rb3 = -1.6063638306e+02, /* 0xc320a2ea */ -rb4 = -6.3756646729e+02, /* 0xc41f6441 */ -rb5 = -1.0250950928e+03, /* 0xc480230b */ -rb6 = -4.8351919556e+02, /* 0xc3f1c275 */ -sb1 = 3.0338060379e+01, /* 0x41f2b459 */ -sb2 = 3.2579251099e+02, /* 0x43a2e571 */ -sb3 = 1.5367296143e+03, /* 0x44c01759 */ -sb4 = 3.1998581543e+03, /* 0x4547fdbb */ -sb5 = 2.5530502930e+03, /* 0x451f90ce */ -sb6 = 4.7452853394e+02, /* 0x43ed43a7 */ -sb7 = -2.2440952301e+01; /* 0xc1b38712 */ - -#ifdef __STDC__ - float erff(float x) -#else - float erff(x) - float x; -#endif -{ - __int32_t hx,ix,i; - float R,S,P,Q,s,y,z,r; - GET_FLOAT_WORD(hx,x); - ix = hx&0x7fffffff; - if(!FLT_UWORD_IS_FINITE(ix)) { /* erf(nan)=nan */ - i = ((__uint32_t)hx>>31)<<1; - return (float)(1-i)+one/x; /* erf(+-inf)=+-1 */ - } - - if(ix < 0x3f580000) { /* |x|<0.84375 */ - if(ix < 0x31800000) { /* |x|<2**-28 */ - if (ix < 0x04000000) - /*avoid underflow */ - return (float)0.125*((float)8.0*x+efx8*x); - return x + efx*x; - } - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - return x + x*y; - } - if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ - s = fabsf(x)-one; - P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); - Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); - if(hx>=0) return erx + P/Q; else return -erx - P/Q; - } - if (ix >= 0x40c00000) { /* inf>|x|>=6 */ - if(hx>=0) return one-tiny; else return tiny-one; - } - x = fabsf(x); - s = one/(x*x); - if(ix< 0x4036DB6E) { /* |x| < 1/0.35 */ - R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( - ra5+s*(ra6+s*ra7)))))); - S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( - sa5+s*(sa6+s*(sa7+s*sa8))))))); - } else { /* |x| >= 1/0.35 */ - R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( - rb5+s*rb6))))); - S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( - sb5+s*(sb6+s*sb7)))))); - } - GET_FLOAT_WORD(ix,x); - SET_FLOAT_WORD(z,ix&0xfffff000); - r = __ieee754_expf(-z*z-(float)0.5625)*__ieee754_expf((z-x)*(z+x)+R/S); - if(hx>=0) return one-r/x; else return r/x-one; -} - -#ifdef __STDC__ - float erfcf(float x) -#else - float erfcf(x) - float x; -#endif -{ - __int32_t hx,ix; - float R,S,P,Q,s,y,z,r; - GET_FLOAT_WORD(hx,x); - ix = hx&0x7fffffff; - if(!FLT_UWORD_IS_FINITE(ix)) { /* erfc(nan)=nan */ - /* erfc(+-inf)=0,2 */ - return (float)(((__uint32_t)hx>>31)<<1)+one/x; - } - - if(ix < 0x3f580000) { /* |x|<0.84375 */ - if(ix < 0x23800000) /* |x|<2**-56 */ - return one-x; - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - if(hx < 0x3e800000) { /* x<1/4 */ - return one-(x+x*y); - } else { - r = x*y; - r += (x-half); - return half - r ; - } - } - if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ - s = fabsf(x)-one; - P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); - Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); - if(hx>=0) { - z = one-erx; return z - P/Q; - } else { - z = erx+P/Q; return one+z; - } - } - if (ix < 0x41e00000) { /* |x|<28 */ - x = fabsf(x); - s = one/(x*x); - if(ix< 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/ - R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( - ra5+s*(ra6+s*ra7)))))); - S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( - sa5+s*(sa6+s*(sa7+s*sa8))))))); - } else { /* |x| >= 1/.35 ~ 2.857143 */ - if(hx<0&&ix>=0x40c00000) return two-tiny;/* x < -6 */ - R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( - rb5+s*rb6))))); - S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( - sb5+s*(sb6+s*sb7)))))); - } - GET_FLOAT_WORD(ix,x); - SET_FLOAT_WORD(z,ix&0xfffff000); - r = __ieee754_expf(-z*z-(float)0.5625)* - __ieee754_expf((z-x)*(z+x)+R/S); - if(hx>0) return r/x; else return two-r/x; - } else { - if(hx>0) return tiny*tiny; else return two-tiny; - } -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double erf(double x) -#else - double erf(x) - double x; -#endif -{ - return (double) erff((float) x); -} - -#ifdef __STDC__ - double erfc(double x) -#else - double erfc(x) - double x; -#endif -{ - return (double) erfcf((float) x); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/sf_frexp.c b/MicroPython_BUILD/components/micropython/lib/libm/sf_frexp.c deleted file mode 100644 index df50fb77..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/sf_frexp.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* sf_frexp.c -- float version of s_frexp.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const float -#else -static float -#endif -two25 = 3.3554432000e+07; /* 0x4c000000 */ - -#ifdef __STDC__ - float frexpf(float x, int *eptr) -#else - float frexpf(x, eptr) - float x; int *eptr; -#endif -{ - __int32_t hx, ix; - GET_FLOAT_WORD(hx,x); - ix = 0x7fffffff&hx; - *eptr = 0; - if(!FLT_UWORD_IS_FINITE(ix)||FLT_UWORD_IS_ZERO(ix)) return x; /* 0,inf,nan */ - if (FLT_UWORD_IS_SUBNORMAL(ix)) { /* subnormal */ - x *= two25; - GET_FLOAT_WORD(hx,x); - ix = hx&0x7fffffff; - *eptr = -25; - } - *eptr += (ix>>23)-126; - hx = (hx&0x807fffff)|0x3f000000; - SET_FLOAT_WORD(x,hx); - return x; -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double frexp(double x, int *eptr) -#else - double frexp(x, eptr) - double x; int *eptr; -#endif -{ - return (double) frexpf((float) x, eptr); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/sf_ldexp.c b/MicroPython_BUILD/components/micropython/lib/libm/sf_ldexp.c deleted file mode 100644 index 37968d47..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/sf_ldexp.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* sf_ldexp.c -- float version of s_ldexp.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" -//#include - -#ifdef __STDC__ - float ldexpf(float value, int exp) -#else - float ldexpf(value, exp) - float value; int exp; -#endif -{ - if(!isfinite(value)||value==(float)0.0) return value; - value = scalbnf(value,exp); - //if(!finitef(value)||value==(float)0.0) errno = ERANGE; - return value; -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double ldexp(double value, int exp) -#else - double ldexp(value, exp) - double value; int exp; -#endif -{ - return (double) ldexpf((float) value, exp); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/sf_modf.c b/MicroPython_BUILD/components/micropython/lib/libm/sf_modf.c deleted file mode 100644 index 410db2a3..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/sf_modf.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/common - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* sf_modf.c -- float version of s_modf.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ -static const float one = 1.0; -#else -static float one = 1.0; -#endif - -#ifdef __STDC__ - float modff(float x, float *iptr) -#else - float modff(x, iptr) - float x,*iptr; -#endif -{ - __int32_t i0,j0; - __uint32_t i; - GET_FLOAT_WORD(i0,x); - j0 = ((i0>>23)&0xff)-0x7f; /* exponent of x */ - if(j0<23) { /* integer part in x */ - if(j0<0) { /* |x|<1 */ - SET_FLOAT_WORD(*iptr,i0&0x80000000); /* *iptr = +-0 */ - return x; - } else { - i = (0x007fffff)>>j0; - if((i0&i)==0) { /* x is integral */ - __uint32_t ix; - *iptr = x; - GET_FLOAT_WORD(ix,x); - SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */ - return x; - } else { - SET_FLOAT_WORD(*iptr,i0&(~i)); - return x - *iptr; - } - } - } else { /* no fraction part */ - __uint32_t ix; - *iptr = x*one; - GET_FLOAT_WORD(ix,x); - SET_FLOAT_WORD(x,ix&0x80000000); /* return +-0 */ - return x; - } -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double modf(double x, double *iptr) -#else - double modf(x, iptr) - double x,*iptr; -#endif -{ - return (double) modff((float) x, (float *) iptr); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/sf_sin.c b/MicroPython_BUILD/components/micropython/lib/libm/sf_sin.c deleted file mode 100644 index d2705077..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/sf_sin.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* sf_sin.c -- float version of s_sin.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - float sinf(float x) -#else - float sinf(x) - float x; -#endif -{ - float y[2],z=0.0; - __int32_t n,ix; - - GET_FLOAT_WORD(ix,x); - - /* |x| ~< pi/4 */ - ix &= 0x7fffffff; - if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0); - - /* sin(Inf or NaN) is NaN */ - else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2f(x,y); - switch(n&3) { - case 0: return __kernel_sinf(y[0],y[1],1); - case 1: return __kernel_cosf(y[0],y[1]); - case 2: return -__kernel_sinf(y[0],y[1],1); - default: - return -__kernel_cosf(y[0],y[1]); - } - } -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double sin(double x) -#else - double sin(x) - double x; -#endif -{ - return (double) sinf((float) x); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/sf_tan.c b/MicroPython_BUILD/components/micropython/lib/libm/sf_tan.c deleted file mode 100644 index 148b16d6..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/sf_tan.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* sf_tan.c -- float version of s_tan.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "fdlibm.h" - -#ifdef __STDC__ - float tanf(float x) -#else - float tanf(x) - float x; -#endif -{ - float y[2],z=0.0; - __int32_t n,ix; - - GET_FLOAT_WORD(ix,x); - - /* |x| ~< pi/4 */ - ix &= 0x7fffffff; - if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1); - - /* tan(Inf or NaN) is NaN */ - else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; /* NaN */ - - /* argument reduction needed */ - else { - n = __ieee754_rem_pio2f(x,y); - return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even - -1 -- n odd */ - } -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double tan(double x) -#else - double tan(x) - double x; -#endif -{ - return (double) tanf((float) x); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/thumb_vfp_sqrtf.c b/MicroPython_BUILD/components/micropython/lib/libm/thumb_vfp_sqrtf.c deleted file mode 100644 index 12ffebf8..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/thumb_vfp_sqrtf.c +++ /dev/null @@ -1,11 +0,0 @@ -// an implementation of sqrtf for Thumb using hardware VFP instructions - -#include - -float sqrtf(float x) { - asm volatile ( - "vsqrt.f32 %[r], %[x]\n" - : [r] "=t" (x) - : [x] "t" (x)); - return x; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm/wf_lgamma.c b/MicroPython_BUILD/components/micropython/lib/libm/wf_lgamma.c deleted file mode 100644 index d86ede79..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/wf_lgamma.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* wf_lgamma.c -- float version of w_lgamma.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ - -#include "fdlibm.h" -#define _IEEE_LIBM 1 -//#include -//#include - -#ifdef __STDC__ - float lgammaf(float x) -#else - float lgammaf(x) - float x; -#endif -{ -#ifdef _IEEE_LIBM - int sign; - return __ieee754_lgammaf_r(x,&sign); -#else - float y; - struct exception exc; - y = __ieee754_lgammaf_r(x,&(_REENT_SIGNGAM(_REENT))); - if(_LIB_VERSION == _IEEE_) return y; - if(!finitef(y)&&finitef(x)) { -#ifndef HUGE_VAL -#define HUGE_VAL inf - double inf = 0.0; - - SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ -#endif - exc.name = "lgammaf"; - exc.err = 0; - exc.arg1 = exc.arg2 = (double)x; - if (_LIB_VERSION == _SVID_) - exc.retval = HUGE; - else - exc.retval = HUGE_VAL; - if(floorf(x)==x&&x<=(float)0.0) { - /* lgammaf(-integer) */ - exc.type = SING; - if (_LIB_VERSION == _POSIX_) - errno = EDOM; - else if (!matherr(&exc)) { - errno = EDOM; - } - - } else { - /* lgammaf(finite) overflow */ - exc.type = OVERFLOW; - if (_LIB_VERSION == _POSIX_) - errno = ERANGE; - else if (!matherr(&exc)) { - errno = ERANGE; - } - } - if (exc.err != 0) - errno = exc.err; - return (float)exc.retval; - } else - return y; -#endif -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double lgamma(double x) -#else - double lgamma(x) - double x; -#endif -{ - return (double) lgammaf((float) x); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm/wf_tgamma.c b/MicroPython_BUILD/components/micropython/lib/libm/wf_tgamma.c deleted file mode 100644 index 64b2488d..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm/wf_tgamma.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * These math functions are taken from newlib-nano-2, the newlib/libm/math - * directory, available from https://github.com/32bitmicro/newlib-nano-2. - * - * Appropriate copyright headers are reproduced below. - */ - -/* w_gammaf.c -- float version of w_gamma.c. - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ - -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include "math.h" -#include "fdlibm.h" -#define _IEEE_LIBM 1 - -#ifdef __STDC__ - float tgammaf(float x) -#else - float tgammaf(x) - float x; -#endif -{ - float y; - int local_signgam; - y = expf(__ieee754_lgammaf_r(x,&local_signgam)); - if (local_signgam < 0) y = -y; -#ifdef _IEEE_LIBM - return y; -#else - if(_LIB_VERSION == _IEEE_) return y; - - if(!finitef(y)&&finitef(x)) { - if(floorf(x)==x&&x<=(float)0.0) - /* tgammaf pole */ - return (float)__kernel_standard((double)x,(double)x,141); - else - /* tgammaf overflow */ - return (float)__kernel_standard((double)x,(double)x,140); - } - return y; -#endif -} - -#ifdef _DOUBLE_IS_32BITS - -#ifdef __STDC__ - double tgamma(double x) -#else - double tgamma(x) - double x; -#endif -{ - return (double) tgammaf((float) x); -} - -#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/README b/MicroPython_BUILD/components/micropython/lib/libm_dbl/README deleted file mode 100644 index 512b3282..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/README +++ /dev/null @@ -1,32 +0,0 @@ -This directory contains source code for the standard double-precision math -functions. - -The files lgamma.c, log10.c and tanh.c are too small to have a meaningful -copyright or license. - -The rest of the files in this directory are copied from the musl library, -v1.1.16, and, unless otherwise stated in the individual file, have the -following copyright and MIT license: - ----------------------------------------------------------------------- -Copyright © 2005-2014 Rich Felker, et al. - -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/MicroPython_BUILD/components/micropython/lib/libm_dbl/__cos.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__cos.c deleted file mode 100644 index 46cefb38..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__cos.c +++ /dev/null @@ -1,71 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * __cos( x, y ) - * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * - * Algorithm - * 1. Since cos(-x) = cos(x), we need only to consider positive x. - * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. - * 3. cos(x) is approximated by a polynomial of degree 14 on - * [0,pi/4] - * 4 14 - * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x - * where the remez error is - * - * | 2 4 6 8 10 12 14 | -58 - * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 - * | | - * - * 4 6 8 10 12 14 - * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then - * cos(x) ~ 1 - x*x/2 + r - * since cos(x+y) ~ cos(x) - sin(x)*y - * ~ cos(x) - x*y, - * a correction term is necessary in cos(x) and hence - * cos(x+y) = 1 - (x*x/2 - (r - x*y)) - * For better accuracy, rearrange to - * cos(x+y) ~ w + (tmp + (r-x*y)) - * where w = 1 - x*x/2 and tmp is a tiny correction term - * (1 - x*x/2 == w + tmp exactly in infinite precision). - * The exactness of w + tmp in infinite precision depends on w - * and tmp having the same precision as x. If they have extra - * precision due to compiler bugs, then the extra precision is - * only good provided it is retained in all terms of the final - * expression for cos(). Retention happens in all cases tested - * under FreeBSD, so don't pessimize things by forcibly clipping - * any extra precision in w. - */ - -#include "libm.h" - -static const double -C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ -C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ -C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ -C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ -C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ -C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ - -double __cos(double x, double y) -{ - double_t hz,z,r,w; - - z = x*x; - w = z*z; - r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); - hz = 0.5*z; - w = 1.0-hz; - return w + (((1.0-w)-hz) + (z*r-x*y)); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__expo2.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__expo2.c deleted file mode 100644 index 740ac680..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__expo2.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "libm.h" - -/* k is such that k*ln2 has minimal relative error and x - kln2 > log(DBL_MIN) */ -static const int k = 2043; -static const double kln2 = 0x1.62066151add8bp+10; - -/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */ -double __expo2(double x) -{ - double scale; - - /* note that k is odd and scale*scale overflows */ - INSERT_WORDS(scale, (uint32_t)(0x3ff + k/2) << 20, 0); - /* exp(x - k ln2) * 2**(k-1) */ - return exp(x - kln2) * scale * scale; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__fpclassify.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__fpclassify.c deleted file mode 100644 index 5c908ba3..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__fpclassify.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -int __fpclassifyd(double x) -{ - union {double f; uint64_t i;} u = {x}; - int e = u.i>>52 & 0x7ff; - if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; - if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE; - return FP_NORMAL; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__rem_pio2.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__rem_pio2.c deleted file mode 100644 index d403f81c..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__rem_pio2.c +++ /dev/null @@ -1,177 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - * Optimized by Bruce D. Evans. - */ -/* __rem_pio2(x,y) - * - * return the remainder of x rem pi/2 in y[0]+y[1] - * use __rem_pio2_large() for large x - */ - -#include "libm.h" - -#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 -#define EPS DBL_EPSILON -#elif FLT_EVAL_METHOD==2 -#define EPS LDBL_EPSILON -#endif - -/* - * invpio2: 53 bits of 2/pi - * pio2_1: first 33 bit of pi/2 - * pio2_1t: pi/2 - pio2_1 - * pio2_2: second 33 bit of pi/2 - * pio2_2t: pi/2 - (pio2_1+pio2_2) - * pio2_3: third 33 bit of pi/2 - * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) - */ -static const double -toint = 1.5/EPS, -invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ -pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ -pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ -pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ -pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ -pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ -pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ - -/* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ -int __rem_pio2(double x, double *y) -{ - union {double f; uint64_t i;} u = {x}; - double_t z,w,t,r,fn; - double tx[3],ty[2]; - uint32_t ix; - int sign, n, ex, ey, i; - - sign = u.i>>63; - ix = u.i>>32 & 0x7fffffff; - if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ - if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ - goto medium; /* cancellation -- use medium case */ - if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ - if (!sign) { - z = x - pio2_1; /* one round good to 85 bits */ - y[0] = z - pio2_1t; - y[1] = (z-y[0]) - pio2_1t; - return 1; - } else { - z = x + pio2_1; - y[0] = z + pio2_1t; - y[1] = (z-y[0]) + pio2_1t; - return -1; - } - } else { - if (!sign) { - z = x - 2*pio2_1; - y[0] = z - 2*pio2_1t; - y[1] = (z-y[0]) - 2*pio2_1t; - return 2; - } else { - z = x + 2*pio2_1; - y[0] = z + 2*pio2_1t; - y[1] = (z-y[0]) + 2*pio2_1t; - return -2; - } - } - } - if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ - if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ - if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ - goto medium; - if (!sign) { - z = x - 3*pio2_1; - y[0] = z - 3*pio2_1t; - y[1] = (z-y[0]) - 3*pio2_1t; - return 3; - } else { - z = x + 3*pio2_1; - y[0] = z + 3*pio2_1t; - y[1] = (z-y[0]) + 3*pio2_1t; - return -3; - } - } else { - if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ - goto medium; - if (!sign) { - z = x - 4*pio2_1; - y[0] = z - 4*pio2_1t; - y[1] = (z-y[0]) - 4*pio2_1t; - return 4; - } else { - z = x + 4*pio2_1; - y[0] = z + 4*pio2_1t; - y[1] = (z-y[0]) + 4*pio2_1t; - return -4; - } - } - } - if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ -medium: - /* rint(x/(pi/2)), Assume round-to-nearest. */ - fn = (double_t)x*invpio2 + toint - toint; - n = (int32_t)fn; - r = x - fn*pio2_1; - w = fn*pio2_1t; /* 1st round, good to 85 bits */ - y[0] = r - w; - u.f = y[0]; - ey = u.i>>52 & 0x7ff; - ex = ix>>20; - if (ex - ey > 16) { /* 2nd round, good to 118 bits */ - t = r; - w = fn*pio2_2; - r = t - w; - w = fn*pio2_2t - ((t-r)-w); - y[0] = r - w; - u.f = y[0]; - ey = u.i>>52 & 0x7ff; - if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ - t = r; - w = fn*pio2_3; - r = t - w; - w = fn*pio2_3t - ((t-r)-w); - y[0] = r - w; - } - } - y[1] = (r - y[0]) - w; - return n; - } - /* - * all other (large) arguments - */ - if (ix >= 0x7ff00000) { /* x is inf or NaN */ - y[0] = y[1] = x - x; - return 0; - } - /* set z = scalbn(|x|,-ilogb(x)+23) */ - u.f = x; - u.i &= (uint64_t)-1>>12; - u.i |= (uint64_t)(0x3ff + 23)<<52; - z = u.f; - for (i=0; i < 2; i++) { - tx[i] = (double)(int32_t)z; - z = (z-tx[i])*0x1p24; - } - tx[i] = z; - /* skip zero terms, first term is non-zero */ - while (tx[i] == 0.0) - i--; - n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); - if (sign) { - y[0] = -ty[0]; - y[1] = -ty[1]; - return -n; - } - y[0] = ty[0]; - y[1] = ty[1]; - return n; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__rem_pio2_large.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__rem_pio2_large.c deleted file mode 100644 index 958f28c2..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__rem_pio2_large.c +++ /dev/null @@ -1,442 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * __rem_pio2_large(x,y,e0,nx,prec) - * double x[],y[]; int e0,nx,prec; - * - * __rem_pio2_large return the last three digits of N with - * y = x - N*pi/2 - * so that |y| < pi/2. - * - * The method is to compute the integer (mod 8) and fraction parts of - * (2/pi)*x without doing the full multiplication. In general we - * skip the part of the product that are known to be a huge integer ( - * more accurately, = 0 mod 8 ). Thus the number of operations are - * independent of the exponent of the input. - * - * (2/pi) is represented by an array of 24-bit integers in ipio2[]. - * - * Input parameters: - * x[] The input value (must be positive) is broken into nx - * pieces of 24-bit integers in double precision format. - * x[i] will be the i-th 24 bit of x. The scaled exponent - * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 - * match x's up to 24 bits. - * - * Example of breaking a double positive z into x[0]+x[1]+x[2]: - * e0 = ilogb(z)-23 - * z = scalbn(z,-e0) - * for i = 0,1,2 - * x[i] = floor(z) - * z = (z-x[i])*2**24 - * - * - * y[] ouput result in an array of double precision numbers. - * The dimension of y[] is: - * 24-bit precision 1 - * 53-bit precision 2 - * 64-bit precision 2 - * 113-bit precision 3 - * The actual value is the sum of them. Thus for 113-bit - * precison, one may have to do something like: - * - * long double t,w,r_head, r_tail; - * t = (long double)y[2] + (long double)y[1]; - * w = (long double)y[0]; - * r_head = t+w; - * r_tail = w - (r_head - t); - * - * e0 The exponent of x[0]. Must be <= 16360 or you need to - * expand the ipio2 table. - * - * nx dimension of x[] - * - * prec an integer indicating the precision: - * 0 24 bits (single) - * 1 53 bits (double) - * 2 64 bits (extended) - * 3 113 bits (quad) - * - * External function: - * double scalbn(), floor(); - * - * - * Here is the description of some local variables: - * - * jk jk+1 is the initial number of terms of ipio2[] needed - * in the computation. The minimum and recommended value - * for jk is 3,4,4,6 for single, double, extended, and quad. - * jk+1 must be 2 larger than you might expect so that our - * recomputation test works. (Up to 24 bits in the integer - * part (the 24 bits of it that we compute) and 23 bits in - * the fraction part may be lost to cancelation before we - * recompute.) - * - * jz local integer variable indicating the number of - * terms of ipio2[] used. - * - * jx nx - 1 - * - * jv index for pointing to the suitable ipio2[] for the - * computation. In general, we want - * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 - * is an integer. Thus - * e0-3-24*jv >= 0 or (e0-3)/24 >= jv - * Hence jv = max(0,(e0-3)/24). - * - * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. - * - * q[] double array with integral value, representing the - * 24-bits chunk of the product of x and 2/pi. - * - * q0 the corresponding exponent of q[0]. Note that the - * exponent for q[i] would be q0-24*i. - * - * PIo2[] double precision array, obtained by cutting pi/2 - * into 24 bits chunks. - * - * f[] ipio2[] in floating point - * - * iq[] integer array by breaking up q[] in 24-bits chunk. - * - * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] - * - * ih integer. If >0 it indicates q[] is >= 0.5, hence - * it also indicates the *sign* of the result. - * - */ -/* - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "libm.h" - -static const int init_jk[] = {3,4,4,6}; /* initial value for jk */ - -/* - * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi - * - * integer array, contains the (24*i)-th to (24*i+23)-th - * bit of 2/pi after binary point. The corresponding - * floating value is - * - * ipio2[i] * 2^(-24(i+1)). - * - * NB: This table must have at least (e0-3)/24 + jk terms. - * For quad precision (e0 <= 16360, jk = 6), this is 686. - */ -static const int32_t ipio2[] = { -0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, -0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, -0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, -0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, -0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, -0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, -0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, -0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, -0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, -0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, -0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, - -#if LDBL_MAX_EXP > 1024 -0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6, -0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, -0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35, -0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30, -0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, -0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4, -0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770, -0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, -0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19, -0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522, -0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, -0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6, -0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E, -0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, -0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3, -0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF, -0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, -0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612, -0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929, -0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, -0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B, -0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C, -0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, -0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB, -0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC, -0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, -0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F, -0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5, -0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, -0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B, -0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA, -0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, -0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3, -0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3, -0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, -0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F, -0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61, -0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, -0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51, -0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0, -0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, -0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6, -0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC, -0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, -0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328, -0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D, -0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, -0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B, -0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4, -0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, -0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F, -0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD, -0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, -0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4, -0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761, -0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, -0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30, -0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262, -0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, -0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1, -0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C, -0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, -0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08, -0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196, -0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, -0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4, -0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC, -0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, -0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0, -0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C, -0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, -0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC, -0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22, -0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, -0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7, -0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5, -0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, -0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4, -0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF, -0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, -0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2, -0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138, -0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, -0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569, -0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34, -0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, -0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D, -0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F, -0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, -0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569, -0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B, -0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, -0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41, -0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49, -0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, -0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110, -0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8, -0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, -0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A, -0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270, -0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, -0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616, -0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B, -0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0, -#endif -}; - -static const double PIo2[] = { - 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ - 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ - 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ - 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ - 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ - 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ - 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ - 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ -}; - -int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec) -{ - int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; - double z,fw,f[20],fq[20],q[20]; - - /* initialize jk*/ - jk = init_jk[prec]; - jp = jk; - - /* determine jx,jv,q0, note that 3>q0 */ - jx = nx-1; - jv = (e0-3)/24; if(jv<0) jv=0; - q0 = e0-24*(jv+1); - - /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ - j = jv-jx; m = jx+jk; - for (i=0; i<=m; i++,j++) - f[i] = j<0 ? 0.0 : (double)ipio2[j]; - - /* compute q[0],q[1],...q[jk] */ - for (i=0; i<=jk; i++) { - for (j=0,fw=0.0; j<=jx; j++) - fw += x[j]*f[jx+i-j]; - q[i] = fw; - } - - jz = jk; -recompute: - /* distill q[] into iq[] reversingly */ - for (i=0,j=jz,z=q[jz]; j>0; i++,j--) { - fw = (double)(int32_t)(0x1p-24*z); - iq[i] = (int32_t)(z - 0x1p24*fw); - z = q[j-1]+fw; - } - - /* compute n */ - z = scalbn(z,q0); /* actual value of z */ - z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ - n = (int32_t)z; - z -= (double)n; - ih = 0; - if (q0 > 0) { /* need iq[jz-1] to determine n */ - i = iq[jz-1]>>(24-q0); n += i; - iq[jz-1] -= i<<(24-q0); - ih = iq[jz-1]>>(23-q0); - } - else if (q0 == 0) ih = iq[jz-1]>>23; - else if (z >= 0.5) ih = 2; - - if (ih > 0) { /* q > 0.5 */ - n += 1; carry = 0; - for (i=0; i 0) { /* rare case: chance is 1 in 12 */ - switch(q0) { - case 1: - iq[jz-1] &= 0x7fffff; break; - case 2: - iq[jz-1] &= 0x3fffff; break; - } - } - if (ih == 2) { - z = 1.0 - z; - if (carry != 0) - z -= scalbn(1.0,q0); - } - } - - /* check if recomputation is needed */ - if (z == 0.0) { - j = 0; - for (i=jz-1; i>=jk; i--) j |= iq[i]; - if (j == 0) { /* need recomputation */ - for (k=1; iq[jk-k]==0; k++); /* k = no. of terms needed */ - - for (i=jz+1; i<=jz+k; i++) { /* add q[jz+1] to q[jz+k] */ - f[jx+i] = (double)ipio2[jv+i]; - for (j=0,fw=0.0; j<=jx; j++) - fw += x[j]*f[jx+i-j]; - q[i] = fw; - } - jz += k; - goto recompute; - } - } - - /* chop off zero terms */ - if (z == 0.0) { - jz -= 1; - q0 -= 24; - while (iq[jz] == 0) { - jz--; - q0 -= 24; - } - } else { /* break z into 24-bit if necessary */ - z = scalbn(z,-q0); - if (z >= 0x1p24) { - fw = (double)(int32_t)(0x1p-24*z); - iq[jz] = (int32_t)(z - 0x1p24*fw); - jz += 1; - q0 += 24; - iq[jz] = (int32_t)fw; - } else - iq[jz] = (int32_t)z; - } - - /* convert integer "bit" chunk to floating-point value */ - fw = scalbn(1.0,q0); - for (i=jz; i>=0; i--) { - q[i] = fw*(double)iq[i]; - fw *= 0x1p-24; - } - - /* compute PIo2[0,...,jp]*q[jz,...,0] */ - for(i=jz; i>=0; i--) { - for (fw=0.0,k=0; k<=jp && k<=jz-i; k++) - fw += PIo2[k]*q[i+k]; - fq[jz-i] = fw; - } - - /* compress fq[] into y[] */ - switch(prec) { - case 0: - fw = 0.0; - for (i=jz; i>=0; i--) - fw += fq[i]; - y[0] = ih==0 ? fw : -fw; - break; - case 1: - case 2: - fw = 0.0; - for (i=jz; i>=0; i--) - fw += fq[i]; - // TODO: drop excess precision here once double_t is used - fw = (double)fw; - y[0] = ih==0 ? fw : -fw; - fw = fq[0]-fw; - for (i=1; i<=jz; i++) - fw += fq[i]; - y[1] = ih==0 ? fw : -fw; - break; - case 3: /* painful */ - for (i=jz; i>0; i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (i=jz; i>1; i--) { - fw = fq[i-1]+fq[i]; - fq[i] += fq[i-1]-fw; - fq[i-1] = fw; - } - for (fw=0.0,i=jz; i>=2; i--) - fw += fq[i]; - if (ih==0) { - y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; - } else { - y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; - } - } - return n&7; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__signbit.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__signbit.c deleted file mode 100644 index 18c6728a..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__signbit.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "libm.h" - -int __signbitd(double x) -{ - union { - double d; - uint64_t i; - } y = { x }; - return y.i>>63; -} - - diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__sin.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__sin.c deleted file mode 100644 index 40309496..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__sin.c +++ /dev/null @@ -1,64 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* __sin( x, y, iy) - * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). - * - * Algorithm - * 1. Since sin(-x) = -sin(x), we need only to consider positive x. - * 2. Callers must return sin(-0) = -0 without calling here since our - * odd polynomial is not evaluated in a way that preserves -0. - * Callers may do the optimization sin(x) ~ x for tiny x. - * 3. sin(x) is approximated by a polynomial of degree 13 on - * [0,pi/4] - * 3 13 - * sin(x) ~ x + S1*x + ... + S6*x - * where - * - * |sin(x) 2 4 6 8 10 12 | -58 - * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 - * | x | - * - * 4. sin(x+y) = sin(x) + sin'(x')*y - * ~ sin(x) + (1-x*x/2)*y - * For better accuracy, let - * 3 2 2 2 2 - * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) - * then 3 2 - * sin(x) = x + (S1*x + (x *(r-y/2)+y)) - */ - -#include "libm.h" - -static const double -S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ -S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ -S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ -S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ -S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ -S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ - -double __sin(double x, double y, int iy) -{ - double_t z,r,v,w; - - z = x*x; - w = z*z; - r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6); - v = z*x; - if (iy == 0) - return x + v*(S1 + z*r); - else - return x - ((z*(0.5*y - v*r) - y) - v*S1); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__tan.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/__tan.c deleted file mode 100644 index 8019844d..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/__tan.c +++ /dev/null @@ -1,110 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/k_tan.c */ -/* - * ==================================================== - * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* __tan( x, y, k ) - * kernel tan function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 - * Input x is assumed to be bounded by ~pi/4 in magnitude. - * Input y is the tail of x. - * Input odd indicates whether tan (if odd = 0) or -1/tan (if odd = 1) is returned. - * - * Algorithm - * 1. Since tan(-x) = -tan(x), we need only to consider positive x. - * 2. Callers must return tan(-0) = -0 without calling here since our - * odd polynomial is not evaluated in a way that preserves -0. - * Callers may do the optimization tan(x) ~ x for tiny x. - * 3. tan(x) is approximated by a odd polynomial of degree 27 on - * [0,0.67434] - * 3 27 - * tan(x) ~ x + T1*x + ... + T13*x - * where - * - * |tan(x) 2 4 26 | -59.2 - * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 - * | x | - * - * Note: tan(x+y) = tan(x) + tan'(x)*y - * ~ tan(x) + (1+x*x)*y - * Therefore, for better accuracy in computing tan(x+y), let - * 3 2 2 2 2 - * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) - * then - * 3 2 - * tan(x+y) = x + (T1*x + (x *(r+y)+y)) - * - * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then - * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) - * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) - */ - -#include "libm.h" - -static const double T[] = { - 3.33333333333334091986e-01, /* 3FD55555, 55555563 */ - 1.33333333333201242699e-01, /* 3FC11111, 1110FE7A */ - 5.39682539762260521377e-02, /* 3FABA1BA, 1BB341FE */ - 2.18694882948595424599e-02, /* 3F9664F4, 8406D637 */ - 8.86323982359930005737e-03, /* 3F8226E3, E96E8493 */ - 3.59207910759131235356e-03, /* 3F6D6D22, C9560328 */ - 1.45620945432529025516e-03, /* 3F57DBC8, FEE08315 */ - 5.88041240820264096874e-04, /* 3F4344D8, F2F26501 */ - 2.46463134818469906812e-04, /* 3F3026F7, 1A8D1068 */ - 7.81794442939557092300e-05, /* 3F147E88, A03792A6 */ - 7.14072491382608190305e-05, /* 3F12B80F, 32F0A7E9 */ - -1.85586374855275456654e-05, /* BEF375CB, DB605373 */ - 2.59073051863633712884e-05, /* 3EFB2A70, 74BF7AD4 */ -}, -pio4 = 7.85398163397448278999e-01, /* 3FE921FB, 54442D18 */ -pio4lo = 3.06161699786838301793e-17; /* 3C81A626, 33145C07 */ - -double __tan(double x, double y, int odd) -{ - double_t z, r, v, w, s, a; - double w0, a0; - uint32_t hx; - int big, sign; - - GET_HIGH_WORD(hx,x); - big = (hx&0x7fffffff) >= 0x3FE59428; /* |x| >= 0.6744 */ - if (big) { - sign = hx>>31; - if (sign) { - x = -x; - y = -y; - } - x = (pio4 - x) + (pio4lo - y); - y = 0.0; - } - z = x * x; - w = z * z; - /* - * Break x^5*(T[1]+x^2*T[2]+...) into - * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + - * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) - */ - r = T[1] + w*(T[3] + w*(T[5] + w*(T[7] + w*(T[9] + w*T[11])))); - v = z*(T[2] + w*(T[4] + w*(T[6] + w*(T[8] + w*(T[10] + w*T[12]))))); - s = z * x; - r = y + z*(s*(r + v) + y) + s*T[0]; - w = x + r; - if (big) { - s = 1 - 2*odd; - v = s - 2.0 * (x + (r - w*w/(w + s))); - return sign ? -v : v; - } - if (!odd) - return w; - /* -1.0/(x+r) has up to 2ulp error, so compute it accurately */ - w0 = w; - SET_LOW_WORD(w0, 0); - v = r - (w0 - x); /* w0+v = r+x */ - a0 = a = -1.0 / w; - SET_LOW_WORD(a0, 0); - return a0 + a*(1.0 + a0*w0 + a0*v); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/acos.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/acos.c deleted file mode 100644 index 6104a32b..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/acos.c +++ /dev/null @@ -1,101 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_acos.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* acos(x) - * Method : - * acos(x) = pi/2 - asin(x) - * acos(-x) = pi/2 + asin(x) - * For |x|<=0.5 - * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) - * For x>0.5 - * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) - * = 2asin(sqrt((1-x)/2)) - * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) - * = 2f + (2c + 2s*z*R(z)) - * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term - * for f so that f+c ~ sqrt(z). - * For x<-0.5 - * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) - * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) - * - * Special cases: - * if x is NaN, return x itself; - * if |x|>1, return NaN with invalid signal. - * - * Function needed: sqrt - */ - -#include "libm.h" - -static const double -pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ -pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ -pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ -pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ -pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ -pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ -pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ -pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ -qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ -qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ -qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ -qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ - -static double R(double z) -{ - double_t p, q; - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - return p/q; -} - -double acos(double x) -{ - double z,w,s,c,df; - uint32_t hx,ix; - - GET_HIGH_WORD(hx, x); - ix = hx & 0x7fffffff; - /* |x| >= 1 or nan */ - if (ix >= 0x3ff00000) { - uint32_t lx; - - GET_LOW_WORD(lx,x); - if (((ix-0x3ff00000) | lx) == 0) { - /* acos(1)=0, acos(-1)=pi */ - if (hx >> 31) - return 2*pio2_hi + 0x1p-120f; - return 0; - } - return 0/(x-x); - } - /* |x| < 0.5 */ - if (ix < 0x3fe00000) { - if (ix <= 0x3c600000) /* |x| < 2**-57 */ - return pio2_hi + 0x1p-120f; - return pio2_hi - (x - (pio2_lo-x*R(x*x))); - } - /* x < -0.5 */ - if (hx >> 31) { - z = (1.0+x)*0.5; - s = sqrt(z); - w = R(z)*s-pio2_lo; - return 2*(pio2_hi - (s+w)); - } - /* x > 0.5 */ - z = (1.0-x)*0.5; - s = sqrt(z); - df = s; - SET_LOW_WORD(df,0); - c = (z-df*df)/(s+df); - w = R(z)*s+c; - return 2*(df+w); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/acosh.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/acosh.c deleted file mode 100644 index badbf908..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/acosh.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "libm.h" - -#if FLT_EVAL_METHOD==2 -#undef sqrt -#define sqrt sqrtl -#endif - -/* acosh(x) = log(x + sqrt(x*x-1)) */ -double acosh(double x) -{ - union {double f; uint64_t i;} u = {.f = x}; - unsigned e = u.i >> 52 & 0x7ff; - - /* x < 1 domain error is handled in the called functions */ - - if (e < 0x3ff + 1) - /* |x| < 2, up to 2ulp error in [1,1.125] */ - return log1p(x-1 + sqrt((x-1)*(x-1)+2*(x-1))); - if (e < 0x3ff + 26) - /* |x| < 0x1p26 */ - return log(2*x - 1/(x+sqrt(x*x-1))); - /* |x| >= 0x1p26 or nan */ - return log(x) + 0.693147180559945309417232121458176568; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/asin.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/asin.c deleted file mode 100644 index 96b4cdfa..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/asin.c +++ /dev/null @@ -1,107 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_asin.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* asin(x) - * Method : - * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... - * we approximate asin(x) on [0,0.5] by - * asin(x) = x + x*x^2*R(x^2) - * where - * R(x^2) is a rational approximation of (asin(x)-x)/x^3 - * and its remez error is bounded by - * |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75) - * - * For x in [0.5,1] - * asin(x) = pi/2-2*asin(sqrt((1-x)/2)) - * Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2; - * then for x>0.98 - * asin(x) = pi/2 - 2*(s+s*z*R(z)) - * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) - * For x<=0.98, let pio4_hi = pio2_hi/2, then - * f = hi part of s; - * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) - * and - * asin(x) = pi/2 - 2*(s+s*z*R(z)) - * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) - * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) - * - * Special cases: - * if x is NaN, return x itself; - * if |x|>1, return NaN with invalid signal. - * - */ - -#include "libm.h" - -static const double -pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ -pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ -/* coefficients for R(x^2) */ -pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ -pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ -pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ -pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ -pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ -pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ -qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ -qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ -qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ -qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ - -static double R(double z) -{ - double_t p, q; - p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); - q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4))); - return p/q; -} - -double asin(double x) -{ - double z,r,s; - uint32_t hx,ix; - - GET_HIGH_WORD(hx, x); - ix = hx & 0x7fffffff; - /* |x| >= 1 or nan */ - if (ix >= 0x3ff00000) { - uint32_t lx; - GET_LOW_WORD(lx, x); - if (((ix-0x3ff00000) | lx) == 0) - /* asin(1) = +-pi/2 with inexact */ - return x*pio2_hi + 0x1p-120f; - return 0/(x-x); - } - /* |x| < 0.5 */ - if (ix < 0x3fe00000) { - /* if 0x1p-1022 <= |x| < 0x1p-26, avoid raising underflow */ - if (ix < 0x3e500000 && ix >= 0x00100000) - return x; - return x + x*R(x*x); - } - /* 1 > |x| >= 0.5 */ - z = (1 - fabs(x))*0.5; - s = sqrt(z); - r = R(z); - if (ix >= 0x3fef3333) { /* if |x| > 0.975 */ - x = pio2_hi-(2*(s+s*r)-pio2_lo); - } else { - double f,c; - /* f+c = sqrt(z) */ - f = s; - SET_LOW_WORD(f,0); - c = (z-f*f)/(s+f); - x = 0.5*pio2_hi - (2*s*r - (pio2_lo-2*c) - (0.5*pio2_hi-2*f)); - } - if (hx >> 31) - return -x; - return x; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/asinh.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/asinh.c deleted file mode 100644 index 0829f228..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/asinh.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "libm.h" - -/* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */ -double asinh(double x) -{ - union {double f; uint64_t i;} u = {.f = x}; - unsigned e = u.i >> 52 & 0x7ff; - unsigned s = u.i >> 63; - - /* |x| */ - u.i &= (uint64_t)-1/2; - x = u.f; - - if (e >= 0x3ff + 26) { - /* |x| >= 0x1p26 or inf or nan */ - x = log(x) + 0.693147180559945309417232121458176568; - } else if (e >= 0x3ff + 1) { - /* |x| >= 2 */ - x = log(2*x + 1/(sqrt(x*x+1)+x)); - } else if (e >= 0x3ff - 26) { - /* |x| >= 0x1p-26, up to 1.6ulp error in [0.125,0.5] */ - x = log1p(x + x*x/(sqrt(x*x+1)+1)); - } else { - /* |x| < 0x1p-26, raise inexact if x != 0 */ - FORCE_EVAL(x + 0x1p120f); - } - return s ? -x : x; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/atan.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/atan.c deleted file mode 100644 index 63b0ab25..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/atan.c +++ /dev/null @@ -1,116 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_atan.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* atan(x) - * Method - * 1. Reduce x to positive by atan(x) = -atan(-x). - * 2. According to the integer k=4t+0.25 chopped, t=x, the argument - * is further reduced to one of the following intervals and the - * arctangent of t is evaluated by the corresponding formula: - * - * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) - * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) - * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) - * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) - * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - - -#include "libm.h" - -static const double atanhi[] = { - 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ - 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ - 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ - 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ -}; - -static const double atanlo[] = { - 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ - 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ - 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ - 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ -}; - -static const double aT[] = { - 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ - -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ - 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ - -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ - 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ - -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ - 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ - -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ - 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ - -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ - 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ -}; - -double atan(double x) -{ - double_t w,s1,s2,z; - uint32_t ix,sign; - int id; - - GET_HIGH_WORD(ix, x); - sign = ix >> 31; - ix &= 0x7fffffff; - if (ix >= 0x44100000) { /* if |x| >= 2^66 */ - if (isnan(x)) - return x; - z = atanhi[3] + 0x1p-120f; - return sign ? -z : z; - } - if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ - if (ix < 0x3e400000) { /* |x| < 2^-27 */ - if (ix < 0x00100000) - /* raise underflow for subnormal x */ - FORCE_EVAL((float)x); - return x; - } - id = -1; - } else { - x = fabs(x); - if (ix < 0x3ff30000) { /* |x| < 1.1875 */ - if (ix < 0x3fe60000) { /* 7/16 <= |x| < 11/16 */ - id = 0; - x = (2.0*x-1.0)/(2.0+x); - } else { /* 11/16 <= |x| < 19/16 */ - id = 1; - x = (x-1.0)/(x+1.0); - } - } else { - if (ix < 0x40038000) { /* |x| < 2.4375 */ - id = 2; - x = (x-1.5)/(1.0+1.5*x); - } else { /* 2.4375 <= |x| < 2^66 */ - id = 3; - x = -1.0/x; - } - } - } - /* end of argument reduction */ - z = x*x; - w = z*z; - /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ - s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); - s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); - if (id < 0) - return x - x*(s1+s2); - z = atanhi[id] - (x*(s1+s2) - atanlo[id] - x); - return sign ? -z : z; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/atan2.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/atan2.c deleted file mode 100644 index 91378b97..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/atan2.c +++ /dev/null @@ -1,107 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_atan2.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - * - */ -/* atan2(y,x) - * Method : - * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). - * 2. Reduce x to positive by (if x and y are unexceptional): - * ARG (x+iy) = arctan(y/x) ... if x > 0, - * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, - * - * Special cases: - * - * ATAN2((anything), NaN ) is NaN; - * ATAN2(NAN , (anything) ) is NaN; - * ATAN2(+-0, +(anything but NaN)) is +-0 ; - * ATAN2(+-0, -(anything but NaN)) is +-pi ; - * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; - * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; - * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; - * ATAN2(+-INF,+INF ) is +-pi/4 ; - * ATAN2(+-INF,-INF ) is +-3pi/4; - * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "libm.h" - -static const double -pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ -pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ - -double atan2(double y, double x) -{ - double z; - uint32_t m,lx,ly,ix,iy; - - if (isnan(x) || isnan(y)) - return x+y; - EXTRACT_WORDS(ix, lx, x); - EXTRACT_WORDS(iy, ly, y); - if (((ix-0x3ff00000) | lx) == 0) /* x = 1.0 */ - return atan(y); - m = ((iy>>31)&1) | ((ix>>30)&2); /* 2*sign(x)+sign(y) */ - ix = ix & 0x7fffffff; - iy = iy & 0x7fffffff; - - /* when y = 0 */ - if ((iy|ly) == 0) { - switch(m) { - case 0: - case 1: return y; /* atan(+-0,+anything)=+-0 */ - case 2: return pi; /* atan(+0,-anything) = pi */ - case 3: return -pi; /* atan(-0,-anything) =-pi */ - } - } - /* when x = 0 */ - if ((ix|lx) == 0) - return m&1 ? -pi/2 : pi/2; - /* when x is INF */ - if (ix == 0x7ff00000) { - if (iy == 0x7ff00000) { - switch(m) { - case 0: return pi/4; /* atan(+INF,+INF) */ - case 1: return -pi/4; /* atan(-INF,+INF) */ - case 2: return 3*pi/4; /* atan(+INF,-INF) */ - case 3: return -3*pi/4; /* atan(-INF,-INF) */ - } - } else { - switch(m) { - case 0: return 0.0; /* atan(+...,+INF) */ - case 1: return -0.0; /* atan(-...,+INF) */ - case 2: return pi; /* atan(+...,-INF) */ - case 3: return -pi; /* atan(-...,-INF) */ - } - } - } - /* |y/x| > 0x1p64 */ - if (ix+(64<<20) < iy || iy == 0x7ff00000) - return m&1 ? -pi/2 : pi/2; - - /* z = atan(|y/x|) without spurious underflow */ - if ((m&2) && iy+(64<<20) < ix) /* |y/x| < 0x1p-64, x<0 */ - z = 0; - else - z = atan(fabs(y/x)); - switch (m) { - case 0: return z; /* atan(+,+) */ - case 1: return -z; /* atan(-,+) */ - case 2: return pi - (z-pi_lo); /* atan(+,-) */ - default: /* case 3 */ - return (z-pi_lo) - pi; /* atan(-,-) */ - } -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/atanh.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/atanh.c deleted file mode 100644 index 63a035d7..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/atanh.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "libm.h" - -/* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ -double atanh(double x) -{ - union {double f; uint64_t i;} u = {.f = x}; - unsigned e = u.i >> 52 & 0x7ff; - unsigned s = u.i >> 63; - double_t y; - - /* |x| */ - u.i &= (uint64_t)-1/2; - y = u.f; - - if (e < 0x3ff - 1) { - if (e < 0x3ff - 32) { - /* handle underflow */ - if (e == 0) - FORCE_EVAL((float)y); - } else { - /* |x| < 0.5, up to 1.7ulp error */ - y = 0.5*log1p(2*y + 2*y*y/(1-y)); - } - } else { - /* avoid overflow */ - y = 0.5*log1p(2*(y/(1-y))); - } - return s ? -y : y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/ceil.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/ceil.c deleted file mode 100644 index b13e6f2d..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/ceil.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "libm.h" - -#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 -#define EPS DBL_EPSILON -#elif FLT_EVAL_METHOD==2 -#define EPS LDBL_EPSILON -#endif -static const double_t toint = 1/EPS; - -double ceil(double x) -{ - union {double f; uint64_t i;} u = {x}; - int e = u.i >> 52 & 0x7ff; - double_t y; - - if (e >= 0x3ff+52 || x == 0) - return x; - /* y = int(x) - x, where int(x) is an integer neighbor of x */ - if (u.i >> 63) - y = x - toint + toint - x; - else - y = x + toint - toint - x; - /* special case because of non-nearest rounding modes */ - if (e <= 0x3ff-1) { - FORCE_EVAL(y); - return u.i >> 63 ? -0.0 : 1; - } - if (y < 0) - return x + y + 1; - return x + y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/cos.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/cos.c deleted file mode 100644 index ee97f68b..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/cos.c +++ /dev/null @@ -1,77 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_cos.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* cos(x) - * Return cosine function of x. - * - * kernel function: - * __sin ... sine function on [-pi/4,pi/4] - * __cos ... cosine function on [-pi/4,pi/4] - * __rem_pio2 ... argument reduction routine - * - * Method. - * Let S,C and T denote the sin, cos and tan respectively on - * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 - * in [-pi/4 , +pi/4], and let n = k mod 4. - * We have - * - * n sin(x) cos(x) tan(x) - * ---------------------------------------------------------- - * 0 S C T - * 1 C -S -1/T - * 2 -S -C T - * 3 -C S -1/T - * ---------------------------------------------------------- - * - * Special cases: - * Let trig be any of sin, cos, or tan. - * trig(+-INF) is NaN, with signals; - * trig(NaN) is that NaN; - * - * Accuracy: - * TRIG(x) returns trig(x) nearly rounded - */ - -#include "libm.h" - -double cos(double x) -{ - double y[2]; - uint32_t ix; - unsigned n; - - GET_HIGH_WORD(ix, x); - ix &= 0x7fffffff; - - /* |x| ~< pi/4 */ - if (ix <= 0x3fe921fb) { - if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */ - /* raise inexact if x!=0 */ - FORCE_EVAL(x + 0x1p120f); - return 1.0; - } - return __cos(x, 0); - } - - /* cos(Inf or NaN) is NaN */ - if (ix >= 0x7ff00000) - return x-x; - - /* argument reduction */ - n = __rem_pio2(x, y); - switch (n&3) { - case 0: return __cos(y[0], y[1]); - case 1: return -__sin(y[0], y[1], 1); - case 2: return -__cos(y[0], y[1]); - default: - return __sin(y[0], y[1], 1); - } -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/cosh.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/cosh.c deleted file mode 100644 index 100f8231..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/cosh.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "libm.h" - -/* cosh(x) = (exp(x) + 1/exp(x))/2 - * = 1 + 0.5*(exp(x)-1)*(exp(x)-1)/exp(x) - * = 1 + x*x/2 + o(x^4) - */ -double cosh(double x) -{ - union {double f; uint64_t i;} u = {.f = x}; - uint32_t w; - double t; - - /* |x| */ - u.i &= (uint64_t)-1/2; - x = u.f; - w = u.i >> 32; - - /* |x| < log(2) */ - if (w < 0x3fe62e42) { - if (w < 0x3ff00000 - (26<<20)) { - /* raise inexact if x!=0 */ - FORCE_EVAL(x + 0x1p120f); - return 1; - } - t = expm1(x); - return 1 + t*t/(2*(1+t)); - } - - /* |x| < log(DBL_MAX) */ - if (w < 0x40862e42) { - t = exp(x); - /* note: if x>log(0x1p26) then the 1/t is not needed */ - return 0.5*(t + 1/t); - } - - /* |x| > log(DBL_MAX) or nan */ - /* note: the result is stored to handle overflow */ - t = __expo2(x); - return t; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/erf.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/erf.c deleted file mode 100644 index 2f30a298..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/erf.c +++ /dev/null @@ -1,273 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_erf.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* double erf(double x) - * double erfc(double x) - * x - * 2 |\ - * erf(x) = --------- | exp(-t*t)dt - * sqrt(pi) \| - * 0 - * - * erfc(x) = 1-erf(x) - * Note that - * erf(-x) = -erf(x) - * erfc(-x) = 2 - erfc(x) - * - * Method: - * 1. For |x| in [0, 0.84375] - * erf(x) = x + x*R(x^2) - * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] - * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] - * where R = P/Q where P is an odd poly of degree 8 and - * Q is an odd poly of degree 10. - * -57.90 - * | R - (erf(x)-x)/x | <= 2 - * - * - * Remark. The formula is derived by noting - * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) - * and that - * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 - * is close to one. The interval is chosen because the fix - * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is - * near 0.6174), and by some experiment, 0.84375 is chosen to - * guarantee the error is less than one ulp for erf. - * - * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and - * c = 0.84506291151 rounded to single (24 bits) - * erf(x) = sign(x) * (c + P1(s)/Q1(s)) - * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 - * 1+(c+P1(s)/Q1(s)) if x < 0 - * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 - * Remark: here we use the taylor series expansion at x=1. - * erf(1+s) = erf(1) + s*Poly(s) - * = 0.845.. + P1(s)/Q1(s) - * That is, we use rational approximation to approximate - * erf(1+s) - (c = (single)0.84506291151) - * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] - * where - * P1(s) = degree 6 poly in s - * Q1(s) = degree 6 poly in s - * - * 3. For x in [1.25,1/0.35(~2.857143)], - * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) - * erf(x) = 1 - erfc(x) - * where - * R1(z) = degree 7 poly in z, (z=1/x^2) - * S1(z) = degree 8 poly in z - * - * 4. For x in [1/0.35,28] - * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 - * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 - * erf(x) = sign(x) *(1 - tiny) (raise inexact) - * erfc(x) = tiny*tiny (raise underflow) if x > 0 - * = 2 - tiny if x<0 - * - * 7. Special case: - * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, - * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, - * erfc/erf(NaN) is NaN - */ - -#include "libm.h" - -static const double -erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ -/* - * Coefficients for approximation to erf on [0,0.84375] - */ -efx8 = 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ -pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ -pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ -pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ -pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ -pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ -qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ -qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ -qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ -qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ -qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ -/* - * Coefficients for approximation to erf in [0.84375,1.25] - */ -pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ -pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ -pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ -pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ -pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ -pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ -pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ -qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ -qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ -qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ -qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ -qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ -qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ -/* - * Coefficients for approximation to erfc in [1.25,1/0.35] - */ -ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ -ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ -ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ -ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ -ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ -ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ -ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ -ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ -sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ -sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ -sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ -sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ -sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ -sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ -sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ -sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ -/* - * Coefficients for approximation to erfc in [1/.35,28] - */ -rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ -rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ -rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ -rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ -rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ -rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ -rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ -sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ -sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ -sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ -sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ -sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ -sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ -sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ - -static double erfc1(double x) -{ - double_t s,P,Q; - - s = fabs(x) - 1; - P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); - Q = 1+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); - return 1 - erx - P/Q; -} - -static double erfc2(uint32_t ix, double x) -{ - double_t s,R,S; - double z; - - if (ix < 0x3ff40000) /* |x| < 1.25 */ - return erfc1(x); - - x = fabs(x); - s = 1/(x*x); - if (ix < 0x4006db6d) { /* |x| < 1/.35 ~ 2.85714 */ - R = ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( - ra5+s*(ra6+s*ra7)))))); - S = 1.0+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( - sa5+s*(sa6+s*(sa7+s*sa8))))))); - } else { /* |x| > 1/.35 */ - R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( - rb5+s*rb6))))); - S = 1.0+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( - sb5+s*(sb6+s*sb7)))))); - } - z = x; - SET_LOW_WORD(z,0); - return exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S)/x; -} - -double erf(double x) -{ - double r,s,z,y; - uint32_t ix; - int sign; - - GET_HIGH_WORD(ix, x); - sign = ix>>31; - ix &= 0x7fffffff; - if (ix >= 0x7ff00000) { - /* erf(nan)=nan, erf(+-inf)=+-1 */ - return 1-2*sign + 1/x; - } - if (ix < 0x3feb0000) { /* |x| < 0.84375 */ - if (ix < 0x3e300000) { /* |x| < 2**-28 */ - /* avoid underflow */ - return 0.125*(8*x + efx8*x); - } - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = 1.0+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - return x + x*y; - } - if (ix < 0x40180000) /* 0.84375 <= |x| < 6 */ - y = 1 - erfc2(ix,x); - else - y = 1 - 0x1p-1022; - return sign ? -y : y; -} - -double erfc(double x) -{ - double r,s,z,y; - uint32_t ix; - int sign; - - GET_HIGH_WORD(ix, x); - sign = ix>>31; - ix &= 0x7fffffff; - if (ix >= 0x7ff00000) { - /* erfc(nan)=nan, erfc(+-inf)=0,2 */ - return 2*sign + 1/x; - } - if (ix < 0x3feb0000) { /* |x| < 0.84375 */ - if (ix < 0x3c700000) /* |x| < 2**-56 */ - return 1.0 - x; - z = x*x; - r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); - s = 1.0+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); - y = r/s; - if (sign || ix < 0x3fd00000) { /* x < 1/4 */ - return 1.0 - (x+x*y); - } - return 0.5 - (x - 0.5 + x*y); - } - if (ix < 0x403c0000) { /* 0.84375 <= |x| < 28 */ - return sign ? 2 - erfc2(ix,x) : erfc2(ix,x); - } - return sign ? 2 - 0x1p-1022 : 0x1p-1022*0x1p-1022; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/exp.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/exp.c deleted file mode 100644 index 9ea672fa..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/exp.c +++ /dev/null @@ -1,134 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_exp.c */ -/* - * ==================================================== - * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. - * - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* exp(x) - * Returns the exponential of x. - * - * Method - * 1. Argument reduction: - * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. - * Given x, find r and integer k such that - * - * x = k*ln2 + r, |r| <= 0.5*ln2. - * - * Here r will be represented as r = hi-lo for better - * accuracy. - * - * 2. Approximation of exp(r) by a special rational function on - * the interval [0,0.34658]: - * Write - * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... - * We use a special Remez algorithm on [0,0.34658] to generate - * a polynomial of degree 5 to approximate R. The maximum error - * of this polynomial approximation is bounded by 2**-59. In - * other words, - * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 - * (where z=r*r, and the values of P1 to P5 are listed below) - * and - * | 5 | -59 - * | 2.0+P1*z+...+P5*z - R(z) | <= 2 - * | | - * The computation of exp(r) thus becomes - * 2*r - * exp(r) = 1 + ---------- - * R(r) - r - * r*c(r) - * = 1 + r + ----------- (for better accuracy) - * 2 - c(r) - * where - * 2 4 10 - * c(r) = r - (P1*r + P2*r + ... + P5*r ). - * - * 3. Scale back to obtain exp(x): - * From step 1, we have - * exp(x) = 2^k * exp(r) - * - * Special cases: - * exp(INF) is INF, exp(NaN) is NaN; - * exp(-INF) is 0, and - * for finite argument, only exp(0)=1 is exact. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Misc. info. - * For IEEE double - * if x > 709.782712893383973096 then exp(x) overflows - * if x < -745.133219101941108420 then exp(x) underflows - */ - -#include "libm.h" - -static const double -half[2] = {0.5,-0.5}, -ln2hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ -ln2lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ -invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ -P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ -P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ -P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ -P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ -P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ - -double exp(double x) -{ - double_t hi, lo, c, xx, y; - int k, sign; - uint32_t hx; - - GET_HIGH_WORD(hx, x); - sign = hx>>31; - hx &= 0x7fffffff; /* high word of |x| */ - - /* special cases */ - if (hx >= 0x4086232b) { /* if |x| >= 708.39... */ - if (isnan(x)) - return x; - if (x > 709.782712893383973096) { - /* overflow if x!=inf */ - x *= 0x1p1023; - return x; - } - if (x < -708.39641853226410622) { - /* underflow if x!=-inf */ - FORCE_EVAL((float)(-0x1p-149/x)); - if (x < -745.13321910194110842) - return 0; - } - } - - /* argument reduction */ - if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ - if (hx >= 0x3ff0a2b2) /* if |x| >= 1.5 ln2 */ - k = (int)(invln2*x + half[sign]); - else - k = 1 - sign - sign; - hi = x - k*ln2hi; /* k*ln2hi is exact here */ - lo = k*ln2lo; - x = hi - lo; - } else if (hx > 0x3e300000) { /* if |x| > 2**-28 */ - k = 0; - hi = x; - lo = 0; - } else { - /* inexact if x!=0 */ - FORCE_EVAL(0x1p1023 + x); - return 1 + x; - } - - /* x is now in primary range */ - xx = x*x; - c = x - xx*(P1+xx*(P2+xx*(P3+xx*(P4+xx*P5)))); - y = 1 + (x*c/(2-c) - lo + hi); - if (k == 0) - return y; - return scalbn(y, k); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/expm1.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/expm1.c deleted file mode 100644 index ac1e61e4..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/expm1.c +++ /dev/null @@ -1,201 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_expm1.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* expm1(x) - * Returns exp(x)-1, the exponential of x minus 1. - * - * Method - * 1. Argument reduction: - * Given x, find r and integer k such that - * - * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 - * - * Here a correction term c will be computed to compensate - * the error in r when rounded to a floating-point number. - * - * 2. Approximating expm1(r) by a special rational function on - * the interval [0,0.34658]: - * Since - * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... - * we define R1(r*r) by - * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) - * That is, - * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) - * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) - * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... - * We use a special Remez algorithm on [0,0.347] to generate - * a polynomial of degree 5 in r*r to approximate R1. The - * maximum error of this polynomial approximation is bounded - * by 2**-61. In other words, - * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 - * where Q1 = -1.6666666666666567384E-2, - * Q2 = 3.9682539681370365873E-4, - * Q3 = -9.9206344733435987357E-6, - * Q4 = 2.5051361420808517002E-7, - * Q5 = -6.2843505682382617102E-9; - * z = r*r, - * with error bounded by - * | 5 | -61 - * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 - * | | - * - * expm1(r) = exp(r)-1 is then computed by the following - * specific way which minimize the accumulation rounding error: - * 2 3 - * r r [ 3 - (R1 + R1*r/2) ] - * expm1(r) = r + --- + --- * [--------------------] - * 2 2 [ 6 - r*(3 - R1*r/2) ] - * - * To compensate the error in the argument reduction, we use - * expm1(r+c) = expm1(r) + c + expm1(r)*c - * ~ expm1(r) + c + r*c - * Thus c+r*c will be added in as the correction terms for - * expm1(r+c). Now rearrange the term to avoid optimization - * screw up: - * ( 2 2 ) - * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) - * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) - * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) - * ( ) - * - * = r - E - * 3. Scale back to obtain expm1(x): - * From step 1, we have - * expm1(x) = either 2^k*[expm1(r)+1] - 1 - * = or 2^k*[expm1(r) + (1-2^-k)] - * 4. Implementation notes: - * (A). To save one multiplication, we scale the coefficient Qi - * to Qi*2^i, and replace z by (x^2)/2. - * (B). To achieve maximum accuracy, we compute expm1(x) by - * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) - * (ii) if k=0, return r-E - * (iii) if k=-1, return 0.5*(r-E)-0.5 - * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) - * else return 1.0+2.0*(r-E); - * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) - * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else - * (vii) return 2^k(1-((E+2^-k)-r)) - * - * Special cases: - * expm1(INF) is INF, expm1(NaN) is NaN; - * expm1(-INF) is -1, and - * for finite argument, only expm1(0)=0 is exact. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Misc. info. - * For IEEE double - * if x > 7.09782712893383973096e+02 then expm1(x) overflow - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "libm.h" - -static const double -o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ -ln2_hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ -ln2_lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ -invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ -/* Scaled Q's: Qn_here = 2**n * Qn_above, for R(2*z) where z = hxs = x*x/2: */ -Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ -Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ -Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ -Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ -Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ - -double expm1(double x) -{ - double_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk; - union {double f; uint64_t i;} u = {x}; - uint32_t hx = u.i>>32 & 0x7fffffff; - int k, sign = u.i>>63; - - /* filter out huge and non-finite argument */ - if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */ - if (isnan(x)) - return x; - if (sign) - return -1; - if (x > o_threshold) { - x *= 0x1p1023; - return x; - } - } - - /* argument reduction */ - if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ - if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ - if (!sign) { - hi = x - ln2_hi; - lo = ln2_lo; - k = 1; - } else { - hi = x + ln2_hi; - lo = -ln2_lo; - k = -1; - } - } else { - k = invln2*x + (sign ? -0.5 : 0.5); - t = k; - hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ - lo = t*ln2_lo; - } - x = hi-lo; - c = (hi-x)-lo; - } else if (hx < 0x3c900000) { /* |x| < 2**-54, return x */ - if (hx < 0x00100000) - FORCE_EVAL((float)x); - return x; - } else - k = 0; - - /* x is now in primary range */ - hfx = 0.5*x; - hxs = x*hfx; - r1 = 1.0+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); - t = 3.0-r1*hfx; - e = hxs*((r1-t)/(6.0 - x*t)); - if (k == 0) /* c is 0 */ - return x - (x*e-hxs); - e = x*(e-c) - c; - e -= hxs; - /* exp(x) ~ 2^k (x_reduced - e + 1) */ - if (k == -1) - return 0.5*(x-e) - 0.5; - if (k == 1) { - if (x < -0.25) - return -2.0*(e-(x+0.5)); - return 1.0+2.0*(x-e); - } - u.i = (uint64_t)(0x3ff + k)<<52; /* 2^k */ - twopk = u.f; - if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */ - y = x - e + 1.0; - if (k == 1024) - y = y*2.0*0x1p1023; - else - y = y*twopk; - return y - 1.0; - } - u.i = (uint64_t)(0x3ff - k)<<52; /* 2^-k */ - if (k < 20) - y = (x-e+(1-u.f))*twopk; - else - y = (x-(e+u.f)+1)*twopk; - return y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/floor.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/floor.c deleted file mode 100644 index 14a31cd8..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/floor.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "libm.h" - -#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 -#define EPS DBL_EPSILON -#elif FLT_EVAL_METHOD==2 -#define EPS LDBL_EPSILON -#endif -static const double_t toint = 1/EPS; - -double floor(double x) -{ - union {double f; uint64_t i;} u = {x}; - int e = u.i >> 52 & 0x7ff; - double_t y; - - if (e >= 0x3ff+52 || x == 0) - return x; - /* y = int(x) - x, where int(x) is an integer neighbor of x */ - if (u.i >> 63) - y = x - toint + toint - x; - else - y = x + toint - toint - x; - /* special case because of non-nearest rounding modes */ - if (e <= 0x3ff-1) { - FORCE_EVAL(y); - return u.i >> 63 ? -1 : 0; - } - if (y > 0) - return x + y - 1; - return x + y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/fmod.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/fmod.c deleted file mode 100644 index 6849722b..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/fmod.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -double fmod(double x, double y) -{ - union {double f; uint64_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>52 & 0x7ff; - int ey = uy.i>>52 & 0x7ff; - int sx = ux.i>>63; - uint64_t i; - - /* in the followings uxi should be ux.i, but then gcc wrongly adds */ - /* float load/store to inner loops ruining performance and code size */ - uint64_t uxi = ux.i; - - if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) - return (x*y)/(x*y); - if (uxi<<1 <= uy.i<<1) { - if (uxi<<1 == uy.i<<1) - return 0*x; - return x; - } - - /* normalize x and y */ - if (!ex) { - for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1ULL >> 12; - uxi |= 1ULL << 52; - } - if (!ey) { - for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1ULL >> 12; - uy.i |= 1ULL << 52; - } - - /* x mod y */ - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 63 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - for (; uxi>>52 == 0; uxi <<= 1, ex--); - - /* scale result */ - if (ex > 0) { - uxi -= 1ULL << 52; - uxi |= (uint64_t)ex << 52; - } else { - uxi >>= -ex + 1; - } - uxi |= (uint64_t)sx << 63; - ux.i = uxi; - return ux.f; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/frexp.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/frexp.c deleted file mode 100644 index 27b6266e..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/frexp.c +++ /dev/null @@ -1,23 +0,0 @@ -#include -#include - -double frexp(double x, int *e) -{ - union { double d; uint64_t i; } y = { x }; - int ee = y.i>>52 & 0x7ff; - - if (!ee) { - if (x) { - x = frexp(x*0x1p64, e); - *e -= 64; - } else *e = 0; - return x; - } else if (ee == 0x7ff) { - return x; - } - - *e = ee - 0x3fe; - y.i &= 0x800fffffffffffffull; - y.i |= 0x3fe0000000000000ull; - return y.d; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/ldexp.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/ldexp.c deleted file mode 100644 index f4d1cd6a..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/ldexp.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -double ldexp(double x, int n) -{ - return scalbn(x, n); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/lgamma.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/lgamma.c deleted file mode 100644 index ed193da1..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/lgamma.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -double __lgamma_r(double, int*); - -double lgamma(double x) { - int sign; - return __lgamma_r(x, &sign); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/libm.h b/MicroPython_BUILD/components/micropython/lib/libm_dbl/libm.h deleted file mode 100644 index dc0b431a..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/libm.h +++ /dev/null @@ -1,96 +0,0 @@ -// Portions of this file are extracted from musl-1.1.16 src/internal/libm.h - -/* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -#include -#include - -#define FLT_EVAL_METHOD 0 - -#define FORCE_EVAL(x) do { \ - if (sizeof(x) == sizeof(float)) { \ - volatile float __x; \ - __x = (x); \ - (void)__x; \ - } else if (sizeof(x) == sizeof(double)) { \ - volatile double __x; \ - __x = (x); \ - (void)__x; \ - } else { \ - volatile long double __x; \ - __x = (x); \ - (void)__x; \ - } \ -} while(0) - -/* Get two 32 bit ints from a double. */ -#define EXTRACT_WORDS(hi,lo,d) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - (hi) = __u.i >> 32; \ - (lo) = (uint32_t)__u.i; \ -} while (0) - -/* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD(hi,d) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - (hi) = __u.i >> 32; \ -} while (0) - -/* Get the less significant 32 bit int from a double. */ -#define GET_LOW_WORD(lo,d) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - (lo) = (uint32_t)__u.i; \ -} while (0) - -/* Set a double from two 32 bit ints. */ -#define INSERT_WORDS(d,hi,lo) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \ - (d) = __u.f; \ -} while (0) - -/* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD(d,hi) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - __u.i &= 0xffffffff; \ - __u.i |= (uint64_t)(hi) << 32; \ - (d) = __u.f; \ -} while (0) - -/* Set the less significant 32 bits of a double from an int. */ -#define SET_LOW_WORD(d,lo) \ -do { \ - union {double f; uint64_t i;} __u; \ - __u.f = (d); \ - __u.i &= 0xffffffff00000000ull; \ - __u.i |= (uint32_t)(lo); \ - (d) = __u.f; \ -} while (0) - -#define DBL_EPSILON 2.22044604925031308085e-16 - -int __rem_pio2(double, double*); -int __rem_pio2_large(double*, double*, int, int, int); -double __sin(double, double, int); -double __cos(double, double); -double __tan(double, double, int); -double __expo2(double); diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/log.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/log.c deleted file mode 100644 index e61e113d..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/log.c +++ /dev/null @@ -1,118 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_log.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* log(x) - * Return the logarithm of x - * - * Method : - * 1. Argument Reduction: find k and f such that - * x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * 2. Approximation of log(1+f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Remez algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s - * (the values of Lg1 to Lg7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lg1*s +...+Lg7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log(1+f) = f - s*(f - R) (if f is not too large) - * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) - * - * 3. Finally, log(x) = k*ln2 + log(1+f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log(x) is NaN with signal if x < 0 (including -INF) ; - * log(+INF) is +INF; log(0) is -INF with signal; - * log(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include -#include - -static const double -ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ -ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -double log(double x) -{ - union {double f; uint64_t i;} u = {x}; - double_t hfsq,f,s,z,R,w,t1,t2,dk; - uint32_t hx; - int k; - - hx = u.i>>32; - k = 0; - if (hx < 0x00100000 || hx>>31) { - if (u.i<<1 == 0) - return -1/(x*x); /* log(+-0)=-inf */ - if (hx>>31) - return (x-x)/0.0; /* log(-#) = NaN */ - /* subnormal number, scale x up */ - k -= 54; - x *= 0x1p54; - u.f = x; - hx = u.i>>32; - } else if (hx >= 0x7ff00000) { - return x; - } else if (hx == 0x3ff00000 && u.i<<32 == 0) - return 0; - - /* reduce x into [sqrt(2)/2, sqrt(2)] */ - hx += 0x3ff00000 - 0x3fe6a09e; - k += (int)(hx>>20) - 0x3ff; - hx = (hx&0x000fffff) + 0x3fe6a09e; - u.i = (uint64_t)hx<<32 | (u.i&0xffffffff); - x = u.f; - - f = x - 1.0; - hfsq = 0.5*f*f; - s = f/(2.0+f); - z = s*s; - w = z*z; - t1 = w*(Lg2+w*(Lg4+w*Lg6)); - t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - R = t2 + t1; - dk = k; - return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/log10.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/log10.c deleted file mode 100644 index bddedd68..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/log10.c +++ /dev/null @@ -1,7 +0,0 @@ -#include - -static const double _M_LN10 = 2.302585092994046; - -double log10(double x) { - return log(x) / (double)_M_LN10; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/log1p.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/log1p.c deleted file mode 100644 index 00971349..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/log1p.c +++ /dev/null @@ -1,122 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_log1p.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* double log1p(double x) - * Return the natural logarithm of 1+x. - * - * Method : - * 1. Argument Reduction: find k and f such that - * 1+x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * Note. If k=0, then f=x is exact. However, if k!=0, then f - * may not be representable exactly. In that case, a correction - * term is need. Let u=1+x rounded. Let c = (1+x)-u, then - * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), - * and add back the correction term c/u. - * (Note: when x > 2**53, one can simply return log(x)) - * - * 2. Approximation of log(1+f): See log.c - * - * 3. Finally, log1p(x) = k*ln2 + log(1+f) + c/u. See log.c - * - * Special cases: - * log1p(x) is NaN with signal if x < -1 (including -INF) ; - * log1p(+INF) is +INF; log1p(-1) is -INF with signal; - * log1p(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - * - * Note: Assuming log() return accurate answer, the following - * algorithm can be used to compute log1p(x) to within a few ULP: - * - * u = 1+x; - * if(u==1.0) return x ; else - * return log(u)*(x/(u-1.0)); - * - * See HP-15C Advanced Functions Handbook, p.193. - */ - -#include "libm.h" - -static const double -ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ -ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ -Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -double log1p(double x) -{ - union {double f; uint64_t i;} u = {x}; - double_t hfsq,f,c,s,z,R,w,t1,t2,dk; - uint32_t hx,hu; - int k; - - hx = u.i>>32; - k = 1; - if (hx < 0x3fda827a || hx>>31) { /* 1+x < sqrt(2)+ */ - if (hx >= 0xbff00000) { /* x <= -1.0 */ - if (x == -1) - return x/0.0; /* log1p(-1) = -inf */ - return (x-x)/0.0; /* log1p(x<-1) = NaN */ - } - if (hx<<1 < 0x3ca00000<<1) { /* |x| < 2**-53 */ - /* underflow if subnormal */ - if ((hx&0x7ff00000) == 0) - FORCE_EVAL((float)x); - return x; - } - if (hx <= 0xbfd2bec4) { /* sqrt(2)/2- <= 1+x < sqrt(2)+ */ - k = 0; - c = 0; - f = x; - } - } else if (hx >= 0x7ff00000) - return x; - if (k) { - u.f = 1 + x; - hu = u.i>>32; - hu += 0x3ff00000 - 0x3fe6a09e; - k = (int)(hu>>20) - 0x3ff; - /* correction term ~ log(1+x)-log(u), avoid underflow in c/u */ - if (k < 54) { - c = k >= 2 ? 1-(u.f-x) : x-(u.f-1); - c /= u.f; - } else - c = 0; - /* reduce u into [sqrt(2)/2, sqrt(2)] */ - hu = (hu&0x000fffff) + 0x3fe6a09e; - u.i = (uint64_t)hu<<32 | (u.i&0xffffffff); - f = u.f - 1; - } - hfsq = 0.5*f*f; - s = f/(2.0+f); - z = s*s; - w = z*z; - t1 = w*(Lg2+w*(Lg4+w*Lg6)); - t2 = z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - R = t2 + t1; - dk = k; - return s*(hfsq+R) + (dk*ln2_lo+c) - hfsq + f + dk*ln2_hi; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/modf.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/modf.c deleted file mode 100644 index 1c8a1db9..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/modf.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "libm.h" - -double modf(double x, double *iptr) -{ - union {double f; uint64_t i;} u = {x}; - uint64_t mask; - int e = (int)(u.i>>52 & 0x7ff) - 0x3ff; - - /* no fractional part */ - if (e >= 52) { - *iptr = x; - if (e == 0x400 && u.i<<12 != 0) /* nan */ - return x; - u.i &= 1ULL<<63; - return u.f; - } - - /* no integral part*/ - if (e < 0) { - u.i &= 1ULL<<63; - *iptr = u.f; - return x; - } - - mask = -1ULL>>12>>e; - if ((u.i & mask) == 0) { - *iptr = x; - u.i &= 1ULL<<63; - return u.f; - } - u.i &= ~mask; - *iptr = u.f; - return x - u.f; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/nearbyint.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/nearbyint.c deleted file mode 100644 index 6e9b0c1f..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/nearbyint.c +++ /dev/null @@ -1,20 +0,0 @@ -//#include -#include - -/* nearbyint is the same as rint, but it must not raise the inexact exception */ - -double nearbyint(double x) -{ -#ifdef FE_INEXACT - #pragma STDC FENV_ACCESS ON - int e; - - e = fetestexcept(FE_INEXACT); -#endif - x = rint(x); -#ifdef FE_INEXACT - if (!e) - feclearexcept(FE_INEXACT); -#endif - return x; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/pow.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/pow.c deleted file mode 100644 index 3ddc1b6f..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/pow.c +++ /dev/null @@ -1,328 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_pow.c */ -/* - * ==================================================== - * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. - * - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* pow(x,y) return x**y - * - * n - * Method: Let x = 2 * (1+f) - * 1. Compute and return log2(x) in two pieces: - * log2(x) = w1 + w2, - * where w1 has 53-24 = 29 bit trailing zeros. - * 2. Perform y*log2(x) = n+y' by simulating muti-precision - * arithmetic, where |y'|<=0.5. - * 3. Return x**y = 2**n*exp(y'*log2) - * - * Special cases: - * 1. (anything) ** 0 is 1 - * 2. 1 ** (anything) is 1 - * 3. (anything except 1) ** NAN is NAN - * 4. NAN ** (anything except 0) is NAN - * 5. +-(|x| > 1) ** +INF is +INF - * 6. +-(|x| > 1) ** -INF is +0 - * 7. +-(|x| < 1) ** +INF is +0 - * 8. +-(|x| < 1) ** -INF is +INF - * 9. -1 ** +-INF is 1 - * 10. +0 ** (+anything except 0, NAN) is +0 - * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 - * 12. +0 ** (-anything except 0, NAN) is +INF, raise divbyzero - * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF, raise divbyzero - * 14. -0 ** (+odd integer) is -0 - * 15. -0 ** (-odd integer) is -INF, raise divbyzero - * 16. +INF ** (+anything except 0,NAN) is +INF - * 17. +INF ** (-anything except 0,NAN) is +0 - * 18. -INF ** (+odd integer) is -INF - * 19. -INF ** (anything) = -0 ** (-anything), (anything except odd integer) - * 20. (anything) ** 1 is (anything) - * 21. (anything) ** -1 is 1/(anything) - * 22. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) - * 23. (-anything except 0 and inf) ** (non-integer) is NAN - * - * Accuracy: - * pow(x,y) returns x**y nearly rounded. In particular - * pow(integer,integer) - * always returns the correct integer provided it is - * representable. - * - * Constants : - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -#include "libm.h" - -static const double -bp[] = {1.0, 1.5,}, -dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ -dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ -two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ -huge = 1.0e300, -tiny = 1.0e-300, -/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ -L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ -L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ -L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ -L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ -L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ -L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ -P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ -P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ -P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ -P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ -P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ -lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ -lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ -lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ -ovt = 8.0085662595372944372e-017, /* -(1024-log2(ovfl+.5ulp)) */ -cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ -cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ -cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ -ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ -ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ -ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ - -double pow(double x, double y) -{ - double z,ax,z_h,z_l,p_h,p_l; - double y1,t1,t2,r,s,t,u,v,w; - int32_t i,j,k,yisint,n; - int32_t hx,hy,ix,iy; - uint32_t lx,ly; - - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hy, ly, y); - ix = hx & 0x7fffffff; - iy = hy & 0x7fffffff; - - /* x**0 = 1, even if x is NaN */ - if ((iy|ly) == 0) - return 1.0; - /* 1**y = 1, even if y is NaN */ - if (hx == 0x3ff00000 && lx == 0) - return 1.0; - /* NaN if either arg is NaN */ - if (ix > 0x7ff00000 || (ix == 0x7ff00000 && lx != 0) || - iy > 0x7ff00000 || (iy == 0x7ff00000 && ly != 0)) - return x + y; - - /* determine if y is an odd int when x < 0 - * yisint = 0 ... y is not an integer - * yisint = 1 ... y is an odd int - * yisint = 2 ... y is an even int - */ - yisint = 0; - if (hx < 0) { - if (iy >= 0x43400000) - yisint = 2; /* even integer y */ - else if (iy >= 0x3ff00000) { - k = (iy>>20) - 0x3ff; /* exponent */ - if (k > 20) { - uint32_t j = ly>>(52-k); - if ((j<<(52-k)) == ly) - yisint = 2 - (j&1); - } else if (ly == 0) { - uint32_t j = iy>>(20-k); - if ((j<<(20-k)) == iy) - yisint = 2 - (j&1); - } - } - } - - /* special value of y */ - if (ly == 0) { - if (iy == 0x7ff00000) { /* y is +-inf */ - if (((ix-0x3ff00000)|lx) == 0) /* (-1)**+-inf is 1 */ - return 1.0; - else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ - return hy >= 0 ? y : 0.0; - else /* (|x|<1)**+-inf = 0,inf */ - return hy >= 0 ? 0.0 : -y; - } - if (iy == 0x3ff00000) { /* y is +-1 */ - if (hy >= 0) - return x; - y = 1/x; -#if FLT_EVAL_METHOD!=0 - { - union {double f; uint64_t i;} u = {y}; - uint64_t i = u.i & -1ULL/2; - if (i>>52 == 0 && (i&(i-1))) - FORCE_EVAL((float)y); - } -#endif - return y; - } - if (hy == 0x40000000) /* y is 2 */ - return x*x; - if (hy == 0x3fe00000) { /* y is 0.5 */ - if (hx >= 0) /* x >= +0 */ - return sqrt(x); - } - } - - ax = fabs(x); - /* special value of x */ - if (lx == 0) { - if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { /* x is +-0,+-inf,+-1 */ - z = ax; - if (hy < 0) /* z = (1/|x|) */ - z = 1.0/z; - if (hx < 0) { - if (((ix-0x3ff00000)|yisint) == 0) { - z = (z-z)/(z-z); /* (-1)**non-int is NaN */ - } else if (yisint == 1) - z = -z; /* (x<0)**odd = -(|x|**odd) */ - } - return z; - } - } - - s = 1.0; /* sign of result */ - if (hx < 0) { - if (yisint == 0) /* (x<0)**(non-int) is NaN */ - return (x-x)/(x-x); - if (yisint == 1) /* (x<0)**(odd int) */ - s = -1.0; - } - - /* |y| is huge */ - if (iy > 0x41e00000) { /* if |y| > 2**31 */ - if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ - if (ix <= 0x3fefffff) - return hy < 0 ? huge*huge : tiny*tiny; - if (ix >= 0x3ff00000) - return hy > 0 ? huge*huge : tiny*tiny; - } - /* over/underflow if x is not close to one */ - if (ix < 0x3fefffff) - return hy < 0 ? s*huge*huge : s*tiny*tiny; - if (ix > 0x3ff00000) - return hy > 0 ? s*huge*huge : s*tiny*tiny; - /* now |1-x| is tiny <= 2**-20, suffice to compute - log(x) by x-x^2/2+x^3/3-x^4/4 */ - t = ax - 1.0; /* t has 20 trailing zeros */ - w = (t*t)*(0.5 - t*(0.3333333333333333333333-t*0.25)); - u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ - v = t*ivln2_l - w*ivln2; - t1 = u + v; - SET_LOW_WORD(t1, 0); - t2 = v - (t1-u); - } else { - double ss,s2,s_h,s_l,t_h,t_l; - n = 0; - /* take care subnormal number */ - if (ix < 0x00100000) { - ax *= two53; - n -= 53; - GET_HIGH_WORD(ix,ax); - } - n += ((ix)>>20) - 0x3ff; - j = ix & 0x000fffff; - /* determine interval */ - ix = j | 0x3ff00000; /* normalize ix */ - if (j <= 0x3988E) /* |x|>1)|0x20000000) + 0x00080000 + (k<<18)); - t_l = ax - (t_h-bp[k]); - s_l = v*((u-s_h*t_h)-s_h*t_l); - /* compute log(ax) */ - s2 = ss*ss; - r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); - r += s_l*(s_h+ss); - s2 = s_h*s_h; - t_h = 3.0 + s2 + r; - SET_LOW_WORD(t_h, 0); - t_l = r - ((t_h-3.0)-s2); - /* u+v = ss*(1+...) */ - u = s_h*t_h; - v = s_l*t_h + t_l*ss; - /* 2/(3log2)*(ss+...) */ - p_h = u + v; - SET_LOW_WORD(p_h, 0); - p_l = v - (p_h-u); - z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ - z_l = cp_l*p_h+p_l*cp + dp_l[k]; - /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ - t = (double)n; - t1 = ((z_h + z_l) + dp_h[k]) + t; - SET_LOW_WORD(t1, 0); - t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); - } - - /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ - y1 = y; - SET_LOW_WORD(y1, 0); - p_l = (y-y1)*t1 + y*t2; - p_h = y1*t1; - z = p_l + p_h; - EXTRACT_WORDS(j, i, z); - if (j >= 0x40900000) { /* z >= 1024 */ - if (((j-0x40900000)|i) != 0) /* if z > 1024 */ - return s*huge*huge; /* overflow */ - if (p_l + ovt > z - p_h) - return s*huge*huge; /* overflow */ - } else if ((j&0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ // FIXME: instead of abs(j) use unsigned j - if (((j-0xc090cc00)|i) != 0) /* z < -1075 */ - return s*tiny*tiny; /* underflow */ - if (p_l <= z - p_h) - return s*tiny*tiny; /* underflow */ - } - /* - * compute 2**(p_h+p_l) - */ - i = j & 0x7fffffff; - k = (i>>20) - 0x3ff; - n = 0; - if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ - n = j + (0x00100000>>(k+1)); - k = ((n&0x7fffffff)>>20) - 0x3ff; /* new k for n */ - t = 0.0; - SET_HIGH_WORD(t, n & ~(0x000fffff>>k)); - n = ((n&0x000fffff)|0x00100000)>>(20-k); - if (j < 0) - n = -n; - p_h -= t; - } - t = p_l + p_h; - SET_LOW_WORD(t, 0); - u = t*lg2_h; - v = (p_l-(t-p_h))*lg2 + t*lg2_l; - z = u + v; - w = v - (z-u); - t = z*z; - t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); - r = (z*t1)/(t1-2.0) - (w + z*w); - z = 1.0 - (r-z); - GET_HIGH_WORD(j, z); - j += n<<20; - if ((j>>20) <= 0) /* subnormal output */ - z = scalbn(z,n); - else - SET_HIGH_WORD(z, j); - return s*z; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/rint.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/rint.c deleted file mode 100644 index fbba390e..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/rint.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include - -#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 -#define EPS DBL_EPSILON -#elif FLT_EVAL_METHOD==2 -#define EPS LDBL_EPSILON -#endif -static const double_t toint = 1/EPS; - -double rint(double x) -{ - union {double f; uint64_t i;} u = {x}; - int e = u.i>>52 & 0x7ff; - int s = u.i>>63; - double_t y; - - if (e >= 0x3ff+52) - return x; - if (s) - y = x - toint + toint; - else - y = x + toint - toint; - if (y == 0) - return s ? -0.0 : 0; - return y; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/scalbn.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/scalbn.c deleted file mode 100644 index 182f5610..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/scalbn.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include - -double scalbn(double x, int n) -{ - union {double f; uint64_t i;} u; - double_t y = x; - - if (n > 1023) { - y *= 0x1p1023; - n -= 1023; - if (n > 1023) { - y *= 0x1p1023; - n -= 1023; - if (n > 1023) - n = 1023; - } - } else if (n < -1022) { - /* make sure final n < -53 to avoid double - rounding in the subnormal range */ - y *= 0x1p-1022 * 0x1p53; - n += 1022 - 53; - if (n < -1022) { - y *= 0x1p-1022 * 0x1p53; - n += 1022 - 53; - if (n < -1022) - n = -1022; - } - } - u.i = (uint64_t)(0x3ff+n)<<52; - x = y * u.f; - return x; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/sin.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/sin.c deleted file mode 100644 index 055e215b..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/sin.c +++ /dev/null @@ -1,78 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* sin(x) - * Return sine function of x. - * - * kernel function: - * __sin ... sine function on [-pi/4,pi/4] - * __cos ... cose function on [-pi/4,pi/4] - * __rem_pio2 ... argument reduction routine - * - * Method. - * Let S,C and T denote the sin, cos and tan respectively on - * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 - * in [-pi/4 , +pi/4], and let n = k mod 4. - * We have - * - * n sin(x) cos(x) tan(x) - * ---------------------------------------------------------- - * 0 S C T - * 1 C -S -1/T - * 2 -S -C T - * 3 -C S -1/T - * ---------------------------------------------------------- - * - * Special cases: - * Let trig be any of sin, cos, or tan. - * trig(+-INF) is NaN, with signals; - * trig(NaN) is that NaN; - * - * Accuracy: - * TRIG(x) returns trig(x) nearly rounded - */ - -#include "libm.h" - -double sin(double x) -{ - double y[2]; - uint32_t ix; - unsigned n; - - /* High word of x. */ - GET_HIGH_WORD(ix, x); - ix &= 0x7fffffff; - - /* |x| ~< pi/4 */ - if (ix <= 0x3fe921fb) { - if (ix < 0x3e500000) { /* |x| < 2**-26 */ - /* raise inexact if x != 0 and underflow if subnormal*/ - FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f); - return x; - } - return __sin(x, 0.0, 0); - } - - /* sin(Inf or NaN) is NaN */ - if (ix >= 0x7ff00000) - return x - x; - - /* argument reduction needed */ - n = __rem_pio2(x, y); - switch (n&3) { - case 0: return __sin(y[0], y[1], 1); - case 1: return __cos(y[0], y[1]); - case 2: return -__sin(y[0], y[1], 1); - default: - return -__cos(y[0], y[1]); - } -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/sinh.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/sinh.c deleted file mode 100644 index 00022c4e..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/sinh.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "libm.h" - -/* sinh(x) = (exp(x) - 1/exp(x))/2 - * = (exp(x)-1 + (exp(x)-1)/exp(x))/2 - * = x + x^3/6 + o(x^5) - */ -double sinh(double x) -{ - union {double f; uint64_t i;} u = {.f = x}; - uint32_t w; - double t, h, absx; - - h = 0.5; - if (u.i >> 63) - h = -h; - /* |x| */ - u.i &= (uint64_t)-1/2; - absx = u.f; - w = u.i >> 32; - - /* |x| < log(DBL_MAX) */ - if (w < 0x40862e42) { - t = expm1(absx); - if (w < 0x3ff00000) { - if (w < 0x3ff00000 - (26<<20)) - /* note: inexact and underflow are raised by expm1 */ - /* note: this branch avoids spurious underflow */ - return x; - return h*(2*t - t*t/(t+1)); - } - /* note: |x|>log(0x1p26)+eps could be just h*exp(x) */ - return h*(t + t/(t+1)); - } - - /* |x| > log(DBL_MAX) or nan */ - /* note: the result is stored to handle overflow */ - t = 2*h*__expo2(absx); - return t; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/sqrt.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/sqrt.c deleted file mode 100644 index b2775673..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/sqrt.c +++ /dev/null @@ -1,185 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_sqrt.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* sqrt(x) - * Return correctly rounded sqrt. - * ------------------------------------------ - * | Use the hardware sqrt if you have one | - * ------------------------------------------ - * Method: - * Bit by bit method using integer arithmetic. (Slow, but portable) - * 1. Normalization - * Scale x to y in [1,4) with even powers of 2: - * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then - * sqrt(x) = 2^k * sqrt(y) - * 2. Bit by bit computation - * Let q = sqrt(y) truncated to i bit after binary point (q = 1), - * i 0 - * i+1 2 - * s = 2*q , and y = 2 * ( y - q ). (1) - * i i i i - * - * To compute q from q , one checks whether - * i+1 i - * - * -(i+1) 2 - * (q + 2 ) <= y. (2) - * i - * -(i+1) - * If (2) is false, then q = q ; otherwise q = q + 2 . - * i+1 i i+1 i - * - * With some algebric manipulation, it is not difficult to see - * that (2) is equivalent to - * -(i+1) - * s + 2 <= y (3) - * i i - * - * The advantage of (3) is that s and y can be computed by - * i i - * the following recurrence formula: - * if (3) is false - * - * s = s , y = y ; (4) - * i+1 i i+1 i - * - * otherwise, - * -i -(i+1) - * s = s + 2 , y = y - s - 2 (5) - * i+1 i i+1 i i - * - * One may easily use induction to prove (4) and (5). - * Note. Since the left hand side of (3) contain only i+2 bits, - * it does not necessary to do a full (53-bit) comparison - * in (3). - * 3. Final rounding - * After generating the 53 bits result, we compute one more bit. - * Together with the remainder, we can decide whether the - * result is exact, bigger than 1/2ulp, or less than 1/2ulp - * (it will never equal to 1/2ulp). - * The rounding mode can be detected by checking whether - * huge + tiny is equal to huge, and whether huge - tiny is - * equal to huge for some floating point number "huge" and "tiny". - * - * Special cases: - * sqrt(+-0) = +-0 ... exact - * sqrt(inf) = inf - * sqrt(-ve) = NaN ... with invalid signal - * sqrt(NaN) = NaN ... with invalid signal for signaling NaN - */ - -#include "libm.h" - -static const double tiny = 1.0e-300; - -double sqrt(double x) -{ - double z; - int32_t sign = (int)0x80000000; - int32_t ix0,s0,q,m,t,i; - uint32_t r,t1,s1,ix1,q1; - - EXTRACT_WORDS(ix0, ix1, x); - - /* take care of Inf and NaN */ - if ((ix0&0x7ff00000) == 0x7ff00000) { - return x*x + x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf, sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if (ix0 <= 0) { - if (((ix0&~sign)|ix1) == 0) - return x; /* sqrt(+-0) = +-0 */ - if (ix0 < 0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = ix0>>20; - if (m == 0) { /* subnormal x */ - while (ix0 == 0) { - m -= 21; - ix0 |= (ix1>>11); - ix1 <<= 21; - } - for (i=0; (ix0&0x00100000) == 0; i++) - ix0<<=1; - m -= i - 1; - ix0 |= ix1>>(32-i); - ix1 <<= i; - } - m -= 1023; /* unbias exponent */ - ix0 = (ix0&0x000fffff)|0x00100000; - if (m & 1) { /* odd m, double x to make it even */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ - r = 0x00200000; /* r = moving bit from right to left */ - - while (r != 0) { - t = s0 + r; - if (t <= ix0) { - s0 = t + r; - ix0 -= t; - q += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r >>= 1; - } - - r = sign; - while (r != 0) { - t1 = s1 + r; - t = s0; - if (t < ix0 || (t == ix0 && t1 <= ix1)) { - s1 = t1 + r; - if ((t1&sign) == sign && (s1&sign) == 0) - s0++; - ix0 -= t; - if (ix1 < t1) - ix0--; - ix1 -= t1; - q1 += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r >>= 1; - } - - /* use floating add to find out rounding direction */ - if ((ix0|ix1) != 0) { - z = 1.0 - tiny; /* raise inexact flag */ - if (z >= 1.0) { - z = 1.0 + tiny; - if (q1 == (uint32_t)0xffffffff) { - q1 = 0; - q++; - } else if (z > 1.0) { - if (q1 == (uint32_t)0xfffffffe) - q++; - q1 += 2; - } else - q1 += q1 & 1; - } - } - ix0 = (q>>1) + 0x3fe00000; - ix1 = q1>>1; - if (q&1) - ix1 |= sign; - ix0 += m << 20; - INSERT_WORDS(z, ix0, ix1); - return z; -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/tan.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/tan.c deleted file mode 100644 index 9c724a45..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/tan.c +++ /dev/null @@ -1,70 +0,0 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_tan.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* tan(x) - * Return tangent function of x. - * - * kernel function: - * __tan ... tangent function on [-pi/4,pi/4] - * __rem_pio2 ... argument reduction routine - * - * Method. - * Let S,C and T denote the sin, cos and tan respectively on - * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 - * in [-pi/4 , +pi/4], and let n = k mod 4. - * We have - * - * n sin(x) cos(x) tan(x) - * ---------------------------------------------------------- - * 0 S C T - * 1 C -S -1/T - * 2 -S -C T - * 3 -C S -1/T - * ---------------------------------------------------------- - * - * Special cases: - * Let trig be any of sin, cos, or tan. - * trig(+-INF) is NaN, with signals; - * trig(NaN) is that NaN; - * - * Accuracy: - * TRIG(x) returns trig(x) nearly rounded - */ - -#include "libm.h" - -double tan(double x) -{ - double y[2]; - uint32_t ix; - unsigned n; - - GET_HIGH_WORD(ix, x); - ix &= 0x7fffffff; - - /* |x| ~< pi/4 */ - if (ix <= 0x3fe921fb) { - if (ix < 0x3e400000) { /* |x| < 2**-27 */ - /* raise inexact if x!=0 and underflow if subnormal */ - FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f); - return x; - } - return __tan(x, 0.0, 0); - } - - /* tan(Inf or NaN) is NaN */ - if (ix >= 0x7ff00000) - return x - x; - - /* argument reduction */ - n = __rem_pio2(x, y); - return __tan(y[0], y[1], n&1); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/tanh.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/tanh.c deleted file mode 100644 index 89743ba9..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/tanh.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -double tanh(double x) { - return sinh(x) / cosh(x); -} diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/tgamma.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/tgamma.c deleted file mode 100644 index d1d0a048..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/tgamma.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -"A Precision Approximation of the Gamma Function" - Cornelius Lanczos (1964) -"Lanczos Implementation of the Gamma Function" - Paul Godfrey (2001) -"An Analysis of the Lanczos Gamma Approximation" - Glendon Ralph Pugh (2004) - -approximation method: - - (x - 0.5) S(x) -Gamma(x) = (x + g - 0.5) * ---------------- - exp(x + g - 0.5) - -with - a1 a2 a3 aN -S(x) ~= [ a0 + ----- + ----- + ----- + ... + ----- ] - x + 1 x + 2 x + 3 x + N - -with a0, a1, a2, a3,.. aN constants which depend on g. - -for x < 0 the following reflection formula is used: - -Gamma(x)*Gamma(-x) = -pi/(x sin(pi x)) - -most ideas and constants are from boost and python -*/ -#include "libm.h" - -static const double pi = 3.141592653589793238462643383279502884; - -/* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */ -static double sinpi(double x) -{ - int n; - - /* argument reduction: x = |x| mod 2 */ - /* spurious inexact when x is odd int */ - x = x * 0.5; - x = 2 * (x - floor(x)); - - /* reduce x into [-.25,.25] */ - n = 4 * x; - n = (n+1)/2; - x -= n * 0.5; - - x *= pi; - switch (n) { - default: /* case 4 */ - case 0: - return __sin(x, 0, 0); - case 1: - return __cos(x, 0); - case 2: - return __sin(-x, 0, 0); - case 3: - return -__cos(x, 0); - } -} - -#define N 12 -//static const double g = 6.024680040776729583740234375; -static const double gmhalf = 5.524680040776729583740234375; -static const double Snum[N+1] = { - 23531376880.410759688572007674451636754734846804940, - 42919803642.649098768957899047001988850926355848959, - 35711959237.355668049440185451547166705960488635843, - 17921034426.037209699919755754458931112671403265390, - 6039542586.3520280050642916443072979210699388420708, - 1439720407.3117216736632230727949123939715485786772, - 248874557.86205415651146038641322942321632125127801, - 31426415.585400194380614231628318205362874684987640, - 2876370.6289353724412254090516208496135991145378768, - 186056.26539522349504029498971604569928220784236328, - 8071.6720023658162106380029022722506138218516325024, - 210.82427775157934587250973392071336271166969580291, - 2.5066282746310002701649081771338373386264310793408, -}; -static const double Sden[N+1] = { - 0, 39916800, 120543840, 150917976, 105258076, 45995730, 13339535, - 2637558, 357423, 32670, 1925, 66, 1, -}; -/* n! for small integer n */ -static const double fact[] = { - 1, 1, 2, 6, 24, 120, 720, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0, - 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0, - 355687428096000.0, 6402373705728000.0, 121645100408832000.0, - 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0, -}; - -/* S(x) rational function for positive x */ -static double S(double x) -{ - double_t num = 0, den = 0; - int i; - - /* to avoid overflow handle large x differently */ - if (x < 8) - for (i = N; i >= 0; i--) { - num = num * x + Snum[i]; - den = den * x + Sden[i]; - } - else - for (i = 0; i <= N; i++) { - num = num / x + Snum[i]; - den = den / x + Sden[i]; - } - return num/den; -} - -double tgamma(double x) -{ - union {double f; uint64_t i;} u = {x}; - double absx, y; - double_t dy, z, r; - uint32_t ix = u.i>>32 & 0x7fffffff; - int sign = u.i>>63; - - /* special cases */ - if (ix >= 0x7ff00000) - /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */ - return x + INFINITY; - if (ix < (0x3ff-54)<<20) - /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */ - return 1/x; - - /* integer arguments */ - /* raise inexact when non-integer */ - if (x == floor(x)) { - if (sign) - return 0/0.0; - if (x <= sizeof fact/sizeof *fact) - return fact[(int)x - 1]; - } - - /* x >= 172: tgamma(x)=inf with overflow */ - /* x =< -184: tgamma(x)=+-0 with underflow */ - if (ix >= 0x40670000) { /* |x| >= 184 */ - if (sign) { - FORCE_EVAL((float)(0x1p-126/x)); - if (floor(x) * 0.5 == floor(x * 0.5)) - return 0; - return -0.0; - } - x *= 0x1p1023; - return x; - } - - absx = sign ? -x : x; - - /* handle the error of x + g - 0.5 */ - y = absx + gmhalf; - if (absx > gmhalf) { - dy = y - absx; - dy -= gmhalf; - } else { - dy = y - gmhalf; - dy -= absx; - } - - z = absx - 0.5; - r = S(absx) * exp(-y); - if (x < 0) { - /* reflection formula for negative x */ - /* sinpi(absx) is not 0, integers are already handled */ - r = -pi / (sinpi(absx) * absx * r); - dy = -dy; - z = -z; - } - r += dy * (gmhalf+0.5) * r / y; - z = pow(y, 0.5*z); - y = r * z * z; - return y; -} - -#if 1 -double __lgamma_r(double x, int *sign) -{ - double r, absx; - - *sign = 1; - - /* special cases */ - if (!isfinite(x)) - /* lgamma(nan)=nan, lgamma(+-inf)=inf */ - return x*x; - - /* integer arguments */ - if (x == floor(x) && x <= 2) { - /* n <= 0: lgamma(n)=inf with divbyzero */ - /* n == 1,2: lgamma(n)=0 */ - if (x <= 0) - return 1/0.0; - return 0; - } - - absx = fabs(x); - - /* lgamma(x) ~ -log(|x|) for tiny |x| */ - if (absx < 0x1p-54) { - *sign = 1 - 2*!!signbit(x); - return -log(absx); - } - - /* use tgamma for smaller |x| */ - if (absx < 128) { - x = tgamma(x); - *sign = 1 - 2*!!signbit(x); - return log(fabs(x)); - } - - /* second term (log(S)-g) could be more precise here.. */ - /* or with stirling: (|x|-0.5)*(log(|x|)-1) + poly(1/|x|) */ - r = (absx-0.5)*(log(absx+gmhalf)-1) + (log(S(absx)) - (gmhalf+0.5)); - if (x < 0) { - /* reflection formula for negative x */ - x = sinpi(absx); - *sign = 2*!!signbit(x) - 1; - r = log(pi/(fabs(x)*absx)) - r; - } - return r; -} - -//weak_alias(__lgamma_r, lgamma_r); -#endif diff --git a/MicroPython_BUILD/components/micropython/lib/libm_dbl/trunc.c b/MicroPython_BUILD/components/micropython/lib/libm_dbl/trunc.c deleted file mode 100644 index d13711b5..00000000 --- a/MicroPython_BUILD/components/micropython/lib/libm_dbl/trunc.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "libm.h" - -double trunc(double x) -{ - union {double f; uint64_t i;} u = {x}; - int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12; - uint64_t m; - - if (e >= 52 + 12) - return x; - if (e < 12) - e = 1; - m = -1ULL >> e; - if ((u.i & m) == 0) - return x; - FORCE_EVAL(x + 0x1p120f); - u.i &= ~m; - return u.f; -} diff --git a/MicroPython_BUILD/components/micropython/lib/memzip/README.md b/MicroPython_BUILD/components/micropython/lib/memzip/README.md deleted file mode 100644 index 287d0fc4..00000000 --- a/MicroPython_BUILD/components/micropython/lib/memzip/README.md +++ /dev/null @@ -1,28 +0,0 @@ -MEMZIP - a simple readonly file system - -memzip takes a zip file which is comprised of uncompressed files and -and presents it as a filesystem, allowing Python files to be imported. - -The script make-memzip.py takes a directory name and will create a zip file -containing uncompressed files found in the directory. It will then generate -a C file which contains the data from the zip file. - -A typical addition to a makefile would look like: -``` -SRC_C += \ - lib/memzip/import.c \ - lib/memzip/lexermemzip.c \ - lib/memzip/memzip.c \ - -OBJ += $(BUILD)/memzip-files.o - -MAKE_MEMZIP = ../lib/memzip/make-memzip.py - -$(BUILD)/memzip-files.o: $(BUILD)/memzip-files.c - $(call compile_c) - -$(BUILD)/memzip-files.c: $(shell find ${MEMZIP_DIR} -type f) - @$(ECHO) "Creating $@" - $(Q)$(PYTHON) $(MAKE_MEMZIP) --zip-file $(BUILD)/memzip-files.zip --c-file $@ $(MEMZIP_DIR) -``` - diff --git a/MicroPython_BUILD/components/micropython/lib/memzip/import.c b/MicroPython_BUILD/components/micropython/lib/memzip/import.c deleted file mode 100644 index 2d5225b8..00000000 --- a/MicroPython_BUILD/components/micropython/lib/memzip/import.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -#include "py/lexer.h" -#include "memzip.h" - -mp_import_stat_t mp_import_stat(const char *path) { - MEMZIP_FILE_INFO info; - - if (memzip_stat(path, &info) != MZ_OK) { - return MP_IMPORT_STAT_NO_EXIST; - } - - if (info.is_dir) { - return MP_IMPORT_STAT_DIR; - } - return MP_IMPORT_STAT_FILE; -} diff --git a/MicroPython_BUILD/components/micropython/lib/memzip/lexermemzip.c b/MicroPython_BUILD/components/micropython/lib/memzip/lexermemzip.c deleted file mode 100644 index 6b26961b..00000000 --- a/MicroPython_BUILD/components/micropython/lib/memzip/lexermemzip.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#include "py/lexer.h" -#include "py/runtime.h" -#include "py/mperrno.h" -#include "memzip.h" - -mp_lexer_t *mp_lexer_new_from_file(const char *filename) -{ - void *data; - size_t len; - - if (memzip_locate(filename, &data, &len) != MZ_OK) { - mp_raise_OSError(MP_ENOENT); - } - - return mp_lexer_new_from_str_len(qstr_from_str(filename), (const char *)data, (mp_uint_t)len, 0); -} - diff --git a/MicroPython_BUILD/components/micropython/lib/memzip/make-memzip.py b/MicroPython_BUILD/components/micropython/lib/memzip/make-memzip.py deleted file mode 100755 index 9730f5e0..00000000 --- a/MicroPython_BUILD/components/micropython/lib/memzip/make-memzip.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# -# Takes a directory of files and zips them up (as uncompressed files). -# This then gets converted into a C data structure which can be read -# like a filesystem at runtime. -# -# This is somewhat like frozen modules in python, but allows arbitrary files -# to be used. - -from __future__ import print_function - -import argparse -import os -import subprocess -import sys -import types - -def create_zip(zip_filename, zip_dir): - abs_zip_filename = os.path.abspath(zip_filename) - save_cwd = os.getcwd() - os.chdir(zip_dir) - if os.path.exists(abs_zip_filename): - os.remove(abs_zip_filename) - subprocess.check_call(['zip', '-0', '-r', '-D', abs_zip_filename, '.']) - os.chdir(save_cwd) - -def create_c_from_file(c_filename, zip_filename): - with open(zip_filename, 'rb') as zip_file: - with open(c_filename, 'wb') as c_file: - print('#include ', file=c_file) - print('', file=c_file) - print('const uint8_t memzip_data[] = {', file=c_file) - while True: - buf = zip_file.read(16) - if not buf: - break - print(' ', end='', file=c_file) - for byte in buf: - if type(byte) is types.StringType: - print(' 0x{:02x},'.format(ord(byte)), end='', file=c_file) - else: - print(' 0x{:02x},'.format(byte), end='', file=c_file) - print('', file=c_file) - print('};', file=c_file) - -def main(): - parser = argparse.ArgumentParser( - prog='make-memzip.py', - usage='%(prog)s [options] [command]', - description='Generates a C source memzip file.' - ) - parser.add_argument( - '-z', '--zip-file', - dest='zip_filename', - help='Specifies the name of the created zip file.', - default='memzip_files.zip' - ) - parser.add_argument( - '-c', '--c-file', - dest='c_filename', - help='Specifies the name of the created C source file.', - default='memzip_files.c' - ) - parser.add_argument( - dest='source_dir', - default='memzip_files' - ) - args = parser.parse_args(sys.argv[1:]) - - print('args.zip_filename =', args.zip_filename) - print('args.c_filename =', args.c_filename) - print('args.source_dir =', args.source_dir) - - create_zip(args.zip_filename, args.source_dir) - create_c_from_file(args.c_filename, args.zip_filename) - -if __name__ == "__main__": - main() - diff --git a/MicroPython_BUILD/components/micropython/lib/memzip/memzip.c b/MicroPython_BUILD/components/micropython/lib/memzip/memzip.c deleted file mode 100644 index 3fbea8e1..00000000 --- a/MicroPython_BUILD/components/micropython/lib/memzip/memzip.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include -#include "py/mpconfig.h" -#include "py/misc.h" -#include "memzip.h" - -extern uint8_t memzip_data[]; - -const MEMZIP_FILE_HDR *memzip_find_file_header(const char *filename) { - - const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)memzip_data; - uint8_t *mem_data; - - /* Zip file filenames don't have a leading /, so we strip it off */ - - if (*filename == '/') { - filename++; - } - while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) { - const char *file_hdr_filename = (const char *)&file_hdr[1]; - mem_data = (uint8_t *)file_hdr_filename; - mem_data += file_hdr->filename_len; - mem_data += file_hdr->extra_len; - if (!strncmp(file_hdr_filename, filename, file_hdr->filename_len)) { - /* We found a match */ - return file_hdr; - } - mem_data += file_hdr->uncompressed_size; - file_hdr = (const MEMZIP_FILE_HDR *)mem_data; - } - return NULL; -} - -bool memzip_is_dir(const char *filename) { - const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)memzip_data; - uint8_t *mem_data; - - if (strcmp(filename, "/") == 0) { - // The root directory is a directory. - return true; - } - - // Zip filenames don't have a leading /, so we strip it off - if (*filename == '/') { - filename++; - } - size_t filename_len = strlen(filename); - - while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) { - const char *file_hdr_filename = (const char *)&file_hdr[1]; - if (filename_len < file_hdr->filename_len && - strncmp(file_hdr_filename, filename, filename_len) == 0 && - file_hdr_filename[filename_len] == '/') { - return true; - } - - mem_data = (uint8_t *)file_hdr_filename; - mem_data += file_hdr->filename_len; - mem_data += file_hdr->extra_len; - mem_data += file_hdr->uncompressed_size; - file_hdr = (const MEMZIP_FILE_HDR *)mem_data; - } - return NULL; - -} - -MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len) -{ - const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(filename); - if (file_hdr == NULL) { - return MZ_NO_FILE; - } - if (file_hdr->compression_method != 0) { - return MZ_FILE_COMPRESSED; - } - - uint8_t *mem_data; - mem_data = (uint8_t *)&file_hdr[1]; - mem_data += file_hdr->filename_len; - mem_data += file_hdr->extra_len; - - *data = mem_data; - *len = file_hdr->uncompressed_size; - return MZ_OK; -} - -MEMZIP_RESULT memzip_stat(const char *path, MEMZIP_FILE_INFO *info) { - const MEMZIP_FILE_HDR *file_hdr = memzip_find_file_header(path); - if (file_hdr == NULL) { - if (memzip_is_dir(path)) { - info->file_size = 0; - info->last_mod_date = 0; - info->last_mod_time = 0; - info->is_dir = 1; - return MZ_OK; - } - return MZ_NO_FILE; - } - info->file_size = file_hdr->uncompressed_size; - info->last_mod_date = file_hdr->last_mod_date; - info->last_mod_time = file_hdr->last_mod_time; - info->is_dir = 0; - - return MZ_OK; -} diff --git a/MicroPython_BUILD/components/micropython/lib/memzip/memzip.h b/MicroPython_BUILD/components/micropython/lib/memzip/memzip.h deleted file mode 100644 index 667e2df7..00000000 --- a/MicroPython_BUILD/components/micropython/lib/memzip/memzip.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma pack(push, 1) - -#define MEMZIP_FILE_HEADER_SIGNATURE 0x04034b50 -typedef struct -{ - uint32_t signature; - uint16_t version; - uint16_t flags; - uint16_t compression_method; - uint16_t last_mod_time; - uint16_t last_mod_date; - uint32_t crc32; - uint32_t compressed_size; - uint32_t uncompressed_size; - uint16_t filename_len; - uint16_t extra_len; - - /* char filename[filename_len] */ - /* uint8_t extra[extra_len] */ - -} MEMZIP_FILE_HDR; - -#define MEMZIP_CENTRAL_DIRECTORY_SIGNATURE 0x02014b50 -typedef struct -{ - uint32_t signature; - uint16_t version_made_by; - uint16_t version_read_with; - uint16_t flags; - uint16_t compression_method; - uint16_t last_mod_time; - uint16_t last_mod_date; - uint32_t crc32; - uint32_t compressed_size; - uint32_t uncompressed_size; - uint16_t filename_len; - uint16_t extra_len; - uint16_t disk_num; - uint16_t internal_file_attributes; - uint32_t external_file_attributes; - uint32_t file_header_offset; - - /* char filename[filename_len] */ - /* uint8_t extra[extra_len] */ - -} MEMZIP_CENTRAL_DIRECTORY_HDR; - -#define MEMZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE 0x06054b50 -typedef struct -{ - uint32_t signature; - uint16_t disk_num; - uint16_t central_directory_disk; - uint16_t num_central_directories_this_disk; - uint16_t total_central_directories; - uint32_t central_directory_size; - uint32_t central_directory_offset; - uint16_t comment_len; - - /* char comment[comment_len] */ - -} MEMZIP_END_OF_CENTRAL_DIRECTORY; - -#pragma pack(pop) - -typedef enum { - MZ_OK = 0, /* (0) Succeeded */ - MZ_NO_FILE, /* (1) Could not find the file. */ - MZ_FILE_COMPRESSED, /* (2) File is compressed (expecting uncompressed) */ - -} MEMZIP_RESULT; - -typedef struct { - uint32_t file_size; - uint16_t last_mod_date; - uint16_t last_mod_time; - uint8_t is_dir; - -} MEMZIP_FILE_INFO; - -MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len); - -MEMZIP_RESULT memzip_stat(const char *path, MEMZIP_FILE_INFO *info); diff --git a/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c b/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c index 074f5530..93c38e67 100644 --- a/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c +++ b/MicroPython_BUILD/components/micropython/lib/mp-readline/readline.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c b/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c index 06c3ff9b..073f46b1 100644 --- a/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c +++ b/MicroPython_BUILD/components/micropython/lib/netutils/netutils.c @@ -41,7 +41,7 @@ mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) { } else { ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); } - return mp_obj_new_str(ip_str, ip_len, false); + return mp_obj_new_str(ip_str, ip_len); } // Takes an array with a raw IP address, and a port, and returns a net-address diff --git a/MicroPython_BUILD/components/micropython/lib/utils/printf.c b/MicroPython_BUILD/components/micropython/lib/utils/printf.c deleted file mode 100644 index 51dfa5b9..00000000 --- a/MicroPython_BUILD/components/micropython/lib/utils/printf.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * 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 "py/mpconfig.h" - -#if MICROPY_USE_INTERNAL_PRINTF - -#include -#include -#include - -#include "py/obj.h" -#include "py/mphal.h" - -#if MICROPY_PY_BUILTINS_FLOAT -#include "py/formatfloat.h" -#endif - -#undef putchar // Some stdlibs have a #define for putchar -int printf(const char *fmt, ...); -int vprintf(const char *fmt, va_list ap); -int putchar(int c); -int puts(const char *s); -int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); -int snprintf(char *str, size_t size, const char *fmt, ...); - -int printf(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - int ret = mp_vprintf(&mp_plat_print, fmt, ap); - va_end(ap); - return ret; -} - -int vprintf(const char *fmt, va_list ap) { - return mp_vprintf(&mp_plat_print, fmt, ap); -} - -#if MICROPY_DEBUG_PRINTERS -int DEBUG_printf(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - #ifndef MICROPY_DEBUG_PRINTER_DEST - #define MICROPY_DEBUG_PRINTER_DEST mp_plat_print - #endif - extern const mp_print_t MICROPY_DEBUG_PRINTER_DEST; - int ret = mp_vprintf(&MICROPY_DEBUG_PRINTER_DEST, fmt, ap); - va_end(ap); - return ret; -} -#endif - -// need this because gcc optimises printf("%c", c) -> putchar(c), and printf("a") -> putchar('a') -int putchar(int c) { - char chr = c; - mp_hal_stdout_tx_strn_cooked(&chr, 1); - return chr; -} - -// need this because gcc optimises printf("string\n") -> puts("string") -int puts(const char *s) { - mp_hal_stdout_tx_strn_cooked(s, strlen(s)); - char chr = '\n'; - mp_hal_stdout_tx_strn_cooked(&chr, 1); - return 1; -} - -typedef struct _strn_print_env_t { - char *cur; - size_t remain; -} strn_print_env_t; - -STATIC void strn_print_strn(void *data, const char *str, size_t len) { - strn_print_env_t *strn_print_env = data; - if (len > strn_print_env->remain) { - len = strn_print_env->remain; - } - memcpy(strn_print_env->cur, str, len); - strn_print_env->cur += len; - strn_print_env->remain -= len; -} - -#if defined(__GNUC__) && !defined(__clang__) -// uClibc requires this alias to be defined, or there may be link errors -// when linkings against it statically. -int __GI_vsnprintf(char *str, size_t size, const char *fmt, va_list ap) __attribute__((weak, alias ("vsnprintf"))); -#endif - -int vsnprintf(char *str, size_t size, const char *fmt, va_list ap) { - strn_print_env_t strn_print_env = {str, size}; - mp_print_t print = {&strn_print_env, strn_print_strn}; - int len = mp_vprintf(&print, fmt, ap); - // add terminating null byte - if (size > 0) { - if (strn_print_env.remain == 0) { - strn_print_env.cur[-1] = 0; - } else { - strn_print_env.cur[0] = 0; - } - } - return len; -} - -int snprintf(char *str, size_t size, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - int ret = vsnprintf(str, size, fmt, ap); - va_end(ap); - return ret; -} - -#endif //MICROPY_USE_INTERNAL_PRINTF diff --git a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c index 07377c28..1793a4f1 100644 --- a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c +++ b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,13 +36,14 @@ #include "py/gc.h" #include "py/frozenmod.h" #include "py/mphal.h" -#if defined(USE_DEVICE_MODE) +#if MICROPY_HW_ENABLE_USB #include "irq.h" #include "usb.h" #endif #include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "mpversion.h" +#include "modmachine.h" pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; int pyexec_system_exit = 0; @@ -138,7 +140,7 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input #if MICROPY_ENABLE_GC // run collection and print GC info - gc_collect(); + gc_collect(1); gc_dump_info(); #endif } @@ -346,6 +348,13 @@ int pyexec_raw_repl(void) { vstr_reset(&line); } else if (c == CHAR_CTRL_D) { // input finished + if (line.len == 0) { + // In raw_repl we only SIMULATE the reboot + // This is used by some applications like RSHELL + mp_hal_stdout_tx_str("soft reboot\r\n"); + vTaskDelay(500); + goto raw_repl_reset; + } break; } else { // let through any other raw 8-bit value @@ -368,6 +377,7 @@ int pyexec_raw_repl(void) { return ret; } } + return 0; } int pyexec_friendly_repl(void) { @@ -408,7 +418,7 @@ int pyexec_friendly_repl(void) { for (;;) { input_restart: - #if defined(USE_DEVICE_MODE) + #if MICROPY_HW_ENABLE_USB if (usb_vcp_is_enabled()) { // If the user gets to here and interrupts are disabled then // they'll never see the prompt, traceback etc. The USB REPL needs @@ -442,7 +452,10 @@ int pyexec_friendly_repl(void) { } else if (ret == CHAR_CTRL_D) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); - vstr_clear(&line); + // No need to return, we can reset here + prepareSleepReset(0, "ESP32: soft reboot\r\n"); + esp_restart(); // no return !! + //vstr_clear(&line); return PYEXEC_FORCED_EXIT; } else if (ret == CHAR_CTRL_E) { // paste mode @@ -465,7 +478,7 @@ int pyexec_friendly_repl(void) { if (c == '\r') { mp_hal_stdout_tx_str("\r\n=== "); } else { - mp_hal_stdout_tx_strn(&c, 1); + mp_hal_stdout_tx_strn((const char *)&c, 1); } } } @@ -493,6 +506,7 @@ int pyexec_friendly_repl(void) { return ret; } } + return 0; } #endif // MICROPY_REPL_EVENT_DRIVEN diff --git a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h index bc98ba94..678c56cf 100644 --- a/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h +++ b/MicroPython_BUILD/components/micropython/lib/utils/pyexec.h @@ -26,6 +26,8 @@ #ifndef MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H #define MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H +#include "py/obj.h" + typedef enum { PYEXEC_MODE_RAW_REPL, PYEXEC_MODE_FRIENDLY_REPL, diff --git a/MicroPython_BUILD/components/micropython/lib/utils/stdout_helpers.c b/MicroPython_BUILD/components/micropython/lib/utils/stdout_helpers.c deleted file mode 100644 index 3de11975..00000000 --- a/MicroPython_BUILD/components/micropython/lib/utils/stdout_helpers.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include "py/mpconfig.h" -#include "py/mphal.h" - -/* - * Extra stdout functions - * These can be either optimized for a particular port, or reference - * implementation below can be used. - */ - -// Send "cooked" string of given length, where every occurrence of -// LF character is replaced with CR LF. -void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { - while (len--) { - if (*str == '\n') { - mp_hal_stdout_tx_strn("\r", 1); - } - mp_hal_stdout_tx_strn(str++, 1); - } -} - -// Send zero-terminated string -void mp_hal_stdout_tx_str(const char *str) { - mp_hal_stdout_tx_strn(str, strlen(str)); -} diff --git a/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c b/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c index 2eb73f66..a9f57f3a 100644 --- a/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c +++ b/MicroPython_BUILD/components/micropython/lib/utils/sys_stdio_mphal.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/mpconfigport.h b/MicroPython_BUILD/components/micropython/mpconfigport.h new file mode 100644 index 00000000..57e644a4 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/mpconfigport.h @@ -0,0 +1,424 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * 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. + */ + +// Options to control how MicroPython is built for this port, +// overriding defaults in py/mpconfig.h. + +#include +#include +#include "rom/ets_sys.h" +#include "sdkconfig.h" + +// ------------------------------------------------------------ +// For testing only, don't change unless you want to experiment +// ------------------------------------------------------------ +// Don't use alloca calls. As alloca() is not part of ANSI C, this +// workaround option is provided for compilers lacking this de-facto +// standard function. The way it works is allocating from heap, and +// relying on garbage collection to free it eventually. This is of +// course much less optimal than real alloca(). +#define MICROPY_NO_ALLOCA (0) +// Avoid using C stack when making Python function calls. +// C stack still may be used if there's no free heap. +#define MICROPY_STACKLESS (0) +// Never use C stack when making Python function calls. +#define MICROPY_STACKLESS_STRICT (0) +// Whether to build functions that print debugging info: +// mp_bytecode_print +// mp_parse_node_print +#define MICROPY_DEBUG_PRINTERS (0) +// ------------------------------------------------------------ + +// object representation and NLR handling +#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) +#define MICROPY_NLR_SETJMP (1) + +// memory allocation policies +#define MICROPY_ALLOC_PATH_MAX (128) + +// emitters +#define MICROPY_PERSISTENT_CODE_LOAD (1) +#define MICROPY_EMIT_XTENSA (0) + +// compiler configuration +#define MICROPY_COMP_MODULE_CONST (1) +#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) + +// optimizations +#define MICROPY_OPT_COMPUTED_GOTO (1) +#define MICROPY_OPT_MPZ_BITWISE (1) + +// Python internal features +// Whether to return number of collected objects from gc.collect() +#ifdef CONFIG_MICROPY_GC_COLLECT_RETVAL +#define MICROPY_PY_GC_COLLECT_RETVAL (1) +#else +#define MICROPY_PY_GC_COLLECT_RETVAL (0) +#endif +#define MICROPY_READER_VFS (1) +#define MICROPY_ENABLE_GC (1) +// Be conservative and always clear to zero newly (re)allocated memory in the GC. +// This helps eliminate stray pointers that hold on to memory that's no longer used. +// It decreases performance due to unnecessary memory clearing. +#define MICROPY_GC_CONSERVATIVE_CLEAR (1) +// Whether to enable finalisers in the garbage collector (ie call __del__) +#ifdef CONFIG_MICROPY_ENABLE_FINALISER +#define MICROPY_ENABLE_FINALISER (1) +#else +#define MICROPY_ENABLE_FINALISER (0) +#endif +#define MICROPY_STACK_CHECK (1) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_EMACS_KEYS (1) +#define MICROPY_REPL_AUTO_INDENT (1) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +//#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) +#define MICROPY_ENABLE_SOURCE_LINE (1) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL) +#define MICROPY_WARNINGS (1) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) +#define MICROPY_PY_BUILTINS_COMPLEX (1) +#define MICROPY_CPYTHON_COMPAT (1) +#define MICROPY_STREAMS_NON_BLOCK (1) +#define MICROPY_STREAMS_POSIX_API (1) +#define MICROPY_MODULE_BUILTIN_INIT (1) +#define MICROPY_MODULE_WEAK_LINKS (1) +#define MICROPY_MODULE_FROZEN_STR (0) // do not support frozen str modules +#define MICROPY_MODULE_FROZEN_MPY (1) +#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool +#define MICROPY_CAN_OVERRIDE_BUILTINS (1) +#define MICROPY_USE_INTERNAL_ERRNO (1) +#define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf, do NOT change +#define MICROPY_ENABLE_SCHEDULER (1) // Do NOT change +// Maximum number of entries in the scheduler +#define MICROPY_SCHEDULER_DEPTH (CONFIG_MICROPY_SCHEDULER_DEPTH) + +#define MICROPY_VFS (1) // !! DO NOT CHANGE, MUST BE 1 !! +#define MICROPY_VFS_FAT (0) // !! DO NOT CHANGE, NOT USED !! + +// control over Python builtins +#define MICROPY_PY_FUNCTION_ATTRS (1) +#define MICROPY_PY_STR_BYTES_CMP_WARN (1) +#ifdef CONFIG_MICROPY_USE_UNICODE +#define MICROPY_PY_BUILTINS_STR_UNICODE (1) +#else +#define MICROPY_PY_BUILTINS_STR_UNICODE (0) +#endif +#define MICROPY_PY_BUILTINS_STR_CENTER (1) +#define MICROPY_PY_BUILTINS_STR_PARTITION (1) +#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) +#define MICROPY_PY_BUILTINS_BYTEARRAY (1) +#define MICROPY_PY_BUILTINS_MEMORYVIEW (1) +#define MICROPY_PY_BUILTINS_SET (1) +#define MICROPY_PY_BUILTINS_SLICE (1) +#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) +#define MICROPY_PY_BUILTINS_FROZENSET (1) +#define MICROPY_PY_BUILTINS_PROPERTY (1) +#define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) +#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1) +#define MICROPY_PY_ALL_SPECIAL_METHODS (1) +#define MICROPY_PY_BUILTINS_COMPILE (1) +#define MICROPY_PY_BUILTINS_ENUMERATE (1) +#define MICROPY_PY_BUILTINS_EXECFILE (1) +#define MICROPY_PY_BUILTINS_FILTER (1) +#define MICROPY_PY_BUILTINS_REVERSED (1) +#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) +#define MICROPY_PY_BUILTINS_INPUT (1) +#define MICROPY_PY_BUILTINS_MIN_MAX (1) +#define MICROPY_PY_BUILTINS_POW3 (1) +#define MICROPY_PY_BUILTINS_HELP (1) +#define MICROPY_PY_BUILTINS_HELP_TEXT esp32_help_text +#define MICROPY_PY_BUILTINS_HELP_MODULES (1) +#define MICROPY_PY___FILE__ (1) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) +#define MICROPY_PY_ARRAY (1) +#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_PY_ATTRTUPLE (1) +#define MICROPY_PY_COLLECTIONS (1) +#define MICROPY_PY_COLLECTIONS_DEQUE (1) +#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) +#define MICROPY_PY_MATH (1) +#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1) +#define MICROPY_PY_CMATH (1) +#define MICROPY_PY_GC (1) +#define MICROPY_PY_IO (1) +#define MICROPY_PY_IO_FILEIO (1) +#define MICROPY_PY_IO_BYTESIO (1) +#define MICROPY_PY_IO_BUFFEREDWRITER (1) +#define MICROPY_PY_STRUCT (1) +#define MICROPY_PY_SYS (1) +#define MICROPY_PY_SYS_MAXSIZE (1) +#define MICROPY_PY_SYS_MODULES (1) +#define MICROPY_PY_SYS_EXIT (1) +#define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_SYS_STDIO_BUFFER (1) +#define MICROPY_PY_UERRNO (1) +#define MICROPY_PY_USELECT (1) +#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_THREAD (1) +#define MICROPY_PY_THREAD_GIL (1) +// Number of VM jump-loops to do before releasing the GIL. +#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR) + +// extended modules +#define MICROPY_PY_UCTYPES (1) +#define MICROPY_PY_UZLIB (1) +#define MICROPY_PY_UJSON (1) +#define MICROPY_PY_URE (1) +#define MICROPY_PY_UHEAPQ (1) +#define MICROPY_PY_UTIMEQ (1) +#define MICROPY_PY_UBINASCII (1) +#define MICROPY_PY_UBINASCII_CRC32 (1) +#define MICROPY_PY_URANDOM (1) +#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1) +#define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new +#define MICROPY_PY_MACHINE_PULSE (1) +#define MICROPY_PY_MACHINE_I2C (1) +#define MICROPY_PY_MACHINE_SPI (1) +#define MICROPY_PY_MACHINE_SPI_MSB (0) +#define MICROPY_PY_MACHINE_SPI_LSB (1) +#define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new +#define MICROPY_PY_USSL (1) +#define MICROPY_SSL_MBEDTLS (1) +#define MICROPY_PY_USSL_FINALISER (0) // Crashes on gc if enabled! +#define MICROPY_PY_UHASHLIB (0) // We use the ESP32 version +#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS) + +#ifdef CONFIG_MICROPY_USE_WEBSOCKETS +#define MICROPY_PY_WEBSOCKET (1) +#else +#define MICROPY_PY_WEBSOCKET (1) +#endif +#define MICROPY_PY_OS_DUPTERM (0) // not supported, do NOT change +#define MICROPY_PY_WEBREPL (0) // not supported, do NOT change + +#ifdef CONFIG_MICROPY_PY_FRAMEBUF +#define MICROPY_PY_FRAMEBUF (1) +#else +#define MICROPY_PY_FRAMEBUF (0) +#endif +#define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL) + +/* + * Defined in 'component.mk' +#ifdef CONFIG_MICROPY_PY_USE_BTREE +#define MICROPY_PY_BTREE (1) +#else +#define MICROPY_PY_BTREE (0) +#endif +*/ + +// fatfs configuration +#if defined(CONFIG_FATFS_LFN_STACK) +#define MICROPY_FATFS_ENABLE_LFN (2) +#elif defined(CONFIG_FATFS_LFN_HEAP) +#define MICROPY_FATFS_ENABLE_LFN (3) +#else /* CONFIG_FATFS_LFN_NONE */ +#define MICROPY_FATFS_ENABLE_LFN (0) +#endif +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MAX_SS (4096) +#define MICROPY_FATFS_MAX_LFN (CONFIG_FATFS_MAX_LFN) // Get from sdkconfig +#define MICROPY_FATFS_LFN_CODE_PAGE (CONFIG_FATFS_CODEPAGE) // Get from sdkconfig + +#define mp_type_fileio nativefs_type_fileio +#define mp_type_textio nativefs_type_textio + +// internal flash file system configuration +#ifdef CONFIG_MICROPY_INTERNALFS_ENCRIPTED +#define MICROPY_INTERNALFS_ENCRIPTED (1) // use encription on filesystem (UNTESTED!) +#else +#define MICROPY_INTERNALFS_ENCRIPTED (0) // do not use encription on filesystem +#endif + +// === sdcard using ESP32 sdmmc driver configuration === +#ifdef CONFIG_MICROPY_SDMMC_SHOW_INFO +#define MICROPY_SDMMC_SHOW_INFO (1) // show sdcard info after initialization +#else +#define MICROPY_SDMMC_SHOW_INFO (0) // do not show sdcard info after initialization +#endif + +// use vfs's functions for import stat and builtin open +#define mp_import_stat mp_vfs_import_stat +#define mp_builtin_open mp_vfs_open +#define mp_builtin_open_obj mp_vfs_open_obj + +// extra built in names to add to the global namespace +#define MICROPY_PORT_BUILTINS \ + { MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, + +// extra built in modules to add to the list of known ones +extern const struct _mp_obj_module_t utime_module; +extern const struct _mp_obj_module_t uos_module; +extern const struct _mp_obj_module_t mp_module_usocket; +extern const struct _mp_obj_module_t mp_module_machine; +extern const struct _mp_obj_module_t mp_module_network; +extern const struct _mp_obj_module_t mp_module_ymodem; + + +#ifdef CONFIG_MICROPY_USE_REQUESTS +extern const struct _mp_obj_module_t mp_module_requests; +#define BUILTIN_MODULE_REQUESTS { MP_OBJ_NEW_QSTR(MP_QSTR_requests), (mp_obj_t)&mp_module_requests }, +#else +#define BUILTIN_MODULE_REQUESTS +#endif + +#ifdef CONFIG_MICROPY_USE_CURL +extern const struct _mp_obj_module_t mp_module_curl; +#define BUILTIN_MODULE_CURL { MP_OBJ_NEW_QSTR(MP_QSTR_curl), (mp_obj_t)&mp_module_curl }, +#else +#define BUILTIN_MODULE_CURL +#endif + +#ifdef CONFIG_MICROPY_USE_SSH +extern const struct _mp_obj_module_t mp_module_ssh; +#define BUILTIN_MODULE_SSH { MP_OBJ_NEW_QSTR(MP_QSTR_ssh), (mp_obj_t)&mp_module_ssh }, +#else +#define BUILTIN_MODULE_SSH +#endif + +#ifdef CONFIG_MICROPY_USE_DISPLAY +extern const struct _mp_obj_module_t mp_module_display; +#define BUILTIN_MODULE_DISPLAY { MP_OBJ_NEW_QSTR(MP_QSTR_display), (mp_obj_t)&mp_module_display }, + +extern const struct _mp_obj_module_t mp_module_um5ui; +#define BUILTIN_MODULE_M5UI { MP_OBJ_NEW_QSTR(MP_QSTR_m5ui), (mp_obj_t)&mp_module_um5ui }, + +#else +#define BUILTIN_MODULE_DISPLAY +#endif + +#ifdef CONFIG_MICROPY_USE_GSM +extern const struct _mp_obj_module_t mp_module_gsm; +#define BUILTIN_MODULE_GSM { MP_OBJ_NEW_QSTR(MP_QSTR_gsm), (mp_obj_t)&mp_module_gsm }, +#else +#define BUILTIN_MODULE_GSM +#endif + +#ifdef CONFIG_MICROPY_USE_OTA +extern const struct _mp_obj_module_t mp_module_ota; +#define BUILTIN_MODULE_OTA { MP_OBJ_NEW_QSTR(MP_QSTR_ota), (mp_obj_t)&mp_module_ota }, +#else +#define BUILTIN_MODULE_OTA +#endif + +#ifdef CONFIG_MICROPY_USE_BLUETOOTH +extern const struct _mp_obj_module_t mp_module_bluetooth; +#define BUILTIN_MODULE_BLUETOOTH { MP_OBJ_NEW_QSTR(MP_QSTR_bluetooth), (mp_obj_t)&mp_module_bluetooth }, +#else +#define BUILTIN_MODULE_BLUETOOTH +#endif + +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_ymodem), (mp_obj_t)&mp_module_ymodem }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ + BUILTIN_MODULE_DISPLAY \ + BUILTIN_MODULE_CURL \ + BUILTIN_MODULE_REQUESTS \ + BUILTIN_MODULE_SSH \ + BUILTIN_MODULE_GSM \ + BUILTIN_MODULE_OTA \ + BUILTIN_MODULE_BLUETOOTH \ + BUILTIN_MODULE_M5UI \ + +#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ + { MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_collections), (mp_obj_t)&mp_module_collections }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_hashlib), (mp_obj_t)&mp_module_uhashlib }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_heapq), (mp_obj_t)&mp_module_uheapq }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_io), (mp_obj_t)&mp_module_io }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&mp_module_urandom }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_module_uselect }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_ssl), (mp_obj_t)&mp_module_ussl }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_zlib), (mp_obj_t)&mp_module_uzlib }, \ + +#define MP_STATE_PORT MP_STATE_VM + +#define MICROPY_PORT_ROOT_POINTERS \ + const char *readline_hist[20]; \ + +// type definitions for the specific machine +#define BYTES_PER_WORD (4) +#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p))) +#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) +#define MP_SSIZE_MAX (0x7fffffff) + +// Note: these "critical nested" macros do not ensure cross-CPU exclusion, +// the only disable interrupts on the current CPU. To full manage exclusion +// one should use portENTER_CRITICAL/portEXIT_CRITICAL instead. +#include "freertos/FreeRTOS.h" +#define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED() +#define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state) + +#if MICROPY_PY_THREAD +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(void); \ + mp_handle_pending(); \ + MP_THREAD_GIL_EXIT(); \ + vTaskDelay(1); \ + MP_THREAD_GIL_ENTER(); \ + } while (0); +#else +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + extern void mp_handle_pending(void); \ + mp_handle_pending(); \ + asm("waiti 0"); \ + } while (0); +#endif + +#define UINT_FMT "%u" +#define INT_FMT "%d" + +typedef int32_t mp_int_t; // must be pointer size +typedef uint32_t mp_uint_t; // must be pointer size +typedef long mp_off_t; +// ssize_t, off_t as required by POSIX-signatured functions in stream.h +#include + +// board specifics + +#define MICROPY_PY_SYS_PLATFORM "esp32_LoBo" +#define MICROPY_HW_BOARD_NAME CONFIG_MICROPY_HW_BOARD_NAME +#define MICROPY_HW_MCU_NAME CONFIG_MICROPY_HW_MCU_NAME +#define MICROPY_TIMEZONE CONFIG_MICROPY_TIMEZONE diff --git a/MicroPython_BUILD/components/micropython/py/asmarm.c b/MicroPython_BUILD/components/micropython/py/asmarm.c index 552fdfb3..1a8923bc 100644 --- a/MicroPython_BUILD/components/micropython/py/asmarm.c +++ b/MicroPython_BUILD/components/micropython/py/asmarm.c @@ -150,10 +150,7 @@ void asm_arm_bkpt(asm_arm_t *as) { // | low address | high address in RAM void asm_arm_entry(asm_arm_t *as, int num_locals) { - - if (num_locals < 0) { - num_locals = 0; - } + assert(num_locals >= 0); as->stack_adjust = 0; as->push_reglist = 1 << ASM_ARM_REG_R1 diff --git a/MicroPython_BUILD/components/micropython/py/asmarm.h b/MicroPython_BUILD/components/micropython/py/asmarm.h index a302b159..871e3582 100644 --- a/MicroPython_BUILD/components/micropython/py/asmarm.h +++ b/MicroPython_BUILD/components/micropython/py/asmarm.h @@ -167,17 +167,12 @@ void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp); } while (0) #define ASM_CALL_IND(as, ptr, idx) asm_arm_bl_ind(as, ptr, idx, ASM_ARM_REG_R3) -#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_arm_mov_local_reg(as, (local_num), (reg)) -#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm)) -#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_arm_mov_reg_i32(as, (reg), (imm)) -#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \ - do { \ - asm_arm_mov_reg_i32(as, (reg_temp), (imm)); \ - asm_arm_mov_local_reg(as, (local_num), (reg_temp)); \ - } while (false) -#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_arm_mov_reg_local(as, (reg), (local_num)) +#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_arm_mov_local_reg((as), (local_num), (reg_src)) +#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm)) +#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_arm_mov_reg_i32((as), (reg_dest), (imm)) +#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_arm_mov_reg_local((as), (reg_dest), (local_num)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_arm_mov_reg_reg((as), (reg_dest), (reg_src)) -#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_arm_mov_reg_local_addr(as, (reg), (local_num)) +#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_arm_mov_reg_local_addr((as), (reg_dest), (local_num)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift)) #define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift)) diff --git a/MicroPython_BUILD/components/micropython/py/asmbase.c b/MicroPython_BUILD/components/micropython/py/asmbase.c index c941e917..4c84c3b2 100644 --- a/MicroPython_BUILD/components/micropython/py/asmbase.c +++ b/MicroPython_BUILD/components/micropython/py/asmbase.c @@ -46,10 +46,10 @@ void mp_asm_base_deinit(mp_asm_base_t *as, bool free_code) { } void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) { - if (pass == MP_ASM_PASS_COMPUTE) { - // reset all labels + if (pass < MP_ASM_PASS_EMIT) { + // Reset labels so we can detect backwards jumps (and verify unique assignment) memset(as->label_offsets, -1, as->max_num_labels * sizeof(size_t)); - } else if (pass == MP_ASM_PASS_EMIT) { + } else { // allocating executable RAM is platform specific MP_PLAT_ALLOC_EXEC(as->code_offset, (void**)&as->code_base, &as->code_size); assert(as->code_base != NULL); diff --git a/MicroPython_BUILD/components/micropython/py/asmthumb.c b/MicroPython_BUILD/components/micropython/py/asmthumb.c index 5316a7ef..c5b45f2f 100644 --- a/MicroPython_BUILD/components/micropython/py/asmthumb.c +++ b/MicroPython_BUILD/components/micropython/py/asmthumb.c @@ -104,6 +104,8 @@ STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) { // | low address | high address in RAM void asm_thumb_entry(asm_thumb_t *as, int num_locals) { + assert(num_locals >= 0); + // work out what to push and how many extra spaces to reserve on stack // so that we have enough for all locals and it's aligned an 8-byte boundary // we push extra regs (r1, r2, r3) to help do the stack adjustment @@ -111,9 +113,6 @@ void asm_thumb_entry(asm_thumb_t *as, int num_locals) { // for push rlist, lowest numbered register at the lowest address uint reglist; uint stack_adjust; - if (num_locals < 0) { - num_locals = 0; - } // don't pop r0 because it's used for return value switch (num_locals) { case 0: diff --git a/MicroPython_BUILD/components/micropython/py/asmthumb.h b/MicroPython_BUILD/components/micropython/py/asmthumb.h index 7070e03a..8a7df5d5 100644 --- a/MicroPython_BUILD/components/micropython/py/asmthumb.h +++ b/MicroPython_BUILD/components/micropython/py/asmthumb.h @@ -26,6 +26,7 @@ #ifndef MICROPY_INCLUDED_PY_ASMTHUMB_H #define MICROPY_INCLUDED_PY_ASMTHUMB_H +#include #include "py/misc.h" #include "py/asmbase.h" @@ -283,17 +284,12 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp } while (0) #define ASM_CALL_IND(as, ptr, idx) asm_thumb_bl_ind(as, ptr, idx, ASM_THUMB_REG_R3) -#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_thumb_mov_local_reg(as, (local_num), (reg)) -#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_optimised(as, (reg), (imm)) -#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_thumb_mov_reg_i32_aligned(as, (reg), (imm)) -#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \ - do { \ - asm_thumb_mov_reg_i32_optimised(as, (reg_temp), (imm)); \ - asm_thumb_mov_local_reg(as, (local_num), (reg_temp)); \ - } while (false) -#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local(as, (reg), (local_num)) +#define ASM_MOV_LOCAL_REG(as, local_num, reg) asm_thumb_mov_local_reg((as), (local_num), (reg)) +#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_thumb_mov_reg_i32_optimised((as), (reg_dest), (imm)) +#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_thumb_mov_reg_i32_aligned((as), (reg_dest), (imm)) +#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_thumb_mov_reg_local((as), (reg_dest), (local_num)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_thumb_mov_reg_reg((as), (reg_dest), (reg_src)) -#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_thumb_mov_reg_local_addr(as, (reg), (local_num)) +#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_thumb_mov_reg_local_addr((as), (reg_dest), (local_num)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift)) #define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift)) diff --git a/MicroPython_BUILD/components/micropython/py/asmx64.c b/MicroPython_BUILD/components/micropython/py/asmx64.c index aa2a8ec7..c900a08d 100644 --- a/MicroPython_BUILD/components/micropython/py/asmx64.c +++ b/MicroPython_BUILD/components/micropython/py/asmx64.c @@ -526,11 +526,9 @@ void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) { } void asm_x64_entry(asm_x64_t *as, int num_locals) { + assert(num_locals >= 0); asm_x64_push_r64(as, ASM_X64_REG_RBP); asm_x64_mov_r64_r64(as, ASM_X64_REG_RBP, ASM_X64_REG_RSP); - if (num_locals < 0) { - num_locals = 0; - } num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE); asm_x64_push_r64(as, ASM_X64_REG_RBX); diff --git a/MicroPython_BUILD/components/micropython/py/asmx64.h b/MicroPython_BUILD/components/micropython/py/asmx64.h index 425bdf2d..2fbbfa9f 100644 --- a/MicroPython_BUILD/components/micropython/py/asmx64.h +++ b/MicroPython_BUILD/components/micropython/py/asmx64.h @@ -162,17 +162,12 @@ void asm_x64_call_ind(asm_x64_t* as, void* ptr, int temp_r32); } while (0) #define ASM_CALL_IND(as, ptr, idx) asm_x64_call_ind(as, ptr, ASM_X64_REG_RAX) -#define ASM_MOV_REG_TO_LOCAL asm_x64_mov_r64_to_local -#define ASM_MOV_IMM_TO_REG asm_x64_mov_i64_to_r64_optimised -#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x64_mov_i64_to_r64_aligned -#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \ - do { \ - asm_x64_mov_i64_to_r64_optimised(as, (imm), (reg_temp)); \ - asm_x64_mov_r64_to_local(as, (reg_temp), (local_num)); \ - } while (false) -#define ASM_MOV_LOCAL_TO_REG asm_x64_mov_local_to_r64 +#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x64_mov_r64_to_local((as), (reg_src), (local_num)) +#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x64_mov_i64_to_r64_optimised((as), (imm), (reg_dest)) +#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_x64_mov_i64_to_r64_aligned((as), (imm), (reg_dest)) +#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x64_mov_local_to_r64((as), (local_num), (reg_dest)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x64_mov_r64_r64((as), (reg_dest), (reg_src)) -#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x64_mov_local_addr_to_r64 +#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x64_mov_local_addr_to_r64((as), (local_num), (reg_dest)) #define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg)) #define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg)) diff --git a/MicroPython_BUILD/components/micropython/py/asmx86.c b/MicroPython_BUILD/components/micropython/py/asmx86.c index 6a78fbd5..3938baaa 100644 --- a/MicroPython_BUILD/components/micropython/py/asmx86.c +++ b/MicroPython_BUILD/components/micropython/py/asmx86.c @@ -387,7 +387,8 @@ void asm_x86_jcc_label(asm_x86_t *as, mp_uint_t jcc_type, mp_uint_t label) { } } -void asm_x86_entry(asm_x86_t *as, mp_uint_t num_locals) { +void asm_x86_entry(asm_x86_t *as, int num_locals) { + assert(num_locals >= 0); asm_x86_push_r32(as, ASM_X86_REG_EBP); asm_x86_mov_r32_r32(as, ASM_X86_REG_EBP, ASM_X86_REG_ESP); if (num_locals > 0) { diff --git a/MicroPython_BUILD/components/micropython/py/asmx86.h b/MicroPython_BUILD/components/micropython/py/asmx86.h index 0a00e2e7..09559850 100644 --- a/MicroPython_BUILD/components/micropython/py/asmx86.h +++ b/MicroPython_BUILD/components/micropython/py/asmx86.h @@ -104,7 +104,7 @@ void asm_x86_test_r8_with_r8(asm_x86_t* as, int src_r32_a, int src_r32_b); void asm_x86_setcc_r8(asm_x86_t* as, mp_uint_t jcc_type, int dest_r8); void asm_x86_jmp_label(asm_x86_t* as, mp_uint_t label); void asm_x86_jcc_label(asm_x86_t* as, mp_uint_t jcc_type, mp_uint_t label); -void asm_x86_entry(asm_x86_t* as, mp_uint_t num_locals); +void asm_x86_entry(asm_x86_t* as, int num_locals); void asm_x86_exit(asm_x86_t* as); void asm_x86_mov_arg_to_r32(asm_x86_t *as, int src_arg_num, int dest_r32); void asm_x86_mov_local_to_r32(asm_x86_t* as, int src_local_num, int dest_r32); @@ -160,17 +160,12 @@ void asm_x86_call_ind(asm_x86_t* as, void* ptr, mp_uint_t n_args, int temp_r32); } while (0) #define ASM_CALL_IND(as, ptr, idx) asm_x86_call_ind(as, ptr, mp_f_n_args[idx], ASM_X86_REG_EAX) -#define ASM_MOV_REG_TO_LOCAL asm_x86_mov_r32_to_local -#define ASM_MOV_IMM_TO_REG asm_x86_mov_i32_to_r32 -#define ASM_MOV_ALIGNED_IMM_TO_REG asm_x86_mov_i32_to_r32_aligned -#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \ - do { \ - asm_x86_mov_i32_to_r32(as, (imm), (reg_temp)); \ - asm_x86_mov_r32_to_local(as, (reg_temp), (local_num)); \ - } while (false) -#define ASM_MOV_LOCAL_TO_REG asm_x86_mov_local_to_r32 +#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_x86_mov_r32_to_local((as), (reg_src), (local_num)) +#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32((as), (imm), (reg_dest)) +#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_x86_mov_i32_to_r32_aligned((as), (imm), (reg_dest)) +#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_x86_mov_local_to_r32((as), (local_num), (reg_dest)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_x86_mov_r32_r32((as), (reg_dest), (reg_src)) -#define ASM_MOV_LOCAL_ADDR_TO_REG asm_x86_mov_local_addr_to_r32 +#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x86_mov_local_addr_to_r32((as), (local_num), (reg_dest)) #define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg)) #define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg)) diff --git a/MicroPython_BUILD/components/micropython/py/asmxtensa.h b/MicroPython_BUILD/components/micropython/py/asmxtensa.h index 7db6c0d3..e6d4158c 100644 --- a/MicroPython_BUILD/components/micropython/py/asmxtensa.h +++ b/MicroPython_BUILD/components/micropython/py/asmxtensa.h @@ -280,17 +280,12 @@ void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_nu asm_xtensa_op_callx0(as, ASM_XTENSA_REG_A0); \ } while (0) -#define ASM_MOV_REG_TO_LOCAL(as, reg, local_num) asm_xtensa_mov_local_reg(as, (local_num), (reg)) -#define ASM_MOV_IMM_TO_REG(as, imm, reg) asm_xtensa_mov_reg_i32(as, (reg), (imm)) -#define ASM_MOV_ALIGNED_IMM_TO_REG(as, imm, reg) asm_xtensa_mov_reg_i32(as, (reg), (imm)) -#define ASM_MOV_IMM_TO_LOCAL_USING(as, imm, local_num, reg_temp) \ - do { \ - asm_xtensa_mov_reg_i32(as, (reg_temp), (imm)); \ - asm_xtensa_mov_local_reg(as, (local_num), (reg_temp)); \ - } while (0) -#define ASM_MOV_LOCAL_TO_REG(as, local_num, reg) asm_xtensa_mov_reg_local(as, (reg), (local_num)) +#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) asm_xtensa_mov_local_reg((as), (local_num), (reg_src)) +#define ASM_MOV_REG_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm)) +#define ASM_MOV_REG_ALIGNED_IMM(as, reg_dest, imm) asm_xtensa_mov_reg_i32((as), (reg_dest), (imm)) +#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) asm_xtensa_mov_reg_local((as), (reg_dest), (local_num)) #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mov_n((as), (reg_dest), (reg_src)) -#define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_xtensa_mov_reg_local_addr(as, (reg), (local_num)) +#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), (local_num)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \ do { \ diff --git a/MicroPython_BUILD/components/micropython/py/binary.c b/MicroPython_BUILD/components/micropython/py/binary.c index 870a0942..f509ff01 100644 --- a/MicroPython_BUILD/components/micropython/py/binary.c +++ b/MicroPython_BUILD/components/micropython/py/binary.c @@ -206,7 +206,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) { return (mp_obj_t)(mp_uint_t)val; } else if (val_type == 'S') { const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val; - return mp_obj_new_str(s_val, strlen(s_val), false); + return mp_obj_new_str(s_val, strlen(s_val)); #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'f') { union { uint32_t i; float f; } fpu = {val}; diff --git a/MicroPython_BUILD/components/micropython/py/builtin.h b/MicroPython_BUILD/components/micropython/py/builtin.h index 84b99a8a..9b2584ea 100644 --- a/MicroPython_BUILD/components/micropython/py/builtin.h +++ b/MicroPython_BUILD/components/micropython/py/builtin.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -75,7 +76,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj); // Defined by a port, but declared here for simplicity MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); - +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_set_float_precision_obj); // LoBo MP_DECLARE_CONST_FUN_OBJ_2(mp_namedtuple_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_op_contains_obj); diff --git a/MicroPython_BUILD/components/micropython/py/builtinhelp.c b/MicroPython_BUILD/components/micropython/py/builtinhelp.c index f5d35834..7106f3ce 100644 --- a/MicroPython_BUILD/components/micropython/py/builtinhelp.c +++ b/MicroPython_BUILD/components/micropython/py/builtinhelp.c @@ -33,9 +33,9 @@ #if MICROPY_PY_BUILTINS_HELP const char mp_help_default_text[] = -"Welcome to LoBo MicroPython\n" +"Welcome to MicroPython!\n" "\n" -"For online documentation please visit\nhttps://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki\n" +"For online docs please visit http://docs.micropython.org/\n" "\n" "Control commands:\n" " CTRL-A -- on a blank line, enter raw REPL mode\n" @@ -69,7 +69,7 @@ STATIC void mp_help_add_from_names(mp_obj_t list, const char *name) { while (*name) { size_t l = strlen(name); // name should end in '.py' and we strip it off - mp_obj_list_append(list, mp_obj_new_str(name, l - 3, false)); + mp_obj_list_append(list, mp_obj_new_str(name, l - 3)); name += l + 1; } } diff --git a/MicroPython_BUILD/components/micropython/py/builtinimport.c b/MicroPython_BUILD/components/micropython/py/builtinimport.c index 095ce361..b8ed096c 100644 --- a/MicroPython_BUILD/components/micropython/py/builtinimport.c +++ b/MicroPython_BUILD/components/micropython/py/builtinimport.c @@ -44,6 +44,8 @@ #define DEBUG_printf(...) (void)0 #endif +#if MICROPY_ENABLE_EXTERNAL_IMPORT + #define PATH_SEP_CHAR '/' bool mp_obj_is_package(mp_obj_t module) { @@ -318,7 +320,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { } uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len); - char *new_mod = alloca(new_mod_l); + char *new_mod = mp_local_alloc(new_mod_l); memcpy(new_mod, this_name, p - this_name); if (mod_len != 0) { new_mod[p - this_name] = '.'; @@ -326,9 +328,10 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { } qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l); + mp_local_free(new_mod); DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q)); module_name = MP_OBJ_NEW_QSTR(new_mod_q); - mod_str = new_mod; + mod_str = qstr_str(new_mod_q); mod_len = new_mod_l; } @@ -388,19 +391,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { } // found weak linked module module_obj = el->value; - if (MICROPY_MODULE_BUILTIN_INIT) { - // look for __init__ and call it if it exists - // Note: this code doesn't work fully correctly because it allows the - // __init__ function to be called twice if the module is imported by its - // non-weak-link name. Also, this code is duplicated in objmodule.c. - mp_obj_t dest[2]; - mp_load_method_maybe(el->value, MP_QSTR___init__, dest); - if (dest[0] != MP_OBJ_NULL) { - mp_call_method_n_kw(0, 0, dest); - // register module so __init__ is not called again - mp_module_register(mod_name, el->value); - } - } + mp_module_call_init(mod_name, module_obj); } else { no_exist: #else @@ -447,7 +438,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { DEBUG_printf("%.*s is dir\n", vstr_len(&path), vstr_str(&path)); // https://docs.python.org/3/reference/import.html // "Specifically, any module that contains a __path__ attribute is considered a package." - mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false)); + mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path))); size_t orig_path_len = path.len; vstr_add_char(&path, PATH_SEP_CHAR); vstr_add_str(&path, "__init__.py"); @@ -484,4 +475,41 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { // Otherwise, we need to return top-level package return top_module_obj; } + +#else // MICROPY_ENABLE_EXTERNAL_IMPORT + +mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { + // Check that it's not a relative import + if (n_args >= 5 && MP_OBJ_SMALL_INT_VALUE(args[4]) != 0) { + mp_raise_NotImplementedError("relative import"); + } + + // Check if module already exists, and return it if it does + qstr module_name_qstr = mp_obj_str_get_qstr(args[0]); + mp_obj_t module_obj = mp_module_get(module_name_qstr); + if (module_obj != MP_OBJ_NULL) { + return module_obj; + } + + #if MICROPY_MODULE_WEAK_LINKS + // Check if there is a weak link to this module + mp_map_elem_t *el = mp_map_lookup((mp_map_t*)&mp_builtin_module_weak_links_map, MP_OBJ_NEW_QSTR(module_name_qstr), MP_MAP_LOOKUP); + if (el != NULL) { + // Found weak-linked module + mp_module_call_init(module_name_qstr, el->value); + return el->value; + } + #endif + + // Couldn't find the module, so fail + if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { + mp_raise_msg(&mp_type_ImportError, "module not found"); + } else { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, + "no module named '%q'", module_name_qstr)); + } +} + +#endif // MICROPY_ENABLE_EXTERNAL_IMPORT + MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj, 1, 5, mp_builtin___import__); diff --git a/MicroPython_BUILD/components/micropython/py/compile.c b/MicroPython_BUILD/components/micropython/py/compile.c index 4e704abf..9200b346 100644 --- a/MicroPython_BUILD/components/micropython/py/compile.c +++ b/MicroPython_BUILD/components/micropython/py/compile.c @@ -376,6 +376,7 @@ STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, as EMIT(store_subscr); } } + return; } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); if (assign_kind == ASSIGN_AUG_LOAD) { @@ -387,16 +388,10 @@ STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, as } EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); } - } else { - goto cannot_assign; + return; } - } else { - goto cannot_assign; } - return; - -cannot_assign: compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression"); } @@ -1050,8 +1045,8 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) { for (int i = 0; i < n; i++) { len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); } - byte *q_ptr; - byte *str_dest = qstr_build_start(len, &q_ptr); + char *q_ptr = mp_local_alloc(len); + char *str_dest = q_ptr; for (int i = 0; i < n; i++) { if (i > 0) { *str_dest++ = '.'; @@ -1061,7 +1056,8 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) { memcpy(str_dest, str_src, str_src_len); str_dest += str_src_len; } - qstr q_full = qstr_build_end(q_ptr); + qstr q_full = qstr_from_strn(q_ptr, len); + mp_local_free(q_ptr); EMIT_ARG(import_name, q_full); if (is_as) { for (int i = 1; i < n; i++) { @@ -1940,51 +1936,52 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } } else { plain_assign: - if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr) - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 2 - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) { - // optimisation for a, b = c, d - mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1]; - mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; - if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) { - // can't optimise when it's a star expression on the lhs - goto no_optimisation; - } - compile_node(comp, pns10->nodes[0]); // rhs - compile_node(comp, pns10->nodes[1]); // rhs - EMIT(rot_two); - c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store - c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store - } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr) - && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 3 - && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) { - // optimisation for a, b, c = d, e, f - mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1]; + #if MICROPY_COMP_DOUBLE_TUPLE_ASSIGN + if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr) + && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)) { mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; - if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) { - // can't optimise when it's a star expression on the lhs - goto no_optimisation; + pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; + uint32_t n_pns0 = MP_PARSE_NODE_STRUCT_NUM_NODES(pns0); + // Can only optimise a tuple-to-tuple assignment when all of the following hold: + // - equal number of items in LHS and RHS tuples + // - 2 or 3 items in the tuples + // - there are no star expressions in the LHS tuple + if (n_pns0 == MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) + && (n_pns0 == 2 + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + || n_pns0 == 3 + #endif + ) + && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr) + && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr) + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + && (n_pns0 == 2 || !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) + #endif + ) { + // Optimisation for a, b = c, d or a, b, c = d, e, f + compile_node(comp, pns1->nodes[0]); // rhs + compile_node(comp, pns1->nodes[1]); // rhs + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + if (n_pns0 == 3) { + compile_node(comp, pns1->nodes[2]); // rhs + EMIT(rot_three); + } + #endif + EMIT(rot_two); + c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store + c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store + #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN + if (n_pns0 == 3) { + c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store + } + #endif + return; } - compile_node(comp, pns10->nodes[0]); // rhs - compile_node(comp, pns10->nodes[1]); // rhs - compile_node(comp, pns10->nodes[2]); // rhs - EMIT(rot_three); - EMIT(rot_two); - c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store - c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store - c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store - } else { - no_optimisation: - compile_node(comp, pns->nodes[1]); // rhs - c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store } + #endif + + compile_node(comp, pns->nodes[1]); // rhs + c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store } } else { goto plain_assign; diff --git a/MicroPython_BUILD/components/micropython/py/emitbc.c b/MicroPython_BUILD/components/micropython/py/emitbc.c index 3f4dfc17..32e83300 100644 --- a/MicroPython_BUILD/components/micropython/py/emitbc.c +++ b/MicroPython_BUILD/components/micropython/py/emitbc.c @@ -313,9 +313,12 @@ void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { emit->scope = scope; emit->last_source_line_offset = 0; emit->last_source_line = 1; + #ifndef NDEBUG + // With debugging enabled labels are checked for unique assignment if (pass < MP_PASS_EMIT) { memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(mp_uint_t)); } + #endif emit->bytecode_offset = 0; emit->code_info_offset = 0; @@ -434,7 +437,9 @@ void mp_emit_bc_end_pass(emit_t *emit) { } else if (emit->pass == MP_PASS_EMIT) { mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base, + #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS emit->code_info_size + emit->bytecode_size, + #endif emit->const_table, #if MICROPY_PERSISTENT_CODE_SAVE emit->ct_cur_obj, emit->ct_cur_raw_code, @@ -495,7 +500,6 @@ void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { emit->label_offsets[l] = emit->bytecode_offset; } else { // ensure label offset has not changed from MP_PASS_CODE_SIZE to MP_PASS_EMIT - //printf("l%d: (at %d vs %d)\n", l, emit->bytecode_offset, emit->label_offsets[l]); assert(emit->label_offsets[l] == emit->bytecode_offset); } } diff --git a/MicroPython_BUILD/components/micropython/py/emitglue.c b/MicroPython_BUILD/components/micropython/py/emitglue.c index d2add988..74bf8ddc 100644 --- a/MicroPython_BUILD/components/micropython/py/emitglue.c +++ b/MicroPython_BUILD/components/micropython/py/emitglue.c @@ -55,7 +55,10 @@ mp_raw_code_t *mp_emit_glue_new_raw_code(void) { return rc; } -void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len, +void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, + #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS + size_t len, + #endif const mp_uint_t *const_table, #if MICROPY_PERSISTENT_CODE_SAVE uint16_t n_obj, uint16_t n_raw_code, diff --git a/MicroPython_BUILD/components/micropython/py/emitglue.h b/MicroPython_BUILD/components/micropython/py/emitglue.h index 43930333..0830a0d5 100644 --- a/MicroPython_BUILD/components/micropython/py/emitglue.h +++ b/MicroPython_BUILD/components/micropython/py/emitglue.h @@ -40,7 +40,7 @@ typedef enum { } mp_raw_code_kind_t; typedef struct _mp_raw_code_t { - mp_raw_code_kind_t kind : 3; + mp_uint_t kind : 3; // of type mp_raw_code_kind_t mp_uint_t scope_flags : 7; mp_uint_t n_pos_args : 11; union { @@ -63,7 +63,10 @@ typedef struct _mp_raw_code_t { mp_raw_code_t *mp_emit_glue_new_raw_code(void); -void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len, +void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, + #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS + size_t len, + #endif const mp_uint_t *const_table, #if MICROPY_PERSISTENT_CODE_SAVE uint16_t n_obj, uint16_t n_raw_code, diff --git a/MicroPython_BUILD/components/micropython/py/emitnarm.c b/MicroPython_BUILD/components/micropython/py/emitnarm.c new file mode 100644 index 00000000..1b585f82 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/emitnarm.c @@ -0,0 +1,15 @@ +// ARM specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_ARM + +// This is defined so that the assembler exports generic assembler API macros +#define GENERIC_ASM_API (1) +#include "py/asmarm.h" + +#define N_ARM (1) +#define EXPORT_FUN(name) emit_native_arm_##name +#include "py/emitnative.c" + +#endif diff --git a/MicroPython_BUILD/components/micropython/py/emitnative.c b/MicroPython_BUILD/components/micropython/py/emitnative.c index 8e97dda1..7e035d5e 100644 --- a/MicroPython_BUILD/components/micropython/py/emitnative.c +++ b/MicroPython_BUILD/components/micropython/py/emitnative.c @@ -63,96 +63,12 @@ || (MICROPY_EMIT_ARM && N_ARM) \ || (MICROPY_EMIT_XTENSA && N_XTENSA) \ -// this is defined so that the assembler exports generic assembler API macros -#define GENERIC_ASM_API (1) - -#if N_X64 - -// x64 specific stuff -#include "py/asmx64.h" -#define EXPORT_FUN(name) emit_native_x64_##name - -#elif N_X86 - -// x86 specific stuff - -STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { - [MP_F_CONVERT_OBJ_TO_NATIVE] = 2, - [MP_F_CONVERT_NATIVE_TO_OBJ] = 2, - [MP_F_LOAD_NAME] = 1, - [MP_F_LOAD_GLOBAL] = 1, - [MP_F_LOAD_BUILD_CLASS] = 0, - [MP_F_LOAD_ATTR] = 2, - [MP_F_LOAD_METHOD] = 3, - [MP_F_LOAD_SUPER_METHOD] = 2, - [MP_F_STORE_NAME] = 2, - [MP_F_STORE_GLOBAL] = 2, - [MP_F_STORE_ATTR] = 3, - [MP_F_OBJ_SUBSCR] = 3, - [MP_F_OBJ_IS_TRUE] = 1, - [MP_F_UNARY_OP] = 2, - [MP_F_BINARY_OP] = 3, - [MP_F_BUILD_TUPLE] = 2, - [MP_F_BUILD_LIST] = 2, - [MP_F_LIST_APPEND] = 2, - [MP_F_BUILD_MAP] = 1, - [MP_F_STORE_MAP] = 3, -#if MICROPY_PY_BUILTINS_SET - [MP_F_BUILD_SET] = 2, - [MP_F_STORE_SET] = 2, -#endif - [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3, - [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3, - [MP_F_CALL_METHOD_N_KW] = 3, - [MP_F_CALL_METHOD_N_KW_VAR] = 3, - [MP_F_NATIVE_GETITER] = 2, - [MP_F_NATIVE_ITERNEXT] = 1, - [MP_F_NLR_PUSH] = 1, - [MP_F_NLR_POP] = 0, - [MP_F_NATIVE_RAISE] = 1, - [MP_F_IMPORT_NAME] = 3, - [MP_F_IMPORT_FROM] = 2, - [MP_F_IMPORT_ALL] = 1, -#if MICROPY_PY_BUILTINS_SLICE - [MP_F_NEW_SLICE] = 3, -#endif - [MP_F_UNPACK_SEQUENCE] = 3, - [MP_F_UNPACK_EX] = 3, - [MP_F_DELETE_NAME] = 1, - [MP_F_DELETE_GLOBAL] = 1, - [MP_F_NEW_CELL] = 1, - [MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3, - [MP_F_SETUP_CODE_STATE] = 5, - [MP_F_SMALL_INT_FLOOR_DIVIDE] = 2, - [MP_F_SMALL_INT_MODULO] = 2, -}; - -#include "py/asmx86.h" -#define EXPORT_FUN(name) emit_native_x86_##name - -#elif N_THUMB - -// thumb specific stuff -#include "py/asmthumb.h" -#define EXPORT_FUN(name) emit_native_thumb_##name - -#elif N_ARM - -// ARM specific stuff -#include "py/asmarm.h" -#define EXPORT_FUN(name) emit_native_arm_##name - -#elif N_XTENSA - -// Xtensa specific stuff -#include "py/asmxtensa.h" -#define EXPORT_FUN(name) emit_native_xtensa_##name - -#else - -#error unknown native emitter - -#endif +// define additional generic helper macros +#define ASM_MOV_LOCAL_IMM_VIA(as, local_num, imm, reg_temp) \ + do { \ + ASM_MOV_REG_IMM((as), (reg_temp), (imm)); \ + ASM_MOV_LOCAL_REG((as), (local_num), (reg_temp)); \ + } while (false) #define EMIT_NATIVE_VIPER_TYPE_ERROR(emit, ...) do { \ *emit->error_slot = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, __VA_ARGS__); \ @@ -389,7 +305,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop ASM_MOV_REG_REG(emit->as, REG_LOCAL_3, REG_ARG_3); } else { assert(i == 3); // should be true; max 4 args is checked above - ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_4, i - REG_LOCAL_NUM); + ASM_MOV_LOCAL_REG(emit->as, i - REG_LOCAL_NUM, REG_ARG_4); } } #endif @@ -418,14 +334,14 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop #endif // set code_state.fun_bc - ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_1, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t)); + ASM_MOV_LOCAL_REG(emit->as, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t), REG_ARG_1); // set code_state.ip (offset from start of this function to prelude info) // XXX this encoding may change size - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), REG_ARG_1); + ASM_MOV_LOCAL_IMM_VIA(emit->as, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), emit->prelude_offset, REG_ARG_1); // put address of code_state into first arg - ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1); + ASM_MOV_REG_LOCAL_ADDR(emit->as, REG_ARG_1, 0); // call mp_setup_code_state to prepare code_state structure #if N_THUMB @@ -438,11 +354,11 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // cache some locals in registers if (scope->num_locals > 0) { - ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 0, REG_LOCAL_1); + ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_1, STATE_START + emit->n_state - 1 - 0); if (scope->num_locals > 1) { - ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 1, REG_LOCAL_2); + ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_2, STATE_START + emit->n_state - 1 - 1); if (scope->num_locals > 2) { - ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - 2, REG_LOCAL_3); + ASM_MOV_REG_LOCAL(emit->as, REG_LOCAL_3, STATE_START + emit->n_state - 1 - 2); } } } @@ -606,7 +522,7 @@ STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_REG && si->data.u_reg == reg_needed) { si->kind = STACK_VALUE; - ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i); + ASM_MOV_LOCAL_REG(emit->as, emit->stack_start + i, si->data.u_reg); } } } @@ -617,7 +533,7 @@ STATIC void need_reg_all(emit_t *emit) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_REG) { si->kind = STACK_VALUE; - ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i); + ASM_MOV_LOCAL_REG(emit->as, emit->stack_start + i, si->data.u_reg); } } } @@ -629,7 +545,7 @@ STATIC void need_stack_settled(emit_t *emit) { if (si->kind == STACK_REG) { DEBUG_printf(" reg(%u) to local(%u)\n", si->data.u_reg, emit->stack_start + i); si->kind = STACK_VALUE; - ASM_MOV_REG_TO_LOCAL(emit->as, si->data.u_reg, emit->stack_start + i); + ASM_MOV_LOCAL_REG(emit->as, emit->stack_start + i, si->data.u_reg); } } for (int i = 0; i < emit->stack_size; i++) { @@ -637,7 +553,7 @@ STATIC void need_stack_settled(emit_t *emit) { if (si->kind == STACK_IMM) { DEBUG_printf(" imm(" INT_FMT ") to local(%u)\n", si->data.u_imm, emit->stack_start + i); si->kind = STACK_VALUE; - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->data.u_imm, emit->stack_start + i, REG_TEMP0); + ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + i, si->data.u_imm, REG_TEMP0); } } } @@ -649,7 +565,7 @@ STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int re *vtype = si->vtype; switch (si->kind) { case STACK_VALUE: - ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - pos, reg_dest); + ASM_MOV_REG_LOCAL(emit->as, reg_dest, emit->stack_start + emit->stack_size - pos); break; case STACK_REG: @@ -659,7 +575,7 @@ STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int re break; case STACK_IMM: - ASM_MOV_IMM_TO_REG(emit->as, si->data.u_imm, reg_dest); + ASM_MOV_REG_IMM(emit->as, reg_dest, si->data.u_imm); break; } } @@ -671,7 +587,7 @@ STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) { si[0] = si[1]; if (si->kind == STACK_VALUE) { // if folded element was on the stack we need to put it in a register - ASM_MOV_LOCAL_TO_REG(emit->as, emit->stack_start + emit->stack_size - 1, reg_dest); + ASM_MOV_REG_LOCAL(emit->as, reg_dest, emit->stack_start + emit->stack_size - 1); si->kind = STACK_REG; si->data.u_reg = reg_dest; } @@ -765,30 +681,30 @@ STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) { STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) { need_reg_all(emit); - ASM_MOV_IMM_TO_REG(emit->as, arg_val, arg_reg); + ASM_MOV_REG_IMM(emit->as, arg_reg, arg_val); ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind); } // the first arg is stored in the code aligned on a mp_uint_t boundary STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) { need_reg_all(emit); - ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val, arg_reg); + ASM_MOV_REG_ALIGNED_IMM(emit->as, arg_reg, arg_val); ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind); } STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) { need_reg_all(emit); - ASM_MOV_IMM_TO_REG(emit->as, arg_val1, arg_reg1); - ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2); + ASM_MOV_REG_IMM(emit->as, arg_reg1, arg_val1); + ASM_MOV_REG_IMM(emit->as, arg_reg2, arg_val2); ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind); } // the first arg is stored in the code aligned on a mp_uint_t boundary STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2, mp_int_t arg_val3, int arg_reg3) { need_reg_all(emit); - ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, arg_val1, arg_reg1); - ASM_MOV_IMM_TO_REG(emit->as, arg_val2, arg_reg2); - ASM_MOV_IMM_TO_REG(emit->as, arg_val3, arg_reg3); + ASM_MOV_REG_ALIGNED_IMM(emit->as, arg_reg1, arg_val1); + ASM_MOV_REG_IMM(emit->as, arg_reg2, arg_val2); + ASM_MOV_REG_IMM(emit->as, arg_reg3, arg_val3); ASM_CALL_IND(emit->as, mp_fun_table[fun_kind], fun_kind); } @@ -808,19 +724,19 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de si->kind = STACK_VALUE; switch (si->vtype) { case VTYPE_PYOBJ: - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, si->data.u_imm, emit->stack_start + emit->stack_size - 1 - i, reg_dest); + ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, si->data.u_imm, reg_dest); break; case VTYPE_BOOL: if (si->data.u_imm == 0) { - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest); + ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, (mp_uint_t)mp_const_false, reg_dest); } else { - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (mp_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest); + ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, (mp_uint_t)mp_const_true, reg_dest); } si->vtype = VTYPE_PYOBJ; break; case VTYPE_INT: case VTYPE_UINT: - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, (uintptr_t)MP_OBJ_NEW_SMALL_INT(si->data.u_imm), emit->stack_start + emit->stack_size - 1 - i, reg_dest); + ASM_MOV_LOCAL_IMM_VIA(emit->as, emit->stack_start + emit->stack_size - 1 - i, (uintptr_t)MP_OBJ_NEW_SMALL_INT(si->data.u_imm), reg_dest); si->vtype = VTYPE_PYOBJ; break; default: @@ -838,9 +754,9 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de stack_info_t *si = &emit->stack_info[emit->stack_size - 1 - i]; if (si->vtype != VTYPE_PYOBJ) { mp_uint_t local_num = emit->stack_start + emit->stack_size - 1 - i; - ASM_MOV_LOCAL_TO_REG(emit->as, local_num, REG_ARG_1); + ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, local_num); emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, si->vtype, REG_ARG_2); // arg2 = type - ASM_MOV_REG_TO_LOCAL(emit->as, REG_RET, local_num); + ASM_MOV_LOCAL_REG(emit->as, local_num, REG_RET); si->vtype = VTYPE_PYOBJ; DEBUG_printf(" convert_native_to_obj(local_num=" UINT_FMT ")\n", local_num); } @@ -848,7 +764,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de // Adujust the stack for a pop of n_pop items, and load the stack pointer into reg_dest. adjust_stack(emit, -n_pop); - ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest); + ASM_MOV_REG_LOCAL_ADDR(emit->as, reg_dest, emit->stack_start + emit->stack_size); } // vtype of all n_push objects is VTYPE_PYOBJ @@ -858,7 +774,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_d emit->stack_info[emit->stack_size + i].kind = STACK_VALUE; emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ; } - ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, emit->stack_start + emit->stack_size, reg_dest); + ASM_MOV_REG_LOCAL_ADDR(emit->as, reg_dest, emit->stack_start + emit->stack_size); adjust_stack(emit, n_push); } @@ -881,7 +797,7 @@ STATIC void emit_native_import_name(emit_t *emit, qstr qst) { stack_info_t *top = peek_stack(emit, 0); if (top->vtype == VTYPE_PTR_NONE) { emit_pre_pop_discard(emit); - ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_ARG_2); + ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)mp_const_none); } else { vtype_kind_t vtype_fromlist; emit_pre_pop_reg(emit, &vtype_fromlist, REG_ARG_2); @@ -891,7 +807,7 @@ STATIC void emit_native_import_name(emit_t *emit, qstr qst) { // level argument should be an immediate integer top = peek_stack(emit, 0); assert(top->vtype == VTYPE_INT && top->kind == STACK_IMM); - ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_NEW_SMALL_INT(top->data.u_imm), REG_ARG_3); + ASM_MOV_REG_IMM(emit->as, REG_ARG_3, (mp_uint_t)MP_OBJ_NEW_SMALL_INT(top->data.u_imm)); emit_pre_pop_discard(emit); } else { @@ -981,7 +897,7 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qst) { STATIC void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj) { emit_native_pre(emit); need_reg_single(emit, REG_RET, 0); - ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)obj, REG_RET); + ASM_MOV_REG_ALIGNED_IMM(emit->as, REG_RET, (mp_uint_t)obj); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } @@ -1006,9 +922,9 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { } else { need_reg_single(emit, REG_TEMP0, 0); if (emit->do_viper_types) { - ASM_MOV_LOCAL_TO_REG(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0); + ASM_MOV_REG_LOCAL(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM); } else { - ASM_MOV_LOCAL_TO_REG(emit->as, STATE_START + emit->n_state - 1 - local_num, REG_TEMP0); + ASM_MOV_REG_LOCAL(emit->as, REG_TEMP0, STATE_START + emit->n_state - 1 - local_num); } emit_post_push_reg(emit, vtype, REG_TEMP0); } @@ -1134,7 +1050,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } #endif - ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index); + ASM_MOV_REG_IMM(emit->as, reg_index, index_value); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } @@ -1151,7 +1067,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } #endif - ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index); + ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } @@ -1168,7 +1084,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) { break; } #endif - ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index); + ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; } @@ -1233,9 +1149,9 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) } else { emit_pre_pop_reg(emit, &vtype, REG_TEMP0); if (emit->do_viper_types) { - ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, local_num - REG_LOCAL_NUM); + ASM_MOV_LOCAL_REG(emit->as, local_num - REG_LOCAL_NUM, REG_TEMP0); } else { - ASM_MOV_REG_TO_LOCAL(emit->as, REG_TEMP0, STATE_START + emit->n_state - 1 - local_num); + ASM_MOV_LOCAL_REG(emit->as, STATE_START + emit->n_state - 1 - local_num, REG_TEMP0); } } emit_post(emit); @@ -1354,7 +1270,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) { break; } #endif - ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index); + ASM_MOV_REG_IMM(emit->as, reg_index, index_value); #if N_ARM asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); return; @@ -1375,7 +1291,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) { break; } #endif - ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index); + ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); #if N_ARM asm_arm_strh_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); return; @@ -1396,7 +1312,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) { break; } #endif - ASM_MOV_IMM_TO_REG(emit->as, index_value << 2, reg_index); + ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); #if N_ARM asm_arm_str_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); return; @@ -1773,7 +1689,7 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) { emit_call(emit, MP_F_NATIVE_GETITER); } else { // mp_getiter will allocate the iter_buf on the heap - ASM_MOV_IMM_TO_REG(emit->as, 0, REG_ARG_2); + ASM_MOV_REG_IMM(emit->as, REG_ARG_2, 0); emit_call(emit, MP_F_NATIVE_GETITER); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } @@ -1784,7 +1700,7 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS); adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS); emit_call(emit, MP_F_NATIVE_ITERNEXT); - ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1); + ASM_MOV_REG_IMM(emit->as, REG_TEMP1, (mp_uint_t)MP_OBJ_STOP_ITERATION); ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } @@ -2128,12 +2044,12 @@ STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_c emit_native_pre(emit); if (n_pos_defaults == 0 && n_kw_defaults == 0) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over); - ASM_MOV_IMM_TO_REG(emit->as, n_closed_over, REG_ARG_2); + ASM_MOV_REG_IMM(emit->as, REG_ARG_2, n_closed_over); } else { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_closed_over + 2); - ASM_MOV_IMM_TO_REG(emit->as, 0x100 | n_closed_over, REG_ARG_2); + ASM_MOV_REG_IMM(emit->as, REG_ARG_2, 0x100 | n_closed_over); } - ASM_MOV_ALIGNED_IMM_TO_REG(emit->as, (mp_uint_t)scope->raw_code, REG_ARG_1); + ASM_MOV_REG_ALIGNED_IMM(emit->as, REG_ARG_1, (mp_uint_t)scope->raw_code); ASM_CALL_IND(emit->as, mp_fun_table[MP_F_MAKE_CLOSURE_FROM_RAW_CODE], MP_F_MAKE_CLOSURE_FROM_RAW_CODE); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } @@ -2212,9 +2128,9 @@ STATIC void emit_native_return_value(emit_t *emit) { if (peek_vtype(emit, 0) == VTYPE_PTR_NONE) { emit_pre_pop_discard(emit); if (emit->return_vtype == VTYPE_PYOBJ) { - ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)mp_const_none, REG_RET); + ASM_MOV_REG_IMM(emit->as, REG_RET, (mp_uint_t)mp_const_none); } else { - ASM_MOV_IMM_TO_REG(emit->as, 0, REG_RET); + ASM_MOV_REG_IMM(emit->as, REG_RET, 0); } } else { vtype_kind_t vtype; diff --git a/MicroPython_BUILD/components/micropython/py/emitnthumb.c b/MicroPython_BUILD/components/micropython/py/emitnthumb.c new file mode 100644 index 00000000..2b68ca3a --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/emitnthumb.c @@ -0,0 +1,15 @@ +// thumb specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_THUMB + +// this is defined so that the assembler exports generic assembler API macros +#define GENERIC_ASM_API (1) +#include "py/asmthumb.h" + +#define N_THUMB (1) +#define EXPORT_FUN(name) emit_native_thumb_##name +#include "py/emitnative.c" + +#endif diff --git a/MicroPython_BUILD/components/micropython/py/emitnx64.c b/MicroPython_BUILD/components/micropython/py/emitnx64.c new file mode 100644 index 00000000..b9800f63 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/emitnx64.c @@ -0,0 +1,15 @@ +// x64 specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_X64 + +// This is defined so that the assembler exports generic assembler API macros +#define GENERIC_ASM_API (1) +#include "py/asmx64.h" + +#define N_X64 (1) +#define EXPORT_FUN(name) emit_native_x64_##name +#include "py/emitnative.c" + +#endif diff --git a/MicroPython_BUILD/components/micropython/py/emitnx86.c b/MicroPython_BUILD/components/micropython/py/emitnx86.c new file mode 100644 index 00000000..d4cd24d7 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/emitnx86.c @@ -0,0 +1,67 @@ +// x86 specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_X86 + +// This is defined so that the assembler exports generic assembler API macros +#define GENERIC_ASM_API (1) +#include "py/asmx86.h" + +// x86 needs a table to know how many args a given function has +STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { + [MP_F_CONVERT_OBJ_TO_NATIVE] = 2, + [MP_F_CONVERT_NATIVE_TO_OBJ] = 2, + [MP_F_LOAD_NAME] = 1, + [MP_F_LOAD_GLOBAL] = 1, + [MP_F_LOAD_BUILD_CLASS] = 0, + [MP_F_LOAD_ATTR] = 2, + [MP_F_LOAD_METHOD] = 3, + [MP_F_LOAD_SUPER_METHOD] = 2, + [MP_F_STORE_NAME] = 2, + [MP_F_STORE_GLOBAL] = 2, + [MP_F_STORE_ATTR] = 3, + [MP_F_OBJ_SUBSCR] = 3, + [MP_F_OBJ_IS_TRUE] = 1, + [MP_F_UNARY_OP] = 2, + [MP_F_BINARY_OP] = 3, + [MP_F_BUILD_TUPLE] = 2, + [MP_F_BUILD_LIST] = 2, + [MP_F_LIST_APPEND] = 2, + [MP_F_BUILD_MAP] = 1, + [MP_F_STORE_MAP] = 3, + #if MICROPY_PY_BUILTINS_SET + [MP_F_BUILD_SET] = 2, + [MP_F_STORE_SET] = 2, + #endif + [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3, + [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3, + [MP_F_CALL_METHOD_N_KW] = 3, + [MP_F_CALL_METHOD_N_KW_VAR] = 3, + [MP_F_NATIVE_GETITER] = 2, + [MP_F_NATIVE_ITERNEXT] = 1, + [MP_F_NLR_PUSH] = 1, + [MP_F_NLR_POP] = 0, + [MP_F_NATIVE_RAISE] = 1, + [MP_F_IMPORT_NAME] = 3, + [MP_F_IMPORT_FROM] = 2, + [MP_F_IMPORT_ALL] = 1, + #if MICROPY_PY_BUILTINS_SLICE + [MP_F_NEW_SLICE] = 3, + #endif + [MP_F_UNPACK_SEQUENCE] = 3, + [MP_F_UNPACK_EX] = 3, + [MP_F_DELETE_NAME] = 1, + [MP_F_DELETE_GLOBAL] = 1, + [MP_F_NEW_CELL] = 1, + [MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3, + [MP_F_SETUP_CODE_STATE] = 5, + [MP_F_SMALL_INT_FLOOR_DIVIDE] = 2, + [MP_F_SMALL_INT_MODULO] = 2, +}; + +#define N_X86 (1) +#define EXPORT_FUN(name) emit_native_x86_##name +#include "py/emitnative.c" + +#endif diff --git a/MicroPython_BUILD/components/micropython/py/emitnxtensa.c b/MicroPython_BUILD/components/micropython/py/emitnxtensa.c new file mode 100644 index 00000000..1a423e21 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/emitnxtensa.c @@ -0,0 +1,15 @@ +// Xtensa specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_XTENSA + +// this is defined so that the assembler exports generic assembler API macros +#define GENERIC_ASM_API (1) +#include "py/asmxtensa.h" + +#define N_XTENSA (1) +#define EXPORT_FUN(name) emit_native_xtensa_##name +#include "py/emitnative.c" + +#endif diff --git a/MicroPython_BUILD/components/micropython/py/formatfloat.c b/MicroPython_BUILD/components/micropython/py/formatfloat.c index 4228f99f..dc7fc1d1 100644 --- a/MicroPython_BUILD/components/micropython/py/formatfloat.c +++ b/MicroPython_BUILD/components/micropython/py/formatfloat.c @@ -258,7 +258,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch } // It can be that f was right on the edge of an entry in pos_pow needs to be reduced - if (f >= FPCONST(10.0)) { + if ((int)f >= 10) { e += 1; f *= FPCONST(0.1); } @@ -330,7 +330,11 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch // Print the digits of the mantissa for (int i = 0; i < num_digits; ++i, --dec) { int32_t d = (int32_t)f; - *s++ = '0' + d; + if (d < 0) { + *s++ = '0'; + } else { + *s++ = '0' + d; + } if (dec == 0 && prec > 0) { *s++ = '.'; } @@ -341,7 +345,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch // Round // If we print non-exponential format (i.e. 'f'), but a digit we're going // to round by (e) is too far away, then there's nothing to round. - if ((org_fmt != 'f' || e <= 1) && f >= FPCONST(5.0)) { + if ((org_fmt != 'f' || e <= num_digits) && f >= FPCONST(5.0)) { char *rs = s; rs--; while (1) { diff --git a/MicroPython_BUILD/components/micropython/py/gc.c b/MicroPython_BUILD/components/micropython/py/gc.c index 9752b353..b1f6f7ee 100644 --- a/MicroPython_BUILD/components/micropython/py/gc.c +++ b/MicroPython_BUILD/components/micropython/py/gc.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +28,7 @@ #include #include #include - +#include "esp_log.h" #include "py/gc.h" #include "py/runtime.h" @@ -44,6 +45,10 @@ // make this 1 to dump the heap each time it changes #define EXTENSIVE_HEAP_PROFILING (0) +// make this 1 to zero out swept memory to more eagerly +// detect untraced object still in use +#define CLEAR_ON_SWEEP (1) + #define WORDS_PER_BLOCK ((MICROPY_BYTES_PER_GC_BLOCK) / BYTES_PER_WORD) #define BYTES_PER_BLOCK (MICROPY_BYTES_PER_GC_BLOCK) @@ -92,7 +97,7 @@ #define FTB_CLEAR(block) do { MP_STATE_MEM(gc_finaliser_table_start)[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) #endif -#if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL +#if MICROPY_PY_THREAD && MICROPY_PY_THREAD_GIL #define GC_ENTER() mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1) #define GC_EXIT() mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex)) #else @@ -149,6 +154,7 @@ void gc_init(void *start, void *end) { // allow auto collection MP_STATE_MEM(gc_auto_collect_enabled) = 1; + MP_STATE_MEM(gc_auto_collect_debug) = 0; #if MICROPY_GC_ALLOC_THRESHOLD // by default, maxuint for gc threshold, effectively turning gc-by-threshold off @@ -191,29 +197,22 @@ bool gc_is_locked(void) { && ptr < (void*)MP_STATE_MEM(gc_pool_end) /* must be below end of pool */ \ ) -// ptr should be of type void* -#define VERIFY_MARK_AND_PUSH(ptr) \ - do { \ - if (VERIFY_PTR(ptr)) { \ - size_t _block = BLOCK_FROM_PTR(ptr); \ - if (ATB_GET_KIND(_block) == AT_HEAD) { \ - /* an unmarked head, mark it, and push it on gc stack */ \ - DEBUG_printf("gc_mark(%p)\n", ptr); \ - ATB_HEAD_TO_MARK(_block); \ - if (MP_STATE_MEM(gc_sp) < &MP_STATE_MEM(gc_stack)[MICROPY_ALLOC_GC_STACK_SIZE]) { \ - *MP_STATE_MEM(gc_sp)++ = _block; \ - } else { \ - MP_STATE_MEM(gc_stack_overflow) = 1; \ - } \ - } \ - } \ - } while (0) - -STATIC void gc_drain_stack(void) { - while (MP_STATE_MEM(gc_sp) > MP_STATE_MEM(gc_stack)) { - // pop the next block off the stack - size_t block = *--MP_STATE_MEM(gc_sp); +#ifndef TRACE_MARK +#if DEBUG_PRINT +#define TRACE_MARK(block, ptr) DEBUG_printf("gc_mark(%p)\n", ptr) +#else +#define TRACE_MARK(block, ptr) +#endif +#endif +// Take the given block as the topmost block on the stack. Check all it's +// children: mark the unmarked child blocks and put those newly marked +// blocks on the stack. When all children have been checked, pop off the +// topmost block on the stack and repeat with that one. +STATIC void gc_mark_subtree(size_t block) { + // Start with the block passed in the argument. + size_t sp = 0; + for (;;) { // work out number of consecutive blocks in the chain starting with this one size_t n_blocks = 0; do { @@ -224,31 +223,49 @@ STATIC void gc_drain_stack(void) { void **ptrs = (void**)PTR_FROM_BLOCK(block); for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void*); i > 0; i--, ptrs++) { void *ptr = *ptrs; - VERIFY_MARK_AND_PUSH(ptr); + if (VERIFY_PTR(ptr)) { + // Mark and push this pointer + size_t childblock = BLOCK_FROM_PTR(ptr); + if (ATB_GET_KIND(childblock) == AT_HEAD) { + // an unmarked head, mark it, and push it on gc stack + TRACE_MARK(childblock, ptr); + ATB_HEAD_TO_MARK(childblock); + MP_STATE_MEM(gc_marked)++; + if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { + MP_STATE_MEM(gc_stack)[sp++] = childblock; + } else { + MP_STATE_MEM(gc_stack_overflow) = 1; + } + } + } } + + // Are there any blocks on the stack? + if (sp == 0) { + break; // No, stack is empty, we're done. + } + + // pop the next block off the stack + block = MP_STATE_MEM(gc_stack)[--sp]; } } STATIC void gc_deal_with_stack_overflow(void) { while (MP_STATE_MEM(gc_stack_overflow)) { MP_STATE_MEM(gc_stack_overflow) = 0; - MP_STATE_MEM(gc_sp) = MP_STATE_MEM(gc_stack); // scan entire memory looking for blocks which have been marked but not their children for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { // trace (again) if mark bit set if (ATB_GET_KIND(block) == AT_MARK) { - *MP_STATE_MEM(gc_sp)++ = block; - gc_drain_stack(); + gc_mark_subtree(block); } } } } STATIC void gc_sweep(void) { - #if MICROPY_PY_GC_COLLECT_RETVAL MP_STATE_MEM(gc_collected) = 0; - #endif // free unmarked heads and their tails int free_tail = 0; for (size_t block = 0; block < MP_STATE_MEM(gc_alloc_table_byte_len) * BLOCKS_PER_ATB; block++) { @@ -277,15 +294,16 @@ STATIC void gc_sweep(void) { } #endif free_tail = 1; - DEBUG_printf("gc_sweep(%x)\n", PTR_FROM_BLOCK(block)); - #if MICROPY_PY_GC_COLLECT_RETVAL + DEBUG_printf("gc_sweep(%p)\n", (void*)PTR_FROM_BLOCK(block)); MP_STATE_MEM(gc_collected)++; - #endif - // fall through to free the head + // no break, fall through to free the head case AT_TAIL: if (free_tail) { ATB_ANY_TO_FREE(block); + #if CLEAR_ON_SWEEP + memset((void*)PTR_FROM_BLOCK(block), 0, BYTES_PER_BLOCK); + #endif } break; @@ -299,37 +317,43 @@ STATIC void gc_sweep(void) { void gc_collect_start(void) { GC_ENTER(); + MP_STATE_MEM(gc_marked) = 0; MP_STATE_MEM(gc_lock_depth)++; #if MICROPY_GC_ALLOC_THRESHOLD MP_STATE_MEM(gc_alloc_amount) = 0; #endif MP_STATE_MEM(gc_stack_overflow) = 0; - MP_STATE_MEM(gc_sp) = MP_STATE_MEM(gc_stack); - // Trace root pointers. This relies on the root pointers being organised + + // Trace root pointers. This relies on the root pointers being organized // correctly in the mp_state_ctx structure. We scan nlr_top, dict_locals, // dict_globals, then the root pointer section of mp_state_vm. void **ptrs = (void**)(void*)&mp_state_ctx; gc_collect_root(ptrs, offsetof(mp_state_ctx_t, vm.qstr_last_chunk) / sizeof(void*)); + + #if MICROPY_ENABLE_PYSTACK + // Trace root pointers from the Python stack. + ptrs = (void**)(void*)MP_STATE_THREAD(pystack_start); + gc_collect_root(ptrs, (MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start)) / sizeof(void*)); + #endif } void gc_collect_root(void **ptrs, size_t len) { for (size_t i = 0; i < len; i++) { void *ptr = ptrs[i]; - VERIFY_MARK_AND_PUSH(ptr); - gc_drain_stack(); + if (VERIFY_PTR(ptr)) { + size_t block = BLOCK_FROM_PTR(ptr); + if (ATB_GET_KIND(block) == AT_HEAD) { + // An unmarked head: mark it, and mark all its children + TRACE_MARK(block, ptr); + ATB_HEAD_TO_MARK(block); + MP_STATE_MEM(gc_marked)++; + gc_mark_subtree(block); + } + } } } -void gc_collect_end(void) { - gc_deal_with_stack_overflow(); - gc_sweep(); - MP_STATE_MEM(gc_last_free_atb_index) = 0; - MP_STATE_MEM(gc_lock_depth)--; - GC_EXIT(); -} - -void gc_info(gc_info_t *info) { - GC_ENTER(); +static void _gc_info(gc_info_t *info) { info->total = MP_STATE_MEM(gc_pool_end) - MP_STATE_MEM(gc_pool_start); info->used = 0; info->free = 0; @@ -389,6 +413,29 @@ void gc_info(gc_info_t *info) { info->used *= BYTES_PER_BLOCK; info->free *= BYTES_PER_BLOCK; +} + +void gc_collect_end(void) { + gc_deal_with_stack_overflow(); + gc_sweep(); + MP_STATE_MEM(gc_last_free_atb_index) = 0; + MP_STATE_MEM(gc_lock_depth)--; + + #if MICROPY_GC_ALLOC_THRESHOLD + gc_info_t info; + _gc_info(&info); + MP_STATE_MEM(gc_alloc_amount) = info.used / BYTES_PER_BLOCK; + if (MP_STATE_MEM(gc_auto_collect_debug)) { + printf("gc_collect: END: allocated=%d\n", info.used); + } + #endif + + GC_EXIT(); +} + +void gc_info(gc_info_t *info) { + GC_ENTER(); + _gc_info(info); GC_EXIT(); } @@ -417,8 +464,11 @@ void *gc_alloc(size_t n_bytes, bool has_finaliser) { #if MICROPY_GC_ALLOC_THRESHOLD if (!collected && MP_STATE_MEM(gc_alloc_amount) >= MP_STATE_MEM(gc_alloc_threshold)) { + if (MP_STATE_MEM(gc_auto_collect_debug)) { + printf("gc_alloc: gc_collect trigered [%d >= %d]\n", MP_STATE_MEM(gc_alloc_amount)*BYTES_PER_BLOCK, MP_STATE_MEM(gc_alloc_threshold)*BYTES_PER_BLOCK); + } GC_EXIT(); - gc_collect(); + gc_collect(MP_STATE_MEM(gc_auto_collect_debug)); GC_ENTER(); } #endif @@ -440,7 +490,10 @@ void *gc_alloc(size_t n_bytes, bool has_finaliser) { return NULL; } DEBUG_printf("gc_alloc(" UINT_FMT "): no free mem, triggering GC\n", n_bytes); - gc_collect(); + if (MP_STATE_MEM(gc_auto_collect_debug)) { + printf("gc_alloc: no free mem, gc_collect trigered\n"); + } + gc_collect(MP_STATE_MEM(gc_auto_collect_debug)); collected = 1; GC_ENTER(); } @@ -551,12 +604,17 @@ void gc_free(void *ptr) { MP_STATE_MEM(gc_last_free_atb_index) = block / BLOCKS_PER_ATB; } + size_t n_blocks = 0; // free head and all of its tail blocks do { ATB_ANY_TO_FREE(block); block += 1; + n_blocks++; } while (ATB_GET_KIND(block) == AT_TAIL); + #if MICROPY_GC_ALLOC_THRESHOLD + MP_STATE_MEM(gc_alloc_amount) -= n_blocks; + #endif GC_EXIT(); #if EXTENSIVE_HEAP_PROFILING @@ -587,7 +645,7 @@ size_t gc_nbytes(const void *ptr) { #if 0 // old, simple realloc that didn't expand memory in place -void *gc_realloc(void *ptr, mp_uint_t n_bytes) { +void *gc_realloc(void *ptr, size_t n_bytes, bool allow_move) { mp_uint_t n_existing = gc_nbytes(ptr); if (n_bytes <= n_existing) { return ptr; @@ -628,27 +686,18 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { void *ptr = ptr_in; - // sanity check the ptr - if (!VERIFY_PTR(ptr)) { - return NULL; - } - - // get first block - size_t block = BLOCK_FROM_PTR(ptr); - GC_ENTER(); - // sanity check the ptr is pointing to the head of a block - if (ATB_GET_KIND(block) != AT_HEAD) { - GC_EXIT(); - return NULL; - } - if (MP_STATE_MEM(gc_lock_depth) > 0) { GC_EXIT(); return NULL; } + // get the GC block number corresponding to this pointer + assert(VERIFY_PTR(ptr)); + size_t block = BLOCK_FROM_PTR(ptr); + assert(ATB_GET_KIND(block) == AT_HEAD); + // compute number of new blocks that are requested size_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; @@ -687,8 +736,10 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // check if we can shrink the allocated area if (new_blocks < n_blocks) { // free unneeded tail blocks + size_t n_freed = 0; for (size_t bl = block + new_blocks, count = n_blocks - new_blocks; count > 0; bl++, count--) { ATB_ANY_TO_FREE(bl); + n_freed++; } // set the last_free pointer to end of this block if it's earlier in the heap @@ -696,6 +747,9 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { MP_STATE_MEM(gc_last_free_atb_index) = (block + new_blocks) / BLOCKS_PER_ATB; } + #if MICROPY_GC_ALLOC_THRESHOLD + MP_STATE_MEM(gc_alloc_amount) -= n_freed; + #endif GC_EXIT(); #if EXTENSIVE_HEAP_PROFILING @@ -707,12 +761,17 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // check if we can expand in place if (new_blocks <= n_blocks + n_free) { + size_t n_added = 0; // mark few more blocks as used tail for (size_t bl = block + n_blocks; bl < block + new_blocks; bl++) { assert(ATB_GET_KIND(bl) == AT_FREE); ATB_FREE_TO_TAIL(bl); + n_added++; } + #if MICROPY_GC_ALLOC_THRESHOLD + MP_STATE_MEM(gc_alloc_amount) += n_added; + #endif GC_EXIT(); #if MICROPY_GC_CONSERVATIVE_CLEAR @@ -848,7 +907,7 @@ void gc_dump_alloc_table(void) { else if (*ptr == &mp_type_module) { c = 'M'; } else { c = 'h'; - #if 0 + #if 1 // This code prints "Q" for qstr-pool data, and "q" for qstr-str // data. It can be useful to see how qstrs are being allocated, // but is disabled by default because it is very slow. diff --git a/MicroPython_BUILD/components/micropython/py/gc.h b/MicroPython_BUILD/components/micropython/py/gc.h index 739349c1..14176f92 100644 --- a/MicroPython_BUILD/components/micropython/py/gc.h +++ b/MicroPython_BUILD/components/micropython/py/gc.h @@ -40,7 +40,7 @@ void gc_unlock(void); bool gc_is_locked(void); // A given port must implement gc_collect by using the other collect functions. -void gc_collect(void); +void gc_collect(int flag); void gc_collect_start(void); void gc_collect_root(void **ptrs, size_t len); void gc_collect_end(void); diff --git a/MicroPython_BUILD/components/micropython/py/makeqstrdata.py b/MicroPython_BUILD/components/micropython/py/makeqstrdata.py index 38fde1a9..3c0a6090 100644 --- a/MicroPython_BUILD/components/micropython/py/makeqstrdata.py +++ b/MicroPython_BUILD/components/micropython/py/makeqstrdata.py @@ -114,6 +114,9 @@ def parse_input_headers(infiles): if ident == "": # Sort empty qstr above all still order = -200000 + elif ident == "__dir__": + # Put __dir__ after empty qstr for builtin dir() to work + order = -190000 elif ident.startswith("__"): order -= 100000 qstrs[ident] = (order, ident, qstr) diff --git a/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py b/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py index 115a4e96..17644013 100644 --- a/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py +++ b/MicroPython_BUILD/components/micropython/py/makeqstrdefs.py @@ -24,12 +24,16 @@ def write_out(fname, output): f.write("\n".join(output) + "\n") def process_file(f): + re_line = re.compile(r"#[line]*\s\d+\s\"([^\"]+)\"") + re_qstr = re.compile(r'MP_QSTR_[_a-zA-Z0-9]+') output = [] last_fname = None for line in f: + if line.isspace(): + continue # match gcc-like output (# n "file") and msvc-like output (#line n "file") - if line and (line[0:2] == "# " or line[0:5] == "#line"): - m = re.match(r"#[line]*\s\d+\s\"([^\"]+)\"", line) + if line.startswith(('# ', '#line')): + m = re_line.match(line) assert m is not None fname = m.group(1) if not fname.endswith(".c"): @@ -39,7 +43,7 @@ def process_file(f): output = [] last_fname = fname continue - for match in re.findall(r'MP_QSTR_[_a-zA-Z0-9]+', line): + for match in re_qstr.findall(line): name = match.replace('MP_QSTR_', '') if name not in QSTRING_BLACK_LIST: output.append('Q(' + name + ')') @@ -81,6 +85,8 @@ def cat_together(): os.rename(args.output_dir + "/out", args.output_file) with open(args.output_file + ".hash", "w") as f: f.write(new_hash) + else: + print("QSTR not updated") if __name__ == "__main__": diff --git a/MicroPython_BUILD/components/micropython/py/makeversionhdr.py b/MicroPython_BUILD/components/micropython/py/makeversionhdr.py index 749160b4..aedc292e 100644 --- a/MicroPython_BUILD/components/micropython/py/makeversionhdr.py +++ b/MicroPython_BUILD/components/micropython/py/makeversionhdr.py @@ -99,7 +99,7 @@ def make_version_header(filename): # Only write the file if we need to if write_file: - print("Generating %s" % filename) + print("GEN %s" % filename) with open(filename, 'w') as f: f.write(file_data) diff --git a/MicroPython_BUILD/components/micropython/py/malloc.c b/MicroPython_BUILD/components/micropython/py/malloc.c index ea1d4c4b..ba5c952f 100644 --- a/MicroPython_BUILD/components/micropython/py/malloc.c +++ b/MicroPython_BUILD/components/micropython/py/malloc.c @@ -39,6 +39,9 @@ #endif #if MICROPY_MEM_STATS +#if !MICROPY_MALLOC_USES_ALLOCATED_SIZE +#error MICROPY_MEM_STATS requires MICROPY_MALLOC_USES_ALLOCATED_SIZE +#endif #define UPDATE_PEAK() { if (MP_STATE_MEM(current_bytes_allocated) > MP_STATE_MEM(peak_bytes_allocated)) MP_STATE_MEM(peak_bytes_allocated) = MP_STATE_MEM(current_bytes_allocated); } #endif @@ -114,9 +117,6 @@ void *m_malloc_with_finaliser(size_t num_bytes) { void *m_malloc0(size_t num_bytes) { void *ptr = m_malloc(num_bytes); - if (ptr == NULL && num_bytes != 0) { - m_malloc_fail(num_bytes); - } // If this config is set then the GC clears all memory, so we don't need to. #if !MICROPY_GC_CONSERVATIVE_CLEAR memset(ptr, 0, num_bytes); @@ -144,7 +144,11 @@ void *m_realloc(void *ptr, size_t new_num_bytes) { MP_STATE_MEM(current_bytes_allocated) += diff; UPDATE_PEAK(); #endif + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr); + #else + DEBUG_printf("realloc %p, %d : %p\n", ptr, new_num_bytes, new_ptr); + #endif return new_ptr; } @@ -168,7 +172,11 @@ void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move) { UPDATE_PEAK(); } #endif + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr); + #else + DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, new_num_bytes, new_ptr); + #endif return new_ptr; } @@ -181,7 +189,11 @@ void m_free(void *ptr) { #if MICROPY_MEM_STATS MP_STATE_MEM(current_bytes_allocated) -= num_bytes; #endif + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE DEBUG_printf("free %p, %d\n", ptr, num_bytes); + #else + DEBUG_printf("free %p\n", ptr); + #endif } #if MICROPY_MEM_STATS diff --git a/MicroPython_BUILD/components/micropython/py/map.c b/MicroPython_BUILD/components/micropython/py/map.c index 4f76b9b1..6abf4853 100644 --- a/MicroPython_BUILD/components/micropython/py/map.c +++ b/MicroPython_BUILD/components/micropython/py/map.c @@ -33,6 +33,13 @@ #include "py/misc.h" #include "py/runtime.h" +#if MICROPY_DEBUG_VERBOSE // print debugging info +#define DEBUG_PRINT (1) +#else // don't print debugging info +#define DEBUG_PRINT (0) +#define DEBUG_printf(...) (void)0 +#endif + // Fixed empty map. Useful when need to call kw-receiving functions // without any keywords from C, etc. const mp_map_t mp_const_empty_map = { @@ -114,6 +121,7 @@ void mp_map_clear(mp_map_t *map) { STATIC void mp_map_rehash(mp_map_t *map) { size_t old_alloc = map->alloc; size_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1); + DEBUG_printf("mp_map_rehash(%p): " UINT_FMT " -> " UINT_FMT "\n", map, old_alloc, new_alloc); mp_map_elem_t *old_table = map->table; mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc); // If we reach this point, table resizing succeeded, now we can edit the old map. @@ -162,6 +170,7 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t if (map->is_ordered) { for (mp_map_elem_t *elem = &map->table[0], *top = &map->table[map->used]; elem < top; elem++) { if (elem->key == index || (!compare_only_ptrs && mp_obj_equal(elem->key, index))) { + #if MICROPY_PY_COLLECTIONS_ORDEREDDICT if (MP_UNLIKELY(lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND)) { // remove the found element by moving the rest of the array down mp_obj_t value = elem->value; @@ -172,9 +181,11 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t elem->key = MP_OBJ_NULL; elem->value = value; } + #endif return elem; } } + #if MICROPY_PY_COLLECTIONS_ORDEREDDICT if (MP_LIKELY(lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)) { return NULL; } @@ -190,6 +201,9 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t map->all_keys_are_qstrs = 0; } return elem; + #else + return NULL; + #endif } // map is a hash table (not an ordered array), so do a hash lookup diff --git a/MicroPython_BUILD/components/micropython/py/misc.h b/MicroPython_BUILD/components/micropython/py/misc.h index b9f2dae9..72560da1 100644 --- a/MicroPython_BUILD/components/micropython/py/misc.h +++ b/MicroPython_BUILD/components/micropython/py/misc.h @@ -63,8 +63,10 @@ typedef unsigned int uint; #define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type*)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num))) #if MICROPY_ENABLE_FINALISER #define m_new_obj_with_finaliser(type) ((type*)(m_malloc_with_finaliser(sizeof(type)))) +#define m_new_obj_var_with_finaliser(type, var_type, var_num) ((type*)m_malloc_with_finaliser(sizeof(type) + sizeof(var_type) * (var_num))) #else #define m_new_obj_with_finaliser(type) m_new_obj(type) +#define m_new_obj_var_with_finaliser(type, var_type, var_num) m_new_obj_var(type, var_type, var_num) #endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #define m_renew(type, ptr, old_num, new_num) ((type*)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) @@ -119,8 +121,15 @@ typedef uint32_t unichar; typedef uint unichar; #endif +#if MICROPY_PY_BUILTINS_STR_UNICODE unichar utf8_get_char(const byte *s); const byte *utf8_next_char(const byte *s); +size_t utf8_charlen(const byte *str, size_t len); +#else +static inline unichar utf8_get_char(const byte *s) { return *s; } +static inline const byte *utf8_next_char(const byte *s) { return s + 1; } +static inline size_t utf8_charlen(const byte *str, size_t len) { (void)str; return len; } +#endif bool unichar_isspace(unichar c); bool unichar_isalpha(unichar c); @@ -133,7 +142,6 @@ bool unichar_islower(unichar c); unichar unichar_tolower(unichar c); unichar unichar_toupper(unichar c); mp_uint_t unichar_xdigit_value(unichar c); -mp_uint_t unichar_charlen(const char *str, mp_uint_t len); #define UTF8_IS_NONASCII(ch) ((ch) & 0x80) #define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80) @@ -196,20 +204,6 @@ int DEBUG_printf(const char *fmt, ...); extern mp_uint_t mp_verbose_flag; -// This is useful for unicode handling. Some CPU archs has -// special instructions for efficient implementation of this -// function (e.g. CLZ on ARM). -// NOTE: this function is unused at the moment -#ifndef count_lead_ones -static inline mp_uint_t count_lead_ones(byte val) { - mp_uint_t c = 0; - for (byte mask = 0x80; val & mask; mask >>= 1) { - c++; - } - return c; -} -#endif - /** float internals *************/ #if MICROPY_PY_BUILTINS_FLOAT diff --git a/MicroPython_BUILD/components/micropython/py/mkrules.mk b/MicroPython_BUILD/components/micropython/py/mkrules.mk index ac5ddb15..e78abe41 100644 --- a/MicroPython_BUILD/components/micropython/py/mkrules.mk +++ b/MicroPython_BUILD/components/micropython/py/mkrules.mk @@ -33,7 +33,7 @@ endif define compile_c $(ECHO) "_CC_ $<" -$(Q)$(CC) -I$(MP_EXTRA_INC) $(CFLAGS) -c -MD -o $@ $< +$(Q)$(CC) -I$(MP_EXTRA_INC) $(CFLAGS) $(CPPFLAGS) -c -MD -o $@ $< #@ The following fixes the dependency file. #@ See http://make.paulandlesley.org/autodep.html for details. #@ Regex adjusted from the above to play better with Windows paths, etc. @@ -112,7 +112,7 @@ FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:. $(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py @$(ECHO) "MPY $<" $(Q)$(MKDIR) -p $(dir $@) - $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $< + $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $< # to build frozen_mpy.c from all .mpy files $(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h diff --git a/MicroPython_BUILD/components/micropython/py/modbuiltins.c b/MicroPython_BUILD/components/micropython/py/modbuiltins.c index 65c03d52..23c21ca2 100644 --- a/MicroPython_BUILD/components/micropython/py/modbuiltins.c +++ b/MicroPython_BUILD/components/micropython/py/modbuiltins.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -137,7 +138,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable); STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { #if MICROPY_PY_BUILTINS_STR_UNICODE mp_uint_t c = mp_obj_get_int(o_in); - char str[4]; + uint8_t str[4]; int len = 0; if (c < 0x80) { *str = c; len = 1; @@ -159,12 +160,12 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { } else { mp_raise_ValueError("chr() arg not in range(0x110000)"); } - return mp_obj_new_str(str, len, true); + return mp_obj_new_str_via_qstr((char*)str, len); #else mp_int_t ord = mp_obj_get_int(o_in); if (0 <= ord && ord <= 0xff) { - char str[1] = {ord}; - return mp_obj_new_str(str, 1, true); + uint8_t str[1] = {ord}; + return mp_obj_new_str_via_qstr((char*)str, 1); } else { mp_raise_ValueError("chr() arg not in range(256)"); } @@ -173,46 +174,31 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr); STATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) { - // TODO make this function more general and less of a hack - - mp_obj_dict_t *dict = NULL; - mp_map_t *members = NULL; - if (n_args == 0) { - // make a list of names in the local name space - dict = mp_locals_get(); - } else { // n_args == 1 - // make a list of names in the given object - if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) { - dict = mp_obj_module_get_globals(args[0]); - } else { - mp_obj_type_t *type; - if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { - type = MP_OBJ_TO_PTR(args[0]); - } else { - type = mp_obj_get_type(args[0]); - } - if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) { - dict = type->locals_dict; - } - } - if (mp_obj_is_instance_type(mp_obj_get_type(args[0]))) { - mp_obj_instance_t *inst = MP_OBJ_TO_PTR(args[0]); - members = &inst->members; - } - } - mp_obj_t dir = mp_obj_new_list(0, NULL); - if (dict != NULL) { + if (n_args == 0) { + // Make a list of names in the local namespace + mp_obj_dict_t *dict = mp_locals_get(); for (size_t i = 0; i < dict->map.alloc; i++) { if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { mp_obj_list_append(dir, dict->map.table[i].key); } } - } - if (members != NULL) { - for (size_t i = 0; i < members->alloc; i++) { - if (MP_MAP_SLOT_IS_FILLED(members, i)) { - mp_obj_list_append(dir, members->table[i].key); + } else { // n_args == 1 + // Make a list of names in the given object + // Implemented by probing all possible qstrs with mp_load_method_maybe + size_t nqstr = QSTR_TOTAL(); + for (size_t i = MP_QSTR_ + 1; i < nqstr; ++i) { + mp_obj_t dest[2]; + mp_load_method_protected(args[0], i, dest, false); + if (dest[0] != MP_OBJ_NULL) { + #if MICROPY_PY_ALL_SPECIAL_METHODS + // Support for __dir__: see if we can dispatch to this special method + // This relies on MP_QSTR__dir__ being first after MP_QSTR_ + if (i == MP_QSTR___dir__ && dest[1] != MP_OBJ_NULL) { + return mp_call_method_n_kw(0, 0, dest); + } + #endif + mp_obj_list_append(dir, MP_OBJ_NEW_QSTR(i)); } } } @@ -343,19 +329,19 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct); STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { size_t len; - const char *str = mp_obj_str_get_data(o_in, &len); + const byte *str = (const byte*)mp_obj_str_get_data(o_in, &len); #if MICROPY_PY_BUILTINS_STR_UNICODE if (MP_OBJ_IS_STR(o_in)) { - len = unichar_charlen(str, len); + len = utf8_charlen(str, len); if (len == 1) { - return mp_obj_new_int(utf8_get_char((const byte*)str)); + return mp_obj_new_int(utf8_get_char(str)); } } else #endif { // a bytes object, or a str without unicode support (don't sign extend the char) if (len == 1) { - return MP_OBJ_NEW_SMALL_INT(((const byte*)str)[0]); + return MP_OBJ_NEW_SMALL_INT(str[0]); } } @@ -383,46 +369,52 @@ STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow); -STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP); - mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP); - const char *sep_data = " "; - size_t sep_len = 1; - const char *end_data = "\n"; - size_t end_len = 1; - if (sep_elem != NULL && sep_elem->value != mp_const_none) { - sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len); - } - if (end_elem != NULL && end_elem->value != mp_const_none) { - end_data = mp_obj_str_get_data(end_elem->value, &end_len); - } - #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES - void *stream_obj = &mp_sys_stdout_obj; - mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP); - if (file_elem != NULL && file_elem->value != mp_const_none) { - stream_obj = MP_OBJ_TO_PTR(file_elem->value); // XXX may not be a concrete object - } +STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sep, ARG_end, ARG_file }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__space_)} }, + { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__0x0a_)} }, + #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES + { MP_QSTR_file, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_sys_stdout_obj)} }, + #endif + }; + + // parse args (a union is used to reduce the amount of C stack that is needed) + union { + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + size_t len[2]; + } u; + mp_arg_parse_all(0, NULL, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, u.args); - mp_print_t print = {stream_obj, mp_stream_write_adaptor}; + #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES + // TODO file may not be a concrete object (eg it could be a small-int) + mp_print_t print = {MP_OBJ_TO_PTR(u.args[ARG_file].u_obj), mp_stream_write_adaptor}; #endif + + // extract the objects first because we are going to use the other part of the union + mp_obj_t sep = u.args[ARG_sep].u_obj; + mp_obj_t end = u.args[ARG_end].u_obj; + const char *sep_data = mp_obj_str_get_data(sep, &u.len[0]); + const char *end_data = mp_obj_str_get_data(end, &u.len[1]); + for (size_t i = 0; i < n_args; i++) { if (i > 0) { #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES - mp_stream_write_adaptor(stream_obj, sep_data, sep_len); + mp_stream_write_adaptor(print.data, sep_data, u.len[0]); #else - mp_print_strn(&mp_plat_print, sep_data, sep_len, 0, 0, 0); + mp_print_strn(&mp_plat_print, sep_data, u.len[0], 0, 0, 0); #endif } #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES - mp_obj_print_helper(&print, args[i], PRINT_STR); + mp_obj_print_helper(&print, pos_args[i], PRINT_STR); #else - mp_obj_print_helper(&mp_plat_print, args[i], PRINT_STR); + mp_obj_print_helper(&mp_plat_print, pos_args[i], PRINT_STR); #endif } #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES - mp_stream_write_adaptor(stream_obj, end_data, end_len); + mp_stream_write_adaptor(print.data, end_data, u.len[1]); #else - mp_print_strn(&mp_plat_print, end_data, end_len, 0, 0, 0); + mp_print_strn(&mp_plat_print, end_data, u.len[1], 0, 0, 0); #endif return mp_const_none; } @@ -457,16 +449,14 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { return o_in; } #if MICROPY_PY_BUILTINS_FLOAT - mp_int_t num_dig = 0; + mp_float_t val = mp_obj_get_float(o_in); if (n_args > 1) { - num_dig = mp_obj_get_int(args[1]); - mp_float_t val = mp_obj_get_float(o_in); + mp_int_t num_dig = mp_obj_get_int(args[1]); mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig); // TODO may lead to overflow mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val * mult) / mult; return mp_obj_new_float(rounded); } - mp_float_t val = mp_obj_get_float(o_in); mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val); return mp_obj_new_int_from_float(rounded); #else @@ -543,14 +533,8 @@ MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj, mp_builtin_delattr); STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) { qstr attr = mp_obj_str_get_qstr(attr_in); - mp_obj_t dest[2]; - // TODO: https://docs.python.org/3/library/functions.html?highlight=hasattr#hasattr - // explicitly says "This is implemented by calling getattr(object, name) and seeing - // whether it raises an AttributeError or not.", so we should explicitly wrap this - // in nlr_push and handle exception. - mp_load_method_maybe(object_in, attr, dest); - + mp_load_method_protected(object_in, attr, dest, false); return mp_obj_new_bool(dest[0] != MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj, mp_builtin_hasattr); @@ -565,6 +549,23 @@ STATIC mp_obj_t mp_builtin_locals(void) { } MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_builtin_locals); +// LoBo: Get or set float print precision +extern int float_precision; +//----------------------------------------------------------------------------------- +STATIC mp_obj_t mp_builtin_set_float_precision(size_t n_args, const mp_obj_t *args) { + if (n_args > 0) { + mp_int_t prec = mp_obj_get_int(args[0]); + if ((prec >= 4) && (prec <= 16)) { + float_precision = prec; + } + else { + mp_raise_ValueError("Precision must be 4 - 16"); + } + } + return mp_obj_new_int(float_precision); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_set_float_precision_obj, 0, 1, mp_builtin_set_float_precision); + // These are defined in terms of MicroPython API functions right away MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_obj_id); MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_obj_len); @@ -687,6 +688,7 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_round), MP_ROM_PTR(&mp_builtin_round_obj) }, { MP_ROM_QSTR(MP_QSTR_sorted), MP_ROM_PTR(&mp_builtin_sorted_obj) }, { MP_ROM_QSTR(MP_QSTR_sum), MP_ROM_PTR(&mp_builtin_sum_obj) }, + { MP_ROM_QSTR(MP_QSTR_float_precision), MP_ROM_PTR(&mp_builtin_set_float_precision_obj) }, // built-in exceptions { MP_ROM_QSTR(MP_QSTR_BaseException), MP_ROM_PTR(&mp_type_BaseException) }, diff --git a/MicroPython_BUILD/components/micropython/py/modcollections.c b/MicroPython_BUILD/components/micropython/py/modcollections.c index 1a156038..bb648847 100644 --- a/MicroPython_BUILD/components/micropython/py/modcollections.c +++ b/MicroPython_BUILD/components/micropython/py/modcollections.c @@ -30,6 +30,9 @@ STATIC const mp_rom_map_elem_t mp_module_collections_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucollections) }, + #if MICROPY_PY_COLLECTIONS_DEQUE + { MP_ROM_QSTR(MP_QSTR_deque), MP_ROM_PTR(&mp_type_deque) }, + #endif { MP_ROM_QSTR(MP_QSTR_namedtuple), MP_ROM_PTR(&mp_namedtuple_obj) }, #if MICROPY_PY_COLLECTIONS_ORDEREDDICT { MP_ROM_QSTR(MP_QSTR_OrderedDict), MP_ROM_PTR(&mp_type_ordereddict) }, diff --git a/MicroPython_BUILD/components/micropython/py/modgc.c b/MicroPython_BUILD/components/micropython/py/modgc.c index 55e73def..3c136c8f 100644 --- a/MicroPython_BUILD/components/micropython/py/modgc.c +++ b/MicroPython_BUILD/components/micropython/py/modgc.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,16 +31,41 @@ #if MICROPY_PY_GC && MICROPY_ENABLE_GC -// collect(): run a garbage collection -STATIC mp_obj_t py_gc_collect(void) { - gc_collect(); -#if MICROPY_PY_GC_COLLECT_RETVAL - return MP_OBJ_NEW_SMALL_INT(MP_STATE_MEM(gc_collected)); -#else +// collect([flag]): run a garbage collection +STATIC mp_obj_t py_gc_collect(size_t n_args, const mp_obj_t *args) { + int flag = 0; + if (n_args > 0) { + flag = mp_obj_get_int(args[0]) & 3; + } + gc_collect(flag); + + #if MICROPY_PY_GC_COLLECT_RETVAL + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_int(MP_STATE_MEM(gc_marked)); + tuple[1] = mp_obj_new_int(MP_STATE_MEM(gc_collected)); + return mp_obj_new_tuple(2, tuple); + #else return mp_const_none; -#endif + #endif +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_collect_obj, 0, 1, py_gc_collect); + +// collect_iflow(): run a garbage collection if more then given value is used +STATIC mp_obj_t py_gc_collect_if(size_t n_args, const mp_obj_t *args) { + int flag = 0; + if (n_args > 1) { + flag = mp_obj_get_int(args[1]) & 3; + } + mp_int_t val = mp_obj_get_int(args[0]); + gc_info_t info; + gc_info(&info); + if (info.used >= val) { + gc_collect(flag); + return mp_const_true; + } + else return mp_const_false; } -MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_collect_if_obj, 1, 2, py_gc_collect_if); // disable(): disable the garbage collector STATIC mp_obj_t gc_disable(void) { @@ -84,27 +110,32 @@ STATIC mp_obj_t gc_threshold(size_t n_args, const mp_obj_t *args) { } return mp_obj_new_int(MP_STATE_MEM(gc_alloc_threshold) * MICROPY_BYTES_PER_GC_BLOCK); } + if (n_args == 2) { + mp_int_t flag = mp_obj_get_int(args[1]) & 3; + MP_STATE_MEM(gc_auto_collect_debug) = flag; + } mp_int_t val = mp_obj_get_int(args[0]); - if (val < 0) { + if (val < 20480) { MP_STATE_MEM(gc_alloc_threshold) = (size_t)-1; } else { - MP_STATE_MEM(gc_alloc_threshold) = val / MICROPY_BYTES_PER_GC_BLOCK; + MP_STATE_MEM(gc_alloc_threshold) = (val&0x7FFFFF00) / MICROPY_BYTES_PER_GC_BLOCK; } return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_threshold_obj, 0, 1, gc_threshold); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_threshold_obj, 0, 2, gc_threshold); #endif STATIC const mp_rom_map_elem_t mp_module_gc_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gc) }, - { MP_ROM_QSTR(MP_QSTR_collect), MP_ROM_PTR(&gc_collect_obj) }, - { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&gc_disable_obj) }, - { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&gc_enable_obj) }, - { MP_ROM_QSTR(MP_QSTR_isenabled), MP_ROM_PTR(&gc_isenabled_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem_free), MP_ROM_PTR(&gc_mem_free_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem_alloc), MP_ROM_PTR(&gc_mem_alloc_obj) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gc) }, + { MP_ROM_QSTR(MP_QSTR_collect), MP_ROM_PTR(&gc_collect_obj) }, + { MP_ROM_QSTR(MP_QSTR_collectif), MP_ROM_PTR(&gc_collect_if_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&gc_disable_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&gc_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_isenabled), MP_ROM_PTR(&gc_isenabled_obj) }, + { MP_ROM_QSTR(MP_QSTR_mem_free), MP_ROM_PTR(&gc_mem_free_obj) }, + { MP_ROM_QSTR(MP_QSTR_mem_alloc), MP_ROM_PTR(&gc_mem_alloc_obj) }, #if MICROPY_GC_ALLOC_THRESHOLD - { MP_ROM_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&gc_threshold_obj) }, + { MP_ROM_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&gc_threshold_obj) }, #endif }; diff --git a/MicroPython_BUILD/components/micropython/py/modio.c b/MicroPython_BUILD/components/micropython/py/modio.c index 353a0028..3a5c69c4 100644 --- a/MicroPython_BUILD/components/micropython/py/modio.c +++ b/MicroPython_BUILD/components/micropython/py/modio.c @@ -131,7 +131,7 @@ STATIC const mp_obj_type_t bufwriter_type = { }; #endif // MICROPY_PY_IO_BUFFEREDWRITER -#if MICROPY_MODULE_FROZEN_STR +#if MICROPY_PY_IO_RESOURCE_STREAM STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) { VSTR_FIXED(path_buf, MICROPY_ALLOC_PATH_MAX); size_t len; @@ -176,10 +176,10 @@ STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) { return MP_OBJ_FROM_PTR(o); } - mp_obj_t path_out = mp_obj_new_str(path_buf.buf, path_buf.len, false); + mp_obj_t path_out = mp_obj_new_str(path_buf.buf, path_buf.len); return mp_builtin_open(1, &path_out, (mp_map_t*)&mp_const_empty_map); } -MP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream); #endif STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = { diff --git a/MicroPython_BUILD/components/micropython/py/modmath.c b/MicroPython_BUILD/components/micropython/py/modmath.c index 7eda7594..4bf9ba31 100644 --- a/MicroPython_BUILD/components/micropython/py/modmath.c +++ b/MicroPython_BUILD/components/micropython/py/modmath.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013-2017 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -168,8 +169,10 @@ MATH_FUN_1(erfc, erfc) MATH_FUN_1(gamma, tgamma) // lgamma(x): return the natural logarithm of the gamma function of x MATH_FUN_1(lgamma, lgamma) +// hypot(x, y): return sqrt(x*x + y*y) +MATH_FUN_2(hypot, hypot) #endif -//TODO: factorial, fsum +//TODO: fsum // Function that takes a variable number of arguments @@ -232,6 +235,37 @@ STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees); +#include "py/objint.h" +// factorial(x) +STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) { + int n = mp_obj_get_int(x_obj); + if ((n < 0) || (n > 50)) { + mp_raise_ValueError("range error (0 - 50 allowed)"); + } + if (n < 21) { + uint64_t fact = 1; + for (int i = 1; i <= n; i++) { + fact *= i; + } + + return mp_obj_new_int_from_ull(fact); + } + mp_obj_int_t *fact = mp_obj_int_new_mpz(); + mp_obj_int_t *zi = mp_obj_int_new_mpz(); + mp_obj_int_t *z1 = mp_obj_int_new_mpz(); + mpz_set_from_ll(&fact->mpz, 1, true); + mpz_set_from_ll(&zi->mpz, 1, true); + mpz_set_from_ll(&z1->mpz, 1, true); + + for (int i = 1; i <= n; i++) { + mpz_mul_inpl(&fact->mpz, &fact->mpz, &zi->mpz); + mpz_add_inpl(&zi->mpz, &zi->mpz, &z1->mpz); + } + return MP_OBJ_FROM_PTR(fact); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_factorial_obj, mp_math_factorial); + STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_math) }, { MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e }, @@ -274,11 +308,13 @@ STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_trunc), MP_ROM_PTR(&mp_math_trunc_obj) }, { MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&mp_math_radians_obj) }, { MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&mp_math_degrees_obj) }, + { MP_ROM_QSTR(MP_QSTR_factorial), MP_ROM_PTR(&mp_math_factorial_obj) }, #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_erf), MP_ROM_PTR(&mp_math_erf_obj) }, { MP_ROM_QSTR(MP_QSTR_erfc), MP_ROM_PTR(&mp_math_erfc_obj) }, { MP_ROM_QSTR(MP_QSTR_gamma), MP_ROM_PTR(&mp_math_gamma_obj) }, { MP_ROM_QSTR(MP_QSTR_lgamma), MP_ROM_PTR(&mp_math_lgamma_obj) }, + { MP_ROM_QSTR(MP_QSTR_hypot), MP_ROM_PTR(&mp_math_hypot_obj) }, #endif }; diff --git a/MicroPython_BUILD/components/micropython/py/modmicropython.c b/MicroPython_BUILD/components/micropython/py/modmicropython.c index 4ce503fa..38a1eeb1 100644 --- a/MicroPython_BUILD/components/micropython/py/modmicropython.c +++ b/MicroPython_BUILD/components/micropython/py/modmicropython.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,6 +36,7 @@ // Various builtins specific to MicroPython runtime, // living in micropython module +#if MICROPY_ENABLE_COMPILER STATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return MP_OBJ_NEW_SMALL_INT(MP_STATE_VM(mp_optimise_value)); @@ -44,6 +46,7 @@ STATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { } } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_opt_level_obj, 0, 1, mp_micropython_opt_level); +#endif #if MICROPY_PY_MICROPYTHON_MEM_INFO @@ -103,14 +106,21 @@ STATIC mp_obj_t mp_micropython_qstr_info(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_qstr_info_obj, 0, 1, mp_micropython_qstr_info); -#if MICROPY_STACK_CHECK +#endif // MICROPY_PY_MICROPYTHON_MEM_INFO + +#if MICROPY_PY_MICROPYTHON_STACK_USE STATIC mp_obj_t mp_micropython_stack_use(void) { return MP_OBJ_NEW_SMALL_INT(mp_stack_usage()); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_stack_use_obj, mp_micropython_stack_use); #endif -#endif // MICROPY_PY_MICROPYTHON_MEM_INFO +#if MICROPY_ENABLE_PYSTACK +STATIC mp_obj_t mp_micropython_pystack_use(void) { + return MP_OBJ_NEW_SMALL_INT(mp_pystack_usage()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_pystack_use_obj, mp_micropython_pystack_use); +#endif #if MICROPY_ENABLE_GC STATIC mp_obj_t mp_micropython_heap_lock(void) { @@ -151,7 +161,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_micropython_schedule_obj, mp_micropython_sch STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) }, { MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) }, + #if MICROPY_ENABLE_COMPILER { MP_ROM_QSTR(MP_QSTR_opt_level), MP_ROM_PTR(&mp_micropython_opt_level_obj) }, + #endif #if MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS { MP_ROM_QSTR(MP_QSTR_mem_total), MP_ROM_PTR(&mp_micropython_mem_total_obj) }, @@ -160,13 +172,16 @@ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_mem_info), MP_ROM_PTR(&mp_micropython_mem_info_obj) }, { MP_ROM_QSTR(MP_QSTR_qstr_info), MP_ROM_PTR(&mp_micropython_qstr_info_obj) }, - #if MICROPY_STACK_CHECK +#endif + #if MICROPY_PY_MICROPYTHON_STACK_USE { MP_ROM_QSTR(MP_QSTR_stack_use), MP_ROM_PTR(&mp_micropython_stack_use_obj) }, #endif -#endif #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0) { MP_ROM_QSTR(MP_QSTR_alloc_emergency_exception_buf), MP_ROM_PTR(&mp_alloc_emergency_exception_buf_obj) }, #endif + #if MICROPY_ENABLE_PYSTACK + { MP_ROM_QSTR(MP_QSTR_pystack_use), MP_ROM_PTR(&mp_micropython_pystack_use_obj) }, + #endif #if MICROPY_ENABLE_GC { MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) }, { MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) }, diff --git a/MicroPython_BUILD/components/micropython/py/modsys.c b/MicroPython_BUILD/components/micropython/py/modsys.c index 01cd4338..2627d9d5 100644 --- a/MicroPython_BUILD/components/micropython/py/modsys.c +++ b/MicroPython_BUILD/components/micropython/py/modsys.c @@ -5,6 +5,7 @@ * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014-2017 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +26,9 @@ * THE SOFTWARE. */ +#include "sdkconfig.h" +#include +#include #include "py/builtin.h" #include "py/objlist.h" #include "py/objtuple.h" @@ -34,6 +38,9 @@ #include "py/stream.h" #include "py/smallint.h" #include "py/runtime.h" +#include "lib/utils/pyexec.h" +#include "modmachine.h" +#include "machine_rtc.h" #if MICROPY_PY_SYS @@ -99,6 +106,7 @@ STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { exc = mp_obj_new_exception_arg1(&mp_type_SystemExit, args[0]); } nlr_raise(exc); + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit); @@ -140,26 +148,90 @@ STATIC mp_obj_t mp_sys_exc_info(void) { MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info); #endif +#if MICROPY_PY_SYS_GETSIZEOF STATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) { return mp_unary_op(MP_UNARY_OP_SIZEOF, obj); } -MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof); +#endif + +//-------------------------------- +STATIC mp_obj_t mp_sys_mpycore() { + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_str(MICROPY_CORE_VERSION, strlen(MICROPY_CORE_VERSION)); + tuple[1] = mp_obj_new_str(MICROPY_CORE_DATE, strlen(MICROPY_CORE_DATE)); + + return mp_obj_new_tuple(2, tuple); +} +MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_mpycore_obj, mp_sys_mpycore); + +//-------------------------------------- +STATIC mp_obj_t mp_sys_espidf_info(void) +{ + mp_obj_t tuple[3]; + tuple[0] = mp_obj_new_str(MICROPY_ESPIDF_VERSION, strlen(MICROPY_ESPIDF_VERSION)); + tuple[1] = mp_obj_new_str(MICROPY_ESPIDF_HASH, strlen(MICROPY_ESPIDF_HASH)); + tuple[2] = mp_obj_new_str(MICROPY_ESPIDF_DATE, strlen(MICROPY_ESPIDF_DATE)); + + return mp_obj_new_tuple(3, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_espidf_info_obj, mp_sys_espidf_info); + +//------------------------------------------------------------------ +STATIC mp_obj_t mp_sys_timezone(size_t n_args, const mp_obj_t *args) +{ + if (n_args == 0) { + char tzs[64] = {'\0'}; + if (strlen(mpy_time_zone) == 0) { + // Try to get tz from NVS + tz_fromto_NVS(tzs, NULL); + if (strlen(tzs) > 0) { + strcpy(mpy_time_zone, tzs); + setenv("TZ", mpy_time_zone, 1); + tzset(); + } + } + else strcpy(tzs, mpy_time_zone); + } + else { + const char *newtzs = mp_obj_str_get_str(args[0]); + if (strcmp(newtzs, mpy_time_zone) != 0) { + if ((strlen(newtzs) > 2) && (strlen(newtzs) < 64)) { + sprintf(mpy_time_zone, "%s", newtzs); + tz_fromto_NVS(NULL, mpy_time_zone); + } + else { + mp_raise_ValueError("tz string length must be 3 - 64"); + } + } + setenv("TZ", mpy_time_zone, 1); + tzset(); + } + + return mp_obj_new_str(mpy_time_zone, strlen(mpy_time_zone)); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_timezone_obj, 0, 1, mp_sys_timezone); + +//============================================================== STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) }, - { MP_ROM_QSTR(MP_QSTR_path), MP_ROM_PTR(&MP_STATE_VM(mp_sys_path_obj)) }, - { MP_ROM_QSTR(MP_QSTR_argv), MP_ROM_PTR(&MP_STATE_VM(mp_sys_argv_obj)) }, - { MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&version_obj) }, - { MP_ROM_QSTR(MP_QSTR_version_info), MP_ROM_PTR(&mp_sys_version_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_implementation), MP_ROM_PTR(&mp_sys_implementation_obj) }, + { MP_ROM_QSTR(MP_QSTR_path), MP_ROM_PTR(&MP_STATE_VM(mp_sys_path_obj)) }, + { MP_ROM_QSTR(MP_QSTR_argv), MP_ROM_PTR(&MP_STATE_VM(mp_sys_argv_obj)) }, + { MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&version_obj) }, + { MP_ROM_QSTR(MP_QSTR_version_info), MP_ROM_PTR(&mp_sys_version_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_espidf_info), MP_ROM_PTR(&mp_sys_espidf_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_implementation), MP_ROM_PTR(&mp_sys_implementation_obj) }, + { MP_ROM_QSTR(MP_QSTR_mpycore), MP_ROM_PTR(&mp_sys_mpycore_obj) }, + { MP_ROM_QSTR(MP_QSTR_tz), MP_ROM_PTR(&mp_sys_timezone_obj) }, #ifdef MICROPY_PY_SYS_PLATFORM - { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_obj) }, + { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_obj) }, #endif #if MP_ENDIANNESS_LITTLE - { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_little) }, + { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_little) }, #else - { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_big) }, + { MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_big) }, #endif #if MICROPY_PY_SYS_MAXSIZE @@ -169,37 +241,37 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { // to not try to compare sys.maxsize to some literal number (as this // number might not fit in available int size), but instead count number // of "one" bits in sys.maxsize. - { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_INT(MP_SMALL_INT_MAX) }, + { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_INT(MP_SMALL_INT_MAX) }, #else - { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_PTR(&mp_maxsize_obj) }, + { MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_PTR(&mp_maxsize_obj) }, #endif #endif #if MICROPY_PY_SYS_EXIT - { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mp_sys_exit_obj) }, + { MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mp_sys_exit_obj) }, #endif #if MICROPY_PY_SYS_STDFILES - { MP_ROM_QSTR(MP_QSTR_stdin), MP_ROM_PTR(&mp_sys_stdin_obj) }, - { MP_ROM_QSTR(MP_QSTR_stdout), MP_ROM_PTR(&mp_sys_stdout_obj) }, - { MP_ROM_QSTR(MP_QSTR_stderr), MP_ROM_PTR(&mp_sys_stderr_obj) }, + { MP_ROM_QSTR(MP_QSTR_stdin), MP_ROM_PTR(&mp_sys_stdin_obj) }, + { MP_ROM_QSTR(MP_QSTR_stdout), MP_ROM_PTR(&mp_sys_stdout_obj) }, + { MP_ROM_QSTR(MP_QSTR_stderr), MP_ROM_PTR(&mp_sys_stderr_obj) }, #endif #if MICROPY_PY_SYS_MODULES - { MP_ROM_QSTR(MP_QSTR_modules), MP_ROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)) }, + { MP_ROM_QSTR(MP_QSTR_modules), MP_ROM_PTR(&MP_STATE_VM(mp_loaded_modules_dict)) }, #endif #if MICROPY_PY_SYS_EXC_INFO - { MP_ROM_QSTR(MP_QSTR_exc_info), MP_ROM_PTR(&mp_sys_exc_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_exc_info), MP_ROM_PTR(&mp_sys_exc_info_obj) }, #endif #if MICROPY_PY_SYS_GETSIZEOF - { MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) }, + { MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) }, #endif /* * Extensions to CPython */ - { MP_ROM_QSTR(MP_QSTR_print_exception), MP_ROM_PTR(&mp_sys_print_exception_obj) }, + { MP_ROM_QSTR(MP_QSTR_print_exception), MP_ROM_PTR(&mp_sys_print_exception_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table); diff --git a/MicroPython_BUILD/components/micropython/py/modthread.c b/MicroPython_BUILD/components/micropython/py/modthread.c index 60f225af..3b547c2b 100644 --- a/MicroPython_BUILD/components/micropython/py/modthread.c +++ b/MicroPython_BUILD/components/micropython/py/modthread.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,16 +33,15 @@ #if MICROPY_PY_THREAD +#include "soc/cpu.h" #include "py/mpthread.h" #include "mphalport.h" -extern TaskHandle_t MainTaskHandle; - /****************************************************************/ // _thread module -STATIC size_t thread_stack_size = MP_THREAD_DEFAULT_STACK_SIZE; +size_t thread_stack_size = MP_THREAD_DEFAULT_STACK_SIZE; //-------------------------------------------------------------------------- STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) { @@ -77,10 +77,10 @@ typedef struct _thread_entry_args_t { mp_obj_t args[]; } thread_entry_args_t; -//-------------------------------------- -STATIC void *thread_entry(void *args_in) +//------------------------------- +void *thread_entry(void *args_in) { - // Execution begins here for a new thread. We do not have the GIL. + // === Execution begins here for a new thread. We do not have the GIL. === thread_entry_args_t *args = (thread_entry_args_t*)args_in; @@ -96,6 +96,18 @@ STATIC void *thread_entry(void *args_in) MP_THREAD_GIL_ENTER(); + #if MICROPY_ENABLE_PYSTACK + // TODO threading and pystack is not fully supported, for now just make a small stack + mp_obj_t mini_pystack[128]; + mp_pystack_init(mini_pystack, &mini_pystack[128]); + #endif + + volatile uint32_t sp = (uint32_t)get_sp(); + mp_thread_set_sp((void *)sp, MP_STATE_THREAD(stack_top)); + + void **ptrs = (void**)(void*)&mp_state_ctx; + mp_thread_set_ptrs(ptrs, offsetof(mp_state_ctx_t, vm.qstr_last_chunk) / sizeof(void*)); + // signal that we are set up and running mp_thread_start(); @@ -105,6 +117,7 @@ STATIC void *thread_entry(void *args_in) nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { + // === Start executing the byte code === mp_call_function_n_kw(args->fun, args->n_args, args->n_kw, args->args); nlr_pop(); } else { @@ -305,10 +318,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_thread_isnotified_obj, mod_thread_isnotifie //-------------------------------------- STATIC mp_obj_t mod_thread_getREPLId() { - return mp_obj_new_int_from_uint((uintptr_t)MainTaskHandle); + return mp_obj_new_int_from_uint((uintptr_t)ReplTaskHandle); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_getREPLId_obj, mod_thread_getREPLId); +//-------------------------------------- +STATIC mp_obj_t mod_thread_getMAINId() { + return mp_obj_new_int_from_uint((uintptr_t)MainTaskHandle); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_getMAINId_obj, mod_thread_getMAINId); + //-------------------------------------- STATIC mp_obj_t mod_thread_getnotify() { @@ -376,7 +395,7 @@ STATIC mp_obj_t mod_thread_getmsg() } else if (res == THREAD_MSG_TYPE_STRING) { if (buf != NULL) { - tuple[2] = mp_obj_new_str((char *)buf, buflen, false); + tuple[2] = mp_obj_new_str((char *)buf, buflen); free(buf); } else tuple[2] = mp_const_none; @@ -395,7 +414,7 @@ STATIC mp_obj_t mod_thread_getname(mp_obj_t in_id) { if (!res) { sprintf(name,"unknown"); } - return mp_obj_new_str((char *)name, strlen(name), false); + return mp_obj_new_str((char *)name, strlen(name)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_thread_getname_obj, mod_thread_getname); @@ -407,7 +426,7 @@ STATIC mp_obj_t mod_thread_getSelfname() { if (!res) { sprintf(name,"unknown"); } - return mp_obj_new_str((char *)name, strlen(name), false); + return mp_obj_new_str((char *)name, strlen(name)); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_getSelfname_obj, mod_thread_getSelfname); @@ -432,6 +451,7 @@ STATIC mp_obj_t mod_thread_list(mp_uint_t n_args, const mp_obj_t *args) { char th_type[8] = {'\0'}; char th_state[16] = {'\0'}; if (thr->type == THREAD_TYPE_MAIN) sprintf(th_type, "MAIN"); + else if (thr->type == THREAD_TYPE_REPL) sprintf(th_type, "REPL"); else if (thr->type == THREAD_TYPE_PYTHON) sprintf(th_type, "PYTHON"); else if (thr->type == THREAD_TYPE_SERVICE) sprintf(th_type, "SERVICE"); else sprintf(th_type, "Unknown"); @@ -444,27 +464,36 @@ STATIC mp_obj_t mod_thread_list(mp_uint_t n_args, const mp_obj_t *args) { thr->stack_max, th_type); } free(list.threads); + #ifdef CONFIG_MICROPY_USE_TELNET if (TelnetTaskHandle) { mp_printf(&mp_plat_print, "ID=%u, Name: Telnet, Stack=%d, MaxUsed=%d, Type: SERVICE\n", TelnetTaskHandle, TELNET_STACK_LEN, TELNET_STACK_LEN - uxTaskGetStackHighWaterMark(TelnetTaskHandle)); } + #endif + + #ifdef CONFIG_MICROPY_USE_FTPSERVER if (FtpTaskHandle) { mp_printf(&mp_plat_print, "ID=%u, Name: Ftp, Stack=%d, MaxUsed=%d, Type: SERVICE\n", FtpTaskHandle, FTP_STACK_LEN, FTP_STACK_LEN - uxTaskGetStackHighWaterMark(FtpTaskHandle)); } + #endif return mp_const_none; } else { int services = 0; + #ifdef CONFIG_MICROPY_USE_TELNET if (TelnetTaskHandle) services++; + #endif + #ifdef CONFIG_MICROPY_USE_FTPSERVER if (FtpTaskHandle) services++; + #endif mp_obj_t thr_info[6]; mp_obj_t tuple[num+services]; for (n=0; nid); thr_info[1] = mp_obj_new_int(thr->type); - thr_info[2] = mp_obj_new_str(thr->name, strlen(thr->name), false); + thr_info[2] = mp_obj_new_str(thr->name, strlen(thr->name)); if (thr->suspended) thr_info[3] = mp_obj_new_int(1); else if (thr->waiting) thr_info[3] = mp_obj_new_int(2); else thr_info[3] = mp_obj_new_int(0); @@ -473,26 +502,30 @@ STATIC mp_obj_t mod_thread_list(mp_uint_t n_args, const mp_obj_t *args) { tuple[n] = mp_obj_new_tuple(6, thr_info); } free(list.threads); + #ifdef CONFIG_MICROPY_USE_TELNET if (TelnetTaskHandle) { thr_info[0] = mp_obj_new_int((int)TelnetTaskHandle); thr_info[1] = mp_obj_new_int(THREAD_TYPE_SERVICE); - thr_info[2] = mp_obj_new_str("Telnet", 6, false); + thr_info[2] = mp_obj_new_str("Telnet", 6); thr_info[3] = mp_obj_new_int(0); thr_info[4] = mp_obj_new_int(TELNET_STACK_LEN); thr_info[5] = mp_obj_new_int(TELNET_STACK_LEN - uxTaskGetStackHighWaterMark(TelnetTaskHandle)); tuple[n] = mp_obj_new_tuple(6, thr_info); n++; } + #endif + #ifdef CONFIG_MICROPY_USE_FTPSERVER if (FtpTaskHandle) { thr_info[0] = mp_obj_new_int((int)FtpTaskHandle); thr_info[1] = mp_obj_new_int(THREAD_TYPE_SERVICE); - thr_info[2] = mp_obj_new_str("Ftp", 3, false); + thr_info[2] = mp_obj_new_str("Ftp", 3); thr_info[3] = mp_obj_new_int(0); thr_info[4] = mp_obj_new_int(FTP_STACK_LEN); thr_info[5] = mp_obj_new_int(FTP_STACK_LEN - uxTaskGetStackHighWaterMark(FtpTaskHandle)); tuple[n] = mp_obj_new_tuple(6, thr_info); n++; } + #endif return mp_obj_new_tuple(n, tuple); } @@ -512,6 +545,19 @@ STATIC mp_obj_t mod_thread_replAcceptMsg(mp_uint_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_replAcceptMsg_obj, 0, 1, mod_thread_replAcceptMsg); +//-------------------------------------------------------------------------------- +STATIC mp_obj_t mod_thread_mainAcceptMsg(mp_uint_t n_args, const mp_obj_t *args) { + int res = 0; + if (n_args == 0) { + res = mp_thread_mainAcceptMsg(-1); + } + else { + res = mp_thread_mainAcceptMsg(mp_obj_is_true(args[0])); + } + return mp_obj_new_bool(res); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_mainAcceptMsg_obj, 0, 1, mod_thread_mainAcceptMsg); + //----------------------------------------------------------------------------- STATIC mp_obj_t mod_thread_waitnotify(mp_uint_t n_args, const mp_obj_t *args) { uint32_t tmo = portMAX_DELAY; @@ -568,7 +614,9 @@ STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_getnotification), MP_ROM_PTR(&mod_thread_getnotify_obj) }, { MP_ROM_QSTR(MP_QSTR_isnotified), MP_ROM_PTR(&mod_thread_isnotified_obj) }, { MP_ROM_QSTR(MP_QSTR_getReplID), MP_ROM_PTR(&mod_thread_getREPLId_obj) }, + { MP_ROM_QSTR(MP_QSTR_getMainID), MP_ROM_PTR(&mod_thread_getMAINId_obj) }, { MP_ROM_QSTR(MP_QSTR_replAcceptMsg), MP_ROM_PTR(&mod_thread_replAcceptMsg_obj) }, + { MP_ROM_QSTR(MP_QSTR_mainAcceptMsg), MP_ROM_PTR(&mod_thread_mainAcceptMsg_obj) }, { MP_ROM_QSTR(MP_QSTR_sendmsg), MP_ROM_PTR(&mod_thread_sendmsg_obj) }, { MP_ROM_QSTR(MP_QSTR_getmsg), MP_ROM_PTR(&mod_thread_getmsg_obj) }, { MP_ROM_QSTR(MP_QSTR_list), MP_ROM_PTR(&mod_thread_list_obj) }, diff --git a/MicroPython_BUILD/components/micropython/py/mpconfig.h b/MicroPython_BUILD/components/micropython/py/mpconfig.h index 4727e6e8..edb6fa6c 100644 --- a/MicroPython_BUILD/components/micropython/py/mpconfig.h +++ b/MicroPython_BUILD/components/micropython/py/mpconfig.h @@ -79,7 +79,7 @@ // - seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 64-bit fp, e != 0x7ff // - s1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 +/- inf // - 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 normalised nan -// - 01111111 11111101 00000000 00000000 iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int +// - 01111111 11111101 iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int // - 01111111 11111110 00000000 00000000 qqqqqqqq qqqqqqqq qqqqqqqq qqqqqqq1 str // - 01111111 11111100 00000000 00000000 pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment) // Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000. @@ -347,7 +347,7 @@ #endif // Whether to enable optimisation of: a, b, c = d, e, f -// Cost 156 bytes (Thumb2) +// Requires MICROPY_COMP_DOUBLE_TUPLE_ASSIGN and costs 68 bytes (Thumb2) #ifndef MICROPY_COMP_TRIPLE_TUPLE_ASSIGN #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0) #endif @@ -405,6 +405,13 @@ /*****************************************************************************/ /* Python internal features */ +// Whether to enable import of external modules +// When disabled, only importing of built-in modules is supported +// When enabled, a port must implement mp_import_stat (among other things) +#ifndef MICROPY_ENABLE_EXTERNAL_IMPORT +#define MICROPY_ENABLE_EXTERNAL_IMPORT (1) +#endif + // Whether to use the POSIX reader for importing files #ifndef MICROPY_READER_POSIX #define MICROPY_READER_POSIX (0) @@ -441,6 +448,17 @@ #define MICROPY_ENABLE_FINALISER (0) #endif +// Whether to enable a separate allocator for the Python stack. +// If enabled then the code must call mp_pystack_init before mp_init. +#ifndef MICROPY_ENABLE_PYSTACK +#define MICROPY_ENABLE_PYSTACK (0) +#endif + +// Number of bytes that memory returned by mp_pystack_alloc will be aligned by. +#ifndef MICROPY_PYSTACK_ALIGN +#define MICROPY_PYSTACK_ALIGN (8) +#endif + // Whether to check C stack usage. C stack used for calling Python functions, // etc. Not checking means segfault on overflow. #ifndef MICROPY_STACK_CHECK @@ -666,6 +684,13 @@ typedef double mp_float_t; /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ +// Whether to support multiple inheritance of Python classes. Multiple +// inheritance makes some C functions inherently recursive, and adds a bit of +// code overhead. +#ifndef MICROPY_MULTIPLE_INHERITANCE +#define MICROPY_MULTIPLE_INHERITANCE (1) +#endif + // Whether to implement attributes on functions #ifndef MICROPY_PY_FUNCTION_ATTRS #define MICROPY_PY_FUNCTION_ATTRS (0) @@ -688,6 +713,15 @@ typedef double mp_float_t; #define MICROPY_PY_ASYNC_AWAIT (1) #endif +// Non-standard .pend_throw() method for generators, allowing for +// Future-like behavior with respect to exception handling: an +// exception set with .pend_throw() will activate on the next call +// to generator's .send() or .__next__(). (This is useful to implement +// async schedulers.) +#ifndef MICROPY_PY_GENERATOR_PEND_THROW +#define MICROPY_PY_GENERATOR_PEND_THROW (1) +#endif + // Issue a warning when comparing str and bytes objects #ifndef MICROPY_PY_STR_BYTES_CMP_WARN #define MICROPY_PY_STR_BYTES_CMP_WARN (0) @@ -760,6 +794,14 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) #endif +// Whether to support binary ops [only (in)equality is defined] between range +// objects. With this option disabled all range objects that are not exactly +// the same object will compare as not-equal. With it enabled the semantics +// match CPython and ranges are equal if they yield the same sequence of items. +#ifndef MICROPY_PY_BUILTINS_RANGE_BINOP +#define MICROPY_PY_BUILTINS_RANGE_BINOP (0) +#endif + // Whether to support timeout exceptions (like socket.timeout) #ifndef MICROPY_PY_BUILTINS_TIMEOUTERROR #define MICROPY_PY_BUILTINS_TIMEOUTERROR (0) @@ -865,6 +907,11 @@ typedef double mp_float_t; #define MICROPY_PY_MICROPYTHON_MEM_INFO (0) #endif +// Whether to provide "micropython.stack_use" function +#ifndef MICROPY_PY_MICROPYTHON_STACK_USE +#define MICROPY_PY_MICROPYTHON_STACK_USE (MICROPY_PY_MICROPYTHON_MEM_INFO) +#endif + // Whether to provide "array" module. Note that large chunk of the // underlying code is shared with "bytearray" builtin type, so to // get real savings, it should be disabled too. @@ -889,11 +936,21 @@ typedef double mp_float_t; #define MICROPY_PY_COLLECTIONS (1) #endif +// Whether to provide "ucollections.deque" type +#ifndef MICROPY_PY_COLLECTIONS_DEQUE +#define MICROPY_PY_COLLECTIONS_DEQUE (0) +#endif + // Whether to provide "collections.OrderedDict" type #ifndef MICROPY_PY_COLLECTIONS_ORDEREDDICT #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) #endif +// Whether to provide the _asdict function for namedtuple +#ifndef MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT +#define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (0) +#endif + // Whether to provide "math" module #ifndef MICROPY_PY_MATH #define MICROPY_PY_MATH (1) @@ -926,7 +983,11 @@ typedef double mp_float_t; // Whether to provide "uio.resource_stream()" function with // the semantics of CPython's pkg_resources.resource_stream() -// (allows to access resources in frozen packages). +// (allows to access binary resources in frozen source packages). +// Note that the same functionality can be achieved in "pure +// Python" by prepocessing binary resources into Python source +// and bytecode-freezing it (with a simple helper module available +// e.g. in micropython-lib). #ifndef MICROPY_PY_IO_RESOURCE_STREAM #define MICROPY_PY_IO_RESOURCE_STREAM (0) #endif @@ -1294,4 +1355,24 @@ typedef double mp_float_t; #define MP_UNLIKELY(x) __builtin_expect((x), 0) #endif +#ifndef MP_HTOBE16 +#if MP_ENDIANNESS_LITTLE +# define MP_HTOBE16(x) ((uint16_t)( (((x) & 0xff) << 8) | (((x) >> 8) & 0xff) )) +# define MP_BE16TOH(x) MP_HTOBE16(x) +#else +# define MP_HTOBE16(x) (x) +# define MP_BE16TOH(x) (x) +#endif +#endif + +#ifndef MP_HTOBE32 +#if MP_ENDIANNESS_LITTLE +# define MP_HTOBE32(x) ((uint32_t)( (((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff) )) +# define MP_BE32TOH(x) MP_HTOBE32(x) +#else +# define MP_HTOBE32(x) (x) +# define MP_BE32TOH(x) (x) +#endif +#endif + #endif // MICROPY_INCLUDED_PY_MPCONFIG_H diff --git a/MicroPython_BUILD/components/micropython/py/mperrno.h b/MicroPython_BUILD/components/micropython/py/mperrno.h index f439f655..0cad75a1 100644 --- a/MicroPython_BUILD/components/micropython/py/mperrno.h +++ b/MicroPython_BUILD/components/micropython/py/mperrno.h @@ -122,7 +122,7 @@ #define MP_EPIPE EPIPE #define MP_EDOM EDOM #define MP_ERANGE ERANGE -#define MP_EWOULDBLOCK EAGAIN +#define MP_EWOULDBLOCK EWOULDBLOCK #define MP_EOPNOTSUPP EOPNOTSUPP #define MP_EAFNOSUPPORT EAFNOSUPPORT #define MP_EADDRINUSE EADDRINUSE diff --git a/MicroPython_BUILD/components/micropython/py/mphal.h b/MicroPython_BUILD/components/micropython/py/mphal.h index 168c9141..c3fee04c 100644 --- a/MicroPython_BUILD/components/micropython/py/mphal.h +++ b/MicroPython_BUILD/components/micropython/py/mphal.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2015 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/py/mpprint.c b/MicroPython_BUILD/components/micropython/py/mpprint.c index a569ef79..c2e65301 100644 --- a/MicroPython_BUILD/components/micropython/py/mpprint.c +++ b/MicroPython_BUILD/components/micropython/py/mpprint.c @@ -446,11 +446,16 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { } } - // parse long specifiers (current not used) - //bool long_arg = false; + // parse long specifiers (only for LP64 model where they make a difference) + #ifndef __LP64__ + const + #endif + bool long_arg = false; if (*fmt == 'l') { ++fmt; - //long_arg = true; + #ifdef __LP64__ + long_arg = true; + #endif } if (*fmt == '\0') { @@ -505,14 +510,21 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { chrs += mp_print_int(print, va_arg(args, int), 1, 10, 'a', flags, fill, width); break; case 'x': - chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width); - break; - case 'X': - chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'A', flags, fill, width); + case 'X': { + char fmt_c = *fmt - 'X' + 'A'; + mp_uint_t val; + if (long_arg) { + val = va_arg(args, unsigned long int); + } else { + val = va_arg(args, unsigned int); + } + chrs += mp_print_int(print, val, 0, 16, fmt_c, flags, fill, width); break; + } case 'p': case 'P': // don't bother to handle upcase for 'P' - chrs += mp_print_int(print, va_arg(args, unsigned int), 0, 16, 'a', flags, fill, width); + // Use unsigned long int to work on both ILP32 and LP64 systems + chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags, fill, width); break; #if MICROPY_PY_BUILTINS_FLOAT case 'e': diff --git a/MicroPython_BUILD/components/micropython/py/mpstate.h b/MicroPython_BUILD/components/micropython/py/mpstate.h index 826f4530..5799d589 100644 --- a/MicroPython_BUILD/components/micropython/py/mpstate.h +++ b/MicroPython_BUILD/components/micropython/py/mpstate.h @@ -59,7 +59,7 @@ extern mp_dynamic_compiler_t mp_dynamic_compiler; typedef struct _mp_sched_item_t { mp_obj_t func; mp_obj_t arg; - void *carg; + void *carg; } mp_sched_item_t; // This structure hold information about the memory allocation system. @@ -80,13 +80,13 @@ typedef struct _mp_state_mem_t { int gc_stack_overflow; size_t gc_stack[MICROPY_ALLOC_GC_STACK_SIZE]; - size_t *gc_sp; uint16_t gc_lock_depth; // This variable controls auto garbage collection. If set to 0 then the // GC won't automatically run when gc_alloc can't find enough blocks. But // you can still allocate/free memory and also explicitly call gc_collect. uint16_t gc_auto_collect_enabled; + uint16_t gc_auto_collect_debug; #if MICROPY_GC_ALLOC_THRESHOLD size_t gc_alloc_amount; @@ -95,9 +95,8 @@ typedef struct _mp_state_mem_t { size_t gc_last_free_atb_index; - #if MICROPY_PY_GC_COLLECT_RETVAL size_t gc_collected; - #endif + size_t gc_marked; #if MICROPY_PY_THREAD // This is a global mutex used to make the GC thread-safe. @@ -108,10 +107,11 @@ typedef struct _mp_state_mem_t { // This structure hold runtime and VM information. It includes a section // which contains root pointers that must be scanned by the GC. typedef struct _mp_state_vm_t { - //////////////////////////////////////////////////////////// - // START ROOT POINTER SECTION - // everything that needs GC scanning must go here - // this must start at the start of this structure + // + // CONTINUE ROOT POINTER SECTION + // This must start at the start of this structure and follows + // the state in the mp_state_thread_t structure, continuing + // the root pointer section from there. // qstr_pool_t *last_pool; @@ -142,8 +142,6 @@ typedef struct _mp_state_vm_t { volatile mp_obj_t mp_pending_exception; #if MICROPY_ENABLE_SCHEDULER - volatile int16_t sched_state; - uint16_t sched_sp; mp_sched_item_t sched_stack[MICROPY_SCHEDULER_DEPTH]; #endif @@ -169,6 +167,10 @@ typedef struct _mp_state_vm_t { // root pointers for extmod + #if MICROPY_REPL_EVENT_DRIVEN + vstr_t *repl_line; + #endif + #if MICROPY_PY_OS_DUPTERM mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]; mp_obj_t dupterm_arr_obj; @@ -198,13 +200,20 @@ typedef struct _mp_state_vm_t { mp_thread_mutex_t qstr_mutex; #endif + #if MICROPY_ENABLE_COMPILER mp_uint_t mp_optimise_value; + #endif // size of the emergency exception buf, if it's dynamically allocated #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0 mp_int_t mp_emergency_exception_buf_size; #endif + #if MICROPY_ENABLE_SCHEDULER + volatile int16_t sched_state; + uint16_t sched_sp; + #endif + #if MICROPY_PY_THREAD_GIL // This is a global mutex used to make the VM/runtime thread-safe. mp_thread_mutex_t gil_mutex; @@ -215,24 +224,33 @@ typedef struct _mp_state_vm_t { // This structure holds state that is specific to a given thread. // Everything in this structure is scanned for root pointers. typedef struct _mp_state_thread_t { - mp_obj_dict_t *dict_locals; - mp_obj_dict_t *dict_globals; - - // Note: nlr asm code has the offset of this hard-coded - nlr_buf_t *nlr_top; // ROOT POINTER - // Stack top at the start of program char *stack_top; #if MICROPY_STACK_CHECK size_t stack_limit; #endif + + #if MICROPY_ENABLE_PYSTACK + uint8_t *pystack_start; + uint8_t *pystack_end; + uint8_t *pystack_cur; + #endif + + //////////////////////////////////////////////////////////// + // START ROOT POINTER SECTION + // Everything that needs GC scanning must start here, and + // is followed by state in the mp_state_vm_t structure. + // + + mp_obj_dict_t *dict_locals; + mp_obj_dict_t *dict_globals; + + nlr_buf_t *nlr_top; } mp_state_thread_t; // This structure combines the above 3 structures. // The order of the entries are important for root pointer scanning in the GC to work. -// Note: if this structure changes then revisit all nlr asm code since they -// have the offset of nlr_top hard-coded. typedef struct _mp_state_ctx_t { mp_state_thread_t thread; mp_state_vm_t vm; diff --git a/MicroPython_BUILD/components/micropython/py/mpthread.h b/MicroPython_BUILD/components/micropython/py/mpthread.h index 8f84e4a5..aaeabf4b 100644 --- a/MicroPython_BUILD/components/micropython/py/mpthread.h +++ b/MicroPython_BUILD/components/micropython/py/mpthread.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/py/mpz.c b/MicroPython_BUILD/components/micropython/py/mpz.c index 7161c44c..f85dc703 100644 --- a/MicroPython_BUILD/components/micropython/py/mpz.c +++ b/MicroPython_BUILD/components/micropython/py/mpz.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -537,83 +538,57 @@ STATIC void mpn_div(mpz_dig_t *num_dig, size_t *num_len, const mpz_dig_t *den_di // not to overflow the borrow variable. And the shifting of // borrow needs some special logic (it's a shift right with // round up). - - if (DIG_SIZE < 8 * sizeof(mpz_dbl_dig_t) / 2) { - const mpz_dig_t *d = den_dig; - mpz_dbl_dig_t d_norm = 0; - mpz_dbl_dig_signed_t borrow = 0; - - for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { - d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); - borrow += (mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2 - *n = borrow & DIG_MASK; - borrow >>= DIG_SIZE; - } - borrow += *num_dig; // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2 - *num_dig = borrow & DIG_MASK; - borrow >>= DIG_SIZE; - - // adjust quotient if it is too big - for (; borrow != 0; --quo) { - d = den_dig; - d_norm = 0; - mpz_dbl_dig_t carry = 0; - for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { - d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); - carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK); - *n = carry & DIG_MASK; - carry >>= DIG_SIZE; - } - carry += *num_dig; - *num_dig = carry & DIG_MASK; - carry >>= DIG_SIZE; - - borrow += carry; - } - } else { // DIG_SIZE == 8 * sizeof(mpz_dbl_dig_t) / 2 - const mpz_dig_t *d = den_dig; - mpz_dbl_dig_t d_norm = 0; - mpz_dbl_dig_t borrow = 0; - - for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { - d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); - mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); - if (x >= *n || *n - x <= borrow) { - borrow += (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)*n; - *n = (-borrow) & DIG_MASK; - borrow = (borrow >> DIG_SIZE) + ((borrow & DIG_MASK) == 0 ? 0 : 1); // shift-right with round-up - } else { - *n = ((mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)borrow) & DIG_MASK; - borrow = 0; - } - } - if (borrow >= *num_dig) { - borrow -= (mpz_dbl_dig_t)*num_dig; - *num_dig = (-borrow) & DIG_MASK; + // + const mpz_dig_t *d = den_dig; + mpz_dbl_dig_t d_norm = 0; + mpz_dbl_dig_t borrow = 0; + for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { + d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); + mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); + #if DIG_SIZE < MPZ_DBL_DIG_SIZE / 2 + borrow += (mpz_dbl_dig_t)*n - x; // will overflow if DIG_SIZE >= MPZ_DBL_DIG_SIZE/2 + *n = borrow & DIG_MASK; + borrow = (mpz_dbl_dig_signed_t)borrow >> DIG_SIZE; + #else // DIG_SIZE == MPZ_DBL_DIG_SIZE / 2 + if (x >= *n || *n - x <= borrow) { + borrow += x - (mpz_dbl_dig_t)*n; + *n = (-borrow) & DIG_MASK; borrow = (borrow >> DIG_SIZE) + ((borrow & DIG_MASK) == 0 ? 0 : 1); // shift-right with round-up } else { - *num_dig = (*num_dig - borrow) & DIG_MASK; + *n = ((mpz_dbl_dig_t)*n - x - borrow) & DIG_MASK; borrow = 0; } + #endif + } - // adjust quotient if it is too big - for (; borrow != 0; --quo) { - d = den_dig; - d_norm = 0; - mpz_dbl_dig_t carry = 0; - for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { - d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); - carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK); - *n = carry & DIG_MASK; - carry >>= DIG_SIZE; - } - carry += (mpz_dbl_dig_t)*num_dig; - *num_dig = carry & DIG_MASK; - carry >>= DIG_SIZE; + #if DIG_SIZE < MPZ_DBL_DIG_SIZE / 2 + // Borrow was negative in the above for-loop, make it positive for next if-block. + borrow = -borrow; + #endif - //assert(borrow >= carry); // enable this to check the logic - borrow -= carry; + // At this point we have either: + // + // 1. quo was the correct value and the most-sig-digit of num is exactly + // cancelled by borrow (borrow == *num_dig). In this case there is + // nothing more to do. + // + // 2. quo was too large, we subtracted too many den from num, and the + // most-sig-digit of num is 1 less than borrow (borrow == *num_dig + 1). + // In this case we must reduce quo and add back den to num until the + // carry from this operation cancels out the borrow. + // + borrow -= *num_dig; + for (; borrow != 0; --quo) { + d = den_dig; + d_norm = 0; + mpz_dbl_dig_t carry = 0; + for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) { + d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE); + carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK); + *n = carry & DIG_MASK; + carry >>= DIG_SIZE; } + borrow -= carry; } // store this digit of the quotient @@ -731,17 +706,14 @@ STATIC void mpz_need_dig(mpz_t *z, size_t need) { } STATIC mpz_t *mpz_clone(const mpz_t *src) { + assert(src->alloc != 0); mpz_t *z = m_new_obj(mpz_t); z->neg = src->neg; z->fixed_dig = 0; z->alloc = src->alloc; z->len = src->len; - if (src->dig == NULL) { - z->dig = NULL; - } else { - z->dig = m_new(mpz_dig_t, z->alloc); - memcpy(z->dig, src->dig, src->alloc * sizeof(mpz_dig_t)); - } + z->dig = m_new(mpz_dig_t, z->alloc); + memcpy(z->dig, src->dig, src->alloc * sizeof(mpz_dig_t)); return z; } @@ -1009,6 +981,7 @@ these functions are unused /* returns abs(z) */ mpz_t *mpz_abs(const mpz_t *z) { + // TODO: handle case of z->alloc=0 mpz_t *z2 = mpz_clone(z); z2->neg = 0; return z2; @@ -1017,6 +990,7 @@ mpz_t *mpz_abs(const mpz_t *z) { /* returns -z */ mpz_t *mpz_neg(const mpz_t *z) { + // TODO: handle case of z->alloc=0 mpz_t *z2 = mpz_clone(z); z2->neg = 1 - z2->neg; return z2; @@ -1390,13 +1364,14 @@ void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { can have dest, lhs, rhs the same; mod can't be the same as dest */ void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t *mod) { - if (lhs->len == 0 || rhs->neg != 0) { + if (lhs->len == 0 || rhs->neg != 0 || (mod->len == 1 && mod->dig[0] == 1)) { mpz_set_from_int(dest, 0); return; } + mpz_set_from_int(dest, 1); + if (rhs->len == 0) { - mpz_set_from_int(dest, 1); return; } @@ -1404,8 +1379,6 @@ void mpz_pow3_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs, const mpz_t mpz_t *n = mpz_clone(rhs); mpz_t quo; mpz_init_zero(&quo); - mpz_set_from_int(dest, 1); - while (n->len > 0) { if ((n->dig[0] & 1) != 0) { mpz_mul_inpl(dest, dest, x); @@ -1435,6 +1408,7 @@ these functions are unused */ mpz_t *mpz_gcd(const mpz_t *z1, const mpz_t *z2) { if (z1->len == 0) { + // TODO: handle case of z2->alloc=0 mpz_t *a = mpz_clone(z2); a->neg = 0; return a; @@ -1614,8 +1588,8 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) { return true; } -bool mpz_as_int64_checked(const mpz_t *i, uint64_t *value) { - uint64_t val = 0; +bool mpz_as_int64_checked(const mpz_t *i, int64_t *value) { + int64_t val = 0; mpz_dig_t *d = i->dig + i->len; while (d-- > i->dig) { @@ -1715,16 +1689,12 @@ char *mpz_as_str(const mpz_t *i, unsigned int base) { } #endif -// assumes enough space as calculated by mp_int_format_size +// assumes enough space in str as calculated by mp_int_format_size +// base must be between 2 and 32 inclusive // returns length of string, not including null byte size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, char base_char, char comma, char *str) { - if (str == NULL) { - return 0; - } - if (base < 2 || base > 32) { - str[0] = 0; - return 0; - } + assert(str != NULL); + assert(2 <= base && base <= 32); size_t ilen = i->len; diff --git a/MicroPython_BUILD/components/micropython/py/mpz.h b/MicroPython_BUILD/components/micropython/py/mpz.h index cc09ee2d..bd5dee93 100644 --- a/MicroPython_BUILD/components/micropython/py/mpz.h +++ b/MicroPython_BUILD/components/micropython/py/mpz.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -55,18 +56,22 @@ #endif #if MPZ_DIG_SIZE > 16 +#define MPZ_DBL_DIG_SIZE (64) typedef uint32_t mpz_dig_t; typedef uint64_t mpz_dbl_dig_t; typedef int64_t mpz_dbl_dig_signed_t; #elif MPZ_DIG_SIZE > 8 +#define MPZ_DBL_DIG_SIZE (32) typedef uint16_t mpz_dig_t; typedef uint32_t mpz_dbl_dig_t; typedef int32_t mpz_dbl_dig_signed_t; #elif MPZ_DIG_SIZE > 4 +#define MPZ_DBL_DIG_SIZE (16) typedef uint8_t mpz_dig_t; typedef uint16_t mpz_dbl_dig_t; typedef int16_t mpz_dbl_dig_signed_t; #else +#define MPZ_DBL_DIG_SIZE (8) typedef uint8_t mpz_dig_t; typedef uint8_t mpz_dbl_dig_t; typedef int8_t mpz_dbl_dig_signed_t; @@ -134,7 +139,7 @@ static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_ mp_int_t mpz_hash(const mpz_t *z); bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value); bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value); -bool mpz_as_int64_checked(const mpz_t *i, uint64_t *value); +bool mpz_as_int64_checked(const mpz_t *i, int64_t *value); bool mpz_as_uint64_checked(const mpz_t *i, uint64_t *value); void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf); #if MICROPY_PY_BUILTINS_FLOAT diff --git a/MicroPython_BUILD/components/micropython/py/nlr.c b/MicroPython_BUILD/components/micropython/py/nlr.c new file mode 100644 index 00000000..03d01577 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/nlr.c @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Damien P. George + * + * 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 "py/mpstate.h" + +#if !MICROPY_NLR_SETJMP +// When not using setjmp, nlr_push_tail is called from inline asm so needs special care +#if MICROPY_NLR_X86 && MICROPY_NLR_OS_WINDOWS +// On these 32-bit platforms make sure nlr_push_tail doesn't have a leading underscore +unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail"); +#else +// LTO can't see inside inline asm functions so explicitly mark nlr_push_tail as used +__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); +#endif +#endif + +unsigned int nlr_push_tail(nlr_buf_t *nlr) { + nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); + nlr->prev = *top; + MP_NLR_SAVE_PYSTACK(nlr); + *top = nlr; + return 0; // normal return +} + +void nlr_pop(void) { + nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); + *top = (*top)->prev; +} diff --git a/MicroPython_BUILD/components/micropython/py/nlr.h b/MicroPython_BUILD/components/micropython/py/nlr.h index 63fe392d..90595a12 100644 --- a/MicroPython_BUILD/components/micropython/py/nlr.h +++ b/MicroPython_BUILD/components/micropython/py/nlr.h @@ -30,29 +30,34 @@ // exception handling, basically a stack of setjmp/longjmp buffers #include -#include #include #include "py/mpconfig.h" -typedef struct _nlr_buf_t nlr_buf_t; -struct _nlr_buf_t { - // the entries here must all be machine word size - nlr_buf_t *prev; - void *ret_val; // always a concrete object (an exception instance) -#if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP +// If MICROPY_NLR_SETJMP is not enabled then auto-detect the machine arch +#if !MICROPY_NLR_SETJMP +// A lot of nlr-related things need different treatment on Windows +#if defined(_WIN32) || defined(__CYGWIN__) +#define MICROPY_NLR_OS_WINDOWS 1 +#else +#define MICROPY_NLR_OS_WINDOWS 0 +#endif #if defined(__i386__) - void *regs[6]; + #define MICROPY_NLR_X86 (1) + #define MICROPY_NLR_NUM_REGS (6) #elif defined(__x86_64__) - #if defined(__CYGWIN__) - void *regs[12]; - #else - void *regs[8]; - #endif + #define MICROPY_NLR_X64 (1) + #if MICROPY_NLR_OS_WINDOWS + #define MICROPY_NLR_NUM_REGS (10) + #else + #define MICROPY_NLR_NUM_REGS (8) + #endif #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) - void *regs[10]; + #define MICROPY_NLR_THUMB (1) + #define MICROPY_NLR_NUM_REGS (10) #elif defined(__xtensa__) - void *regs[10]; + #define MICROPY_NLR_XTENSA (1) + #define MICROPY_NLR_NUM_REGS (10) #else #define MICROPY_NLR_SETJMP (1) //#warning "No native NLR support for this arch, using setjmp implementation" @@ -60,24 +65,58 @@ struct _nlr_buf_t { #endif #if MICROPY_NLR_SETJMP - jmp_buf jmpbuf; +#include #endif + +typedef struct _nlr_buf_t nlr_buf_t; +struct _nlr_buf_t { + // the entries here must all be machine word size + nlr_buf_t *prev; + void *ret_val; // always a concrete object (an exception instance) + + #if MICROPY_NLR_SETJMP + jmp_buf jmpbuf; + #else + void *regs[MICROPY_NLR_NUM_REGS]; + #endif + + #if MICROPY_ENABLE_PYSTACK + void *pystack; + #endif }; -#if MICROPY_NLR_SETJMP -#include "py/mpstate.h" +// Helper macros to save/restore the pystack state +#if MICROPY_ENABLE_PYSTACK +#define MP_NLR_SAVE_PYSTACK(nlr_buf) (nlr_buf)->pystack = MP_STATE_THREAD(pystack_cur) +#define MP_NLR_RESTORE_PYSTACK(nlr_buf) MP_STATE_THREAD(pystack_cur) = (nlr_buf)->pystack +#else +#define MP_NLR_SAVE_PYSTACK(nlr_buf) (void)nlr_buf +#define MP_NLR_RESTORE_PYSTACK(nlr_buf) (void)nlr_buf +#endif + +// Helper macro to use at the start of a specific nlr_jump implementation +#define MP_NLR_JUMP_HEAD(val, top) \ + nlr_buf_t **_top_ptr = &MP_STATE_THREAD(nlr_top); \ + nlr_buf_t *top = *_top_ptr; \ + if (top == NULL) { \ + nlr_jump_fail(val); \ + } \ + top->ret_val = val; \ + MP_NLR_RESTORE_PYSTACK(top); \ + *_top_ptr = top->prev; \ -NORETURN void nlr_setjmp_jump(void *val); +#if MICROPY_NLR_SETJMP // nlr_push() must be defined as a macro, because "The stack context will be // invalidated if the function which called setjmp() returns." -#define nlr_push(buf) ((buf)->prev = MP_STATE_THREAD(nlr_top), MP_STATE_THREAD(nlr_top) = (buf), setjmp((buf)->jmpbuf)) -#define nlr_pop() { MP_STATE_THREAD(nlr_top) = MP_STATE_THREAD(nlr_top)->prev; } -#define nlr_jump(val) nlr_setjmp_jump(val) +// For this case it is safe to call nlr_push_tail() first. +#define nlr_push(buf) (nlr_push_tail(buf), setjmp((buf)->jmpbuf)) #else unsigned int nlr_push(nlr_buf_t *); +#endif + +unsigned int nlr_push_tail(nlr_buf_t *top); void nlr_pop(void); NORETURN void nlr_jump(void *val); -#endif // This must be implemented by a port. It's called by nlr_jump // if no nlr buf has been pushed. It must not return, but rather @@ -106,7 +145,6 @@ NORETURN void nlr_jump_fail(void *val); /* #define nlr_push(val) \ printf("nlr_push: before: nlr_top=%p, val=%p\n", MP_STATE_THREAD(nlr_top), val),assert(MP_STATE_THREAD(nlr_top) != val),nlr_push(val) -#endif */ #endif diff --git a/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c b/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c index 1fb45944..960dd86f 100644 --- a/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c +++ b/MicroPython_BUILD/components/micropython/py/nlrsetjmp.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,17 +24,18 @@ * THE SOFTWARE. */ -#include "py/nlr.h" +#include "py/mpstate.h" #if MICROPY_NLR_SETJMP -void nlr_setjmp_jump(void *val) { +void nlr_jump(void *val) { nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); nlr_buf_t *top = *top_ptr; if (top == NULL) { nlr_jump_fail(val); } top->ret_val = val; + MP_NLR_RESTORE_PYSTACK(top); *top_ptr = top->prev; longjmp(top->jmpbuf, 1); } diff --git a/MicroPython_BUILD/components/micropython/py/nlrthumb.c b/MicroPython_BUILD/components/micropython/py/nlrthumb.c index 6e7d7176..7dbeac1b 100644 --- a/MicroPython_BUILD/components/micropython/py/nlrthumb.c +++ b/MicroPython_BUILD/components/micropython/py/nlrthumb.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013-2016 Damien P. George + * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,7 @@ #include "py/mpstate.h" -#if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) +#if MICROPY_NLR_THUMB #undef nlr_push @@ -76,30 +76,14 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { #endif ); - return 0; // needed to silence compiler warning + #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) + // Older versions of gcc give an error when naked functions don't return a value + return 0; + #endif } -__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - nlr->prev = *top; - *top = nlr; - return 0; // normal return -} - -void nlr_pop(void) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - *top = (*top)->prev; -} - -NORETURN __attribute__((naked)) void nlr_jump(void *val) { - nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); - nlr_buf_t *top = *top_ptr; - if (top == NULL) { - nlr_jump_fail(val); - } - - top->ret_val = val; - *top_ptr = top->prev; +NORETURN void nlr_jump(void *val) { + MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "mov r0, %0 \n" // r0 points to nlr_buf @@ -136,7 +120,11 @@ NORETURN __attribute__((naked)) void nlr_jump(void *val) { : // clobbered registers ); + #if defined(__GNUC__) + __builtin_unreachable(); + #else for (;;); // needed to silence compiler warning + #endif } -#endif // (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) +#endif // MICROPY_NLR_THUMB diff --git a/MicroPython_BUILD/components/micropython/py/nlrx64.c b/MicroPython_BUILD/components/micropython/py/nlrx64.c index 847d1039..a3a1cf34 100644 --- a/MicroPython_BUILD/components/micropython/py/nlrx64.c +++ b/MicroPython_BUILD/components/micropython/py/nlrx64.c @@ -26,25 +26,19 @@ #include "py/mpstate.h" -#if !MICROPY_NLR_SETJMP && defined(__x86_64__) +#if MICROPY_NLR_X64 #undef nlr_push // x86-64 callee-save registers are: // rbx, rbp, rsp, r12, r13, r14, r15 -#if defined(_WIN32) || defined(__CYGWIN__) -#define NLR_OS_WINDOWS 1 -#else -#define NLR_OS_WINDOWS 0 -#endif - __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); unsigned int nlr_push(nlr_buf_t *nlr) { (void)nlr; - #if NLR_OS_WINDOWS + #if MICROPY_NLR_OS_WINDOWS __asm volatile ( "movq (%rsp), %rax \n" // load return %rip @@ -88,31 +82,12 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; // needed to silence compiler warning } -__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - nlr->prev = *top; - *top = nlr; - return 0; // normal return -} - -void nlr_pop(void) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - *top = (*top)->prev; -} - NORETURN void nlr_jump(void *val) { - nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); - nlr_buf_t *top = *top_ptr; - if (top == NULL) { - nlr_jump_fail(val); - } - - top->ret_val = val; - *top_ptr = top->prev; + MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "movq %0, %%rcx \n" // %rcx points to nlr_buf - #if NLR_OS_WINDOWS + #if MICROPY_NLR_OS_WINDOWS "movq 88(%%rcx), %%rsi \n" // load saved %rsi "movq 80(%%rcx), %%rdi \n" // load saved %rdr #endif @@ -136,4 +111,4 @@ NORETURN void nlr_jump(void *val) { for (;;); // needed to silence compiler warning } -#endif // !MICROPY_NLR_SETJMP && defined(__x86_64__) +#endif // MICROPY_NLR_X64 diff --git a/MicroPython_BUILD/components/micropython/py/nlrx86.c b/MicroPython_BUILD/components/micropython/py/nlrx86.c index 094dea3c..23882cc3 100644 --- a/MicroPython_BUILD/components/micropython/py/nlrx86.c +++ b/MicroPython_BUILD/components/micropython/py/nlrx86.c @@ -26,20 +26,14 @@ #include "py/mpstate.h" -#if !MICROPY_NLR_SETJMP && defined(__i386__) +#if MICROPY_NLR_X86 #undef nlr_push // For reference, x86 callee save regs are: // ebx, esi, edi, ebp, esp, eip -#if defined(_WIN32) || defined(__CYGWIN__) -#define NLR_OS_WINDOWS 1 -#else -#define NLR_OS_WINDOWS 0 -#endif - -#if NLR_OS_WINDOWS +#if MICROPY_NLR_OS_WINDOWS unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail"); #else __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); @@ -70,27 +64,8 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; // needed to silence compiler warning } -__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - nlr->prev = *top; - *top = nlr; - return 0; // normal return -} - -void nlr_pop(void) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - *top = (*top)->prev; -} - NORETURN void nlr_jump(void *val) { - nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); - nlr_buf_t *top = *top_ptr; - if (top == NULL) { - nlr_jump_fail(val); - } - - top->ret_val = val; - *top_ptr = top->prev; + MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "mov %0, %%edx \n" // %edx points to nlr_buf @@ -112,4 +87,4 @@ NORETURN void nlr_jump(void *val) { for (;;); // needed to silence compiler warning } -#endif // !MICROPY_NLR_SETJMP && defined(__i386__) +#endif // MICROPY_NLR_X86 diff --git a/MicroPython_BUILD/components/micropython/py/nlrxtensa.c b/MicroPython_BUILD/components/micropython/py/nlrxtensa.c index 4520e7e7..cd3dee36 100644 --- a/MicroPython_BUILD/components/micropython/py/nlrxtensa.c +++ b/MicroPython_BUILD/components/micropython/py/nlrxtensa.c @@ -26,7 +26,7 @@ #include "py/mpstate.h" -#if !MICROPY_NLR_SETJMP && defined(__xtensa__) +#if MICROPY_NLR_XTENSA #undef nlr_push @@ -55,27 +55,8 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; // needed to silence compiler warning } -__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - nlr->prev = *top; - *top = nlr; - return 0; // normal return -} - -void nlr_pop(void) { - nlr_buf_t **top = &MP_STATE_THREAD(nlr_top); - *top = (*top)->prev; -} - NORETURN void nlr_jump(void *val) { - nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top); - nlr_buf_t *top = *top_ptr; - if (top == NULL) { - nlr_jump_fail(val); - } - - top->ret_val = val; - *top_ptr = top->prev; + MP_NLR_JUMP_HEAD(val, top) __asm volatile ( "mov.n a2, %0 \n" // a2 points to nlr_buf @@ -99,4 +80,4 @@ NORETURN void nlr_jump(void *val) { for (;;); // needed to silence compiler warning } -#endif // !MICROPY_NLR_SETJMP && defined(__xtensa__) +#endif // MICROPY_NLR_XTENSA diff --git a/MicroPython_BUILD/components/micropython/py/obj.c b/MicroPython_BUILD/components/micropython/py/obj.c index 808546d1..8208fb2a 100644 --- a/MicroPython_BUILD/components/micropython/py/obj.c +++ b/MicroPython_BUILD/components/micropython/py/obj.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -242,9 +243,10 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { "can't convert %s to int", mp_obj_get_type_str(arg))); } } + return 0; } -uint64_t mp_obj_get_int64(mp_const_obj_t arg) { +int64_t mp_obj_get_int64(mp_const_obj_t arg) { // This function essentially performs implicit type conversion to int64 // Note that Python does NOT provide implicit type conversion from // float to int in the core expression language, try some_list[1.0]. @@ -264,6 +266,7 @@ uint64_t mp_obj_get_int64(mp_const_obj_t arg) { "can't convert %s to int", mp_obj_get_type_str(arg))); } } + return 0; } mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) { diff --git a/MicroPython_BUILD/components/micropython/py/obj.h b/MicroPython_BUILD/components/micropython/py/obj.h index 385a3777..ee784b64 100644 --- a/MicroPython_BUILD/components/micropython/py/obj.h +++ b/MicroPython_BUILD/components/micropython/py/obj.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -170,8 +171,8 @@ static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o) static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0001000000000000); } -#define MP_OBJ_SMALL_INT_VALUE(o) (((intptr_t)(o)) >> 1) -#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((uintptr_t)(small_int)) << 1) | 0x0001000000000001) +#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)((o) << 16)) >> 17) +#define MP_OBJ_NEW_SMALL_INT(small_int) (((((uint64_t)(small_int)) & 0x7fffffffffff) << 1) | 0x0001000000000001) static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0002000000000000); } @@ -179,7 +180,7 @@ static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o) #define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 1) | 0x0002000000000001)) #if MICROPY_PY_BUILTINS_FLOAT -#define mp_const_float_e {((mp_obj_t)((uint64_t)0x4005bf0a8b125769 + 0x8004000000000000))} +#define mp_const_float_e {((mp_obj_t)((uint64_t)0x4005bf0a8b145769 + 0x8004000000000000))} #define mp_const_float_pi {((mp_obj_t)((uint64_t)0x400921fb54442d18 + 0x8004000000000000))} static inline bool mp_obj_is_float(mp_const_obj_t o) { @@ -250,6 +251,8 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; // The macros below are derived from the ones above and are used to // check for more specific object types. +// Note: these are kept as macros because inline functions sometimes use much +// more code space than the equivalent macros, depending on the compiler. #define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that #define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int)) @@ -258,17 +261,6 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; #define MP_OBJ_IS_FUN(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function)) #define MP_OBJ_IS_METH(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_bound_method)) -// Note: inline functions sometimes use much more code space than the -// equivalent macros, depending on the compiler. -//static inline bool MP_OBJ_IS_TYPE(mp_const_obj_t o, const mp_obj_type_t *t) { return (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))); } // this does not work for checking a string, use below macro for that -//static inline bool MP_OBJ_IS_INT(mp_const_obj_t o) { return (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int)); } // returns true if o is a small int or long int -// Need to forward declare these for the inline function to compile. -extern const mp_obj_type_t mp_type_int; -extern const mp_obj_type_t mp_type_bool; -static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_bool); } // returns true if o is bool, small int or long int -//static inline bool MP_OBJ_IS_STR(mp_const_obj_t o) { return (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str)); } - - // These macros are used to declare and define constant function objects // You can put "static" in front of the definitions to make them local @@ -554,6 +546,7 @@ extern const mp_obj_type_t mp_type_list; extern const mp_obj_type_t mp_type_map; // map (the python builtin, not the dict implementation detail) extern const mp_obj_type_t mp_type_enumerate; extern const mp_obj_type_t mp_type_filter; +extern const mp_obj_type_t mp_type_deque; extern const mp_obj_type_t mp_type_dict; extern const mp_obj_type_t mp_type_ordereddict; extern const mp_obj_type_t mp_type_range; @@ -625,7 +618,6 @@ extern const struct _mp_obj_str_t mp_const_empty_bytes_obj; extern const struct _mp_obj_tuple_t mp_const_empty_tuple_obj; extern const struct _mp_obj_singleton_t mp_const_ellipsis_obj; extern const struct _mp_obj_singleton_t mp_const_notimplemented_obj; -extern const struct _mp_obj_exception_t mp_const_MemoryError_obj; extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj; // General API for objects @@ -638,7 +630,8 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value); mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base); mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception) -mp_obj_t mp_obj_new_str(const char* data, size_t len, bool make_qstr_if_not_already); +mp_obj_t mp_obj_new_str(const char* data, size_t len); +mp_obj_t mp_obj_new_str_via_qstr(const char* data, size_t len); mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte* data, size_t len); mp_obj_t mp_obj_new_bytearray(size_t n, void *items); @@ -681,8 +674,9 @@ bool mp_obj_is_true(mp_obj_t arg); bool mp_obj_is_callable(mp_obj_t o_in); bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); +static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_bool); } // returns true if o is bool, small int or long int mp_int_t mp_obj_get_int(mp_const_obj_t arg); -uint64_t mp_obj_get_int64(mp_const_obj_t arg); +int64_t mp_obj_get_int64(mp_const_obj_t arg); mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg); bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value); #if MICROPY_PY_BUILTINS_FLOAT @@ -709,7 +703,8 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in); // Will raise exception if value doesn't fit into mp_int_t mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); -uint64_t mp_obj_int64_get_checked(mp_const_obj_t self_in); +int64_t mp_obj_int64_get_checked(mp_const_obj_t self_in); +uint64_t mp_obj_uint64_get_checked(mp_const_obj_t self_in); // exception #define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new) @@ -730,6 +725,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway conve const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len); mp_obj_t mp_obj_str_intern(mp_obj_t str); +mp_obj_t mp_obj_str_intern_checked(mp_obj_t obj); void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes); #if MICROPY_PY_BUILTINS_FLOAT diff --git a/MicroPython_BUILD/components/micropython/py/objarray.c b/MicroPython_BUILD/components/micropython/py/objarray.c index 7003ec9e..545dae5b 100644 --- a/MicroPython_BUILD/components/micropython/py/objarray.c +++ b/MicroPython_BUILD/components/micropython/py/objarray.c @@ -5,6 +5,7 @@ * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -90,7 +91,8 @@ STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t #endif #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY -STATIC mp_obj_array_t *array_new(char typecode, size_t n) { +//------------------------------------------------------------------ +mp_obj_array_t *array_new(char typecode, size_t n, uint64_t *init) { int typecode_size = mp_binary_get_size('@', typecode, NULL); mp_obj_array_t *o = m_new_obj(mp_obj_array_t); #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY @@ -104,6 +106,38 @@ STATIC mp_obj_array_t *array_new(char typecode, size_t n) { o->free = 0; o->len = n; o->items = m_new(byte, typecode_size * o->len); + + if (o->len > 0) { + memset(o->items, 0, typecode_size * o->len); + if (init) { + switch (typecode_size) { + case 2: { + uint16_t *ptr = (uint16_t *) o->items; + uint16_t *val = (uint16_t *)init; + for (int i=0; ilen; i++) { + ptr[i] = *val; + } + break; + } + case 4: { + uint32_t *ptr = (uint32_t *) o->items; + uint32_t *val = (uint32_t *)init; + for (int i=0; ilen; i++) { + ptr[i] = *val; + } + break; + } + case 8: { + uint64_t *ptr = (uint64_t *) o->items; + uint64_t *val = (uint64_t *)init; + for (int i=0; ilen; i++) { + ptr[i] = *val; + } + break; + } + } + } + } return o; } #endif @@ -113,17 +147,15 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { // bytearrays can be raw-initialised from anything with the buffer protocol // other arrays can only be raw-initialised from bytes and bytearray objects mp_buffer_info_t bufinfo; - if (((MICROPY_PY_BUILTINS_BYTEARRAY - && typecode == BYTEARRAY_TYPECODE) - || (MICROPY_PY_ARRAY - && (MP_OBJ_IS_TYPE(initializer, &mp_type_bytes) - || (MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(initializer, &mp_type_bytearray))))) - && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) { + if (((MICROPY_PY_BUILTINS_BYTEARRAY && typecode == BYTEARRAY_TYPECODE) || + (MICROPY_PY_ARRAY && (MP_OBJ_IS_TYPE(initializer, &mp_type_bytes) || + (MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(initializer, &mp_type_bytearray))))) && + mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) { // construct array from raw bytes // we round-down the len to make it a multiple of sz (CPython raises error) size_t sz = mp_binary_get_size('@', typecode, NULL); size_t len = bufinfo.len / sz; - mp_obj_array_t *o = array_new(typecode, len); + mp_obj_array_t *o = array_new(typecode, len, NULL); memcpy(o->items, bufinfo.buf, len * sz); return MP_OBJ_FROM_PTR(o); } @@ -137,7 +169,7 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { len = MP_OBJ_SMALL_INT_VALUE(len_in); } - mp_obj_array_t *array = array_new(typecode, len); + mp_obj_array_t *array = array_new(typecode, len, NULL); mp_obj_t iterable = mp_getiter(initializer, NULL); mp_obj_t item; @@ -155,18 +187,30 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { #endif #if MICROPY_PY_ARRAY +//-------------------------------------------------------------------------------------------------------------- STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; - mp_arg_check_num(n_args, n_kw, 1, 2, false); - + mp_arg_check_num(n_args, n_kw, 1, 3, false); // get typecode const char *typecode = mp_obj_str_get_str(args[0]); - if (n_args == 1) { // 1 arg: make an empty array - return MP_OBJ_FROM_PTR(array_new(*typecode, 0)); + return MP_OBJ_FROM_PTR(array_new(*typecode, 0, NULL)); } else { - // 2 args: construct the array from the given object + // 2 or 3 args: + if (MP_OBJ_IS_INT(args[1])) { + // make array of specified number of items + mp_uint_t len = mp_obj_get_int(args[1]); + if (n_args == 3) { + // initialize array vith given value + uint64_t init_val = mp_obj_get_int64(args[2]); + return MP_OBJ_FROM_PTR(array_new(*typecode, len, &init_val)); + } + else { + return MP_OBJ_FROM_PTR(array_new(*typecode, len, NULL)); + } + } + //construct the array from the given object return array_construct(*typecode, args[1]); } } @@ -179,11 +223,11 @@ STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, if (n_args == 0) { // no args: construct an empty bytearray - return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0)); + return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0, NULL)); } else if (MP_OBJ_IS_INT(args[0])) { // 1 arg, an integer: construct a blank bytearray of that length mp_uint_t len = mp_obj_get_int(args[0]); - mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len); + mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len, NULL); memset(o->items, 0, len); return MP_OBJ_FROM_PTR(o); } else { @@ -254,7 +298,7 @@ STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs size_t rhs_len = rhs_bufinfo.len / sz; // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count - mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len); + mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len, NULL); mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte); return MP_OBJ_FROM_PTR(res); } @@ -269,8 +313,7 @@ STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs return lhs_in; } - case MP_BINARY_OP_IN: { - /* NOTE `a in b` is `b.__contains__(a)` */ + case MP_BINARY_OP_CONTAINS: { mp_buffer_info_t lhs_bufinfo; mp_buffer_info_t rhs_bufinfo; @@ -462,7 +505,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value res->len = slice.stop - slice.start; #endif } else { - res = array_new(o->typecode, slice.stop - slice.start); + res = array_new(o->typecode, slice.stop - slice.start, NULL); memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz); } return MP_OBJ_FROM_PTR(res); @@ -570,7 +613,7 @@ size_t mp_obj_array_len(mp_obj_t self_in) { #if MICROPY_PY_BUILTINS_BYTEARRAY mp_obj_t mp_obj_new_bytearray(size_t n, void *items) { - mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n); + mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n, NULL); memcpy(o->items, items, n); return MP_OBJ_FROM_PTR(o); } diff --git a/MicroPython_BUILD/components/micropython/py/objarray.h b/MicroPython_BUILD/components/micropython/py/objarray.h index 03896684..2b885b6f 100644 --- a/MicroPython_BUILD/components/micropython/py/objarray.h +++ b/MicroPython_BUILD/components/micropython/py/objarray.h @@ -5,6 +5,7 @@ * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,4 +40,6 @@ typedef struct _mp_obj_array_t { void *items; } mp_obj_array_t; +mp_obj_array_t *array_new(char typecode, size_t n, uint64_t *init); + #endif // MICROPY_INCLUDED_PY_OBJARRAY_H diff --git a/MicroPython_BUILD/components/micropython/py/objboundmeth.c b/MicroPython_BUILD/components/micropython/py/objboundmeth.c index 890f8b15..b0df6a68 100644 --- a/MicroPython_BUILD/components/micropython/py/objboundmeth.c +++ b/MicroPython_BUILD/components/micropython/py/objboundmeth.c @@ -51,6 +51,9 @@ mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, s // need to insert self before all other args and then call meth size_t n_total = n_args + 2 * n_kw; mp_obj_t *args2 = NULL; + #if MICROPY_ENABLE_PYSTACK + args2 = mp_pystack_alloc(sizeof(mp_obj_t) * (1 + n_total)); + #else mp_obj_t *free_args2 = NULL; if (n_total > 4) { // try to use heap to allocate temporary args array @@ -61,12 +64,17 @@ mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, s // (fallback to) use stack to allocate temporary args array args2 = alloca(sizeof(mp_obj_t) * (1 + n_total)); } + #endif args2[0] = self; memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t)); mp_obj_t res = mp_call_function_n_kw(meth, n_args + 1, n_kw, args2); + #if MICROPY_ENABLE_PYSTACK + mp_pystack_free(args2); + #else if (free_args2 != NULL) { m_del(mp_obj_t, free_args2, 1 + n_total); } + #endif return res; } diff --git a/MicroPython_BUILD/components/micropython/py/objdeque.c b/MicroPython_BUILD/components/micropython/py/objdeque.c new file mode 100644 index 00000000..1cff1f8d --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/objdeque.c @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Paul Sokolovsky + * + * 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 // for ssize_t +#include + +#include "py/mpconfig.h" +#if MICROPY_PY_COLLECTIONS_DEQUE + +#include "py/runtime.h" + +typedef struct _mp_obj_deque_t { + mp_obj_base_t base; + size_t alloc; + size_t i_get; + size_t i_put; + mp_obj_t *items; + uint32_t flags; + #define FLAG_CHECK_OVERFLOW 1 +} mp_obj_deque_t; + +STATIC mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 2, 3, false); + + /* Initialization from existing sequence is not supported, so an empty + tuple must be passed as such. */ + if (args[0] != mp_const_empty_tuple) { + mp_raise_ValueError(NULL); + } + + // Protect against -1 leading to zero-length allocation and bad array access + mp_int_t maxlen = mp_obj_get_int(args[1]); + if (maxlen < 0) { + mp_raise_ValueError(NULL); + } + + mp_obj_deque_t *o = m_new_obj(mp_obj_deque_t); + o->base.type = type; + o->alloc = maxlen + 1; + o->i_get = o->i_put = 0; + o->items = m_new0(mp_obj_t, o->alloc); + + if (n_args > 2) { + o->flags = mp_obj_get_int(args[2]); + } + + return MP_OBJ_FROM_PTR(o); +} + +STATIC mp_obj_t deque_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + switch (op) { + case MP_UNARY_OP_BOOL: + return mp_obj_new_bool(self->i_get != self->i_put); + case MP_UNARY_OP_LEN: { + ssize_t len = self->i_put - self->i_get; + if (len < 0) { + len += self->alloc; + } + return MP_OBJ_NEW_SMALL_INT(len); + } + #if MICROPY_PY_SYS_GETSIZEOF + case MP_UNARY_OP_SIZEOF: { + size_t sz = sizeof(*self) + sizeof(mp_obj_t) * self->alloc; + return MP_OBJ_NEW_SMALL_INT(sz); + } + #endif + default: + return MP_OBJ_NULL; // op not supported + } +} + +STATIC mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) { + mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + + size_t new_i_put = self->i_put + 1; + if (new_i_put == self->alloc) { + new_i_put = 0; + } + + if (self->flags & FLAG_CHECK_OVERFLOW && new_i_put == self->i_get) { + mp_raise_msg(&mp_type_IndexError, "full"); + } + + self->items[self->i_put] = arg; + self->i_put = new_i_put; + + if (self->i_get == new_i_put) { + if (++self->i_get == self->alloc) { + self->i_get = 0; + } + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(deque_append_obj, mp_obj_deque_append); + +STATIC mp_obj_t deque_popleft(mp_obj_t self_in) { + mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->i_get == self->i_put) { + mp_raise_msg(&mp_type_IndexError, "empty"); + } + + mp_obj_t ret = self->items[self->i_get]; + self->items[self->i_get] = MP_OBJ_NULL; + + if (++self->i_get == self->alloc) { + self->i_get = 0; + } + + return ret; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(deque_popleft_obj, deque_popleft); + +#if 0 +STATIC mp_obj_t deque_clear(mp_obj_t self_in) { + mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + self->i_get = self->i_put = 0; + mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(deque_clear_obj, deque_clear); +#endif + +STATIC const mp_rom_map_elem_t deque_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&deque_append_obj) }, + #if 0 + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&deque_clear_obj) }, + #endif + { MP_ROM_QSTR(MP_QSTR_popleft), MP_ROM_PTR(&deque_popleft_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(deque_locals_dict, deque_locals_dict_table); + +const mp_obj_type_t mp_type_deque = { + { &mp_type_type }, + .name = MP_QSTR_deque, + .make_new = deque_make_new, + .unary_op = deque_unary_op, + .locals_dict = (mp_obj_dict_t*)&deque_locals_dict, +}; + +#endif // MICROPY_PY_COLLECTIONS_DEQUE diff --git a/MicroPython_BUILD/components/micropython/py/objdict.c b/MicroPython_BUILD/components/micropython/py/objdict.c index 1553a83b..c0647067 100644 --- a/MicroPython_BUILD/components/micropython/py/objdict.c +++ b/MicroPython_BUILD/components/micropython/py/objdict.c @@ -115,7 +115,7 @@ STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) { STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in); switch (op) { - case MP_BINARY_OP_IN: { + case MP_BINARY_OP_CONTAINS: { mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP); return mp_obj_new_bool(elem != NULL); } @@ -193,42 +193,18 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } /******************************************************************************/ -/* dict iterator */ - -typedef struct _mp_obj_dict_it_t { - mp_obj_base_t base; - mp_fun_1_t iternext; - mp_obj_t dict; - size_t cur; -} mp_obj_dict_it_t; - -STATIC mp_obj_t dict_it_iternext(mp_obj_t self_in) { - mp_obj_dict_it_t *self = MP_OBJ_TO_PTR(self_in); - mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur); +/* dict methods */ - if (next == NULL) { - return MP_OBJ_STOP_ITERATION; - } else { - return next->key; +STATIC void mp_ensure_not_fixed(const mp_obj_dict_t *dict) { + if (dict->map.is_fixed) { + mp_raise_TypeError(NULL); } } -STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { - assert(sizeof(mp_obj_dict_it_t) <= sizeof(mp_obj_iter_buf_t)); - mp_obj_dict_it_t *o = (mp_obj_dict_it_t*)iter_buf; - o->base.type = &mp_type_polymorph_iter; - o->iternext = dict_it_iternext; - o->dict = self_in; - o->cur = 0; - return MP_OBJ_FROM_PTR(o); -} - -/******************************************************************************/ -/* dict methods */ - STATIC mp_obj_t dict_clear(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); + mp_ensure_not_fixed(self); mp_map_clear(&self->map); @@ -284,6 +260,9 @@ STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromk STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) { mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); + if (lookup_kind != MP_MAP_LOOKUP) { + mp_ensure_not_fixed(self); + } mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind); mp_obj_t value; if (elem == NULL || elem->value == MP_OBJ_NULL) { @@ -326,6 +305,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); + mp_ensure_not_fixed(self); size_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { @@ -344,6 +324,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem); STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); + mp_ensure_not_fixed(self); mp_arg_check_num(n_args, kwargs->used, 1, 2, true); @@ -485,7 +466,7 @@ STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t if (o->kind != MP_DICT_VIEW_KEYS) { return MP_OBJ_NULL; // op not supported } - if (op != MP_BINARY_OP_IN) { + if (op != MP_BINARY_OP_CONTAINS) { return MP_OBJ_NULL; // op not supported } return dict_binary_op(op, o->dict, rhs_in); @@ -527,6 +508,20 @@ STATIC mp_obj_t dict_values(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values); +/******************************************************************************/ +/* dict iterator */ + +STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { + assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf; + o->base.type = &dict_view_it_type; + o->kind = MP_DICT_VIEW_KEYS; + o->dict = self_in; + o->cur = 0; + return MP_OBJ_FROM_PTR(o); +} + /******************************************************************************/ /* dict constructors & public C API */ @@ -595,6 +590,7 @@ size_t mp_obj_dict_len(mp_obj_t self_in) { mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); + mp_ensure_not_fixed(self); mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; return self_in; } diff --git a/MicroPython_BUILD/components/micropython/py/objexcept.c b/MicroPython_BUILD/components/micropython/py/objexcept.c index b87609a6..1e746bc8 100644 --- a/MicroPython_BUILD/components/micropython/py/objexcept.c +++ b/MicroPython_BUILD/components/micropython/py/objexcept.c @@ -43,9 +43,6 @@ // Number of traceback entries to reserve in the emergency exception buffer #define EMG_TRACEBACK_ALLOC (2 * TRACEBACK_ENTRY_LEN) -// Instance of MemoryError exception - needed by mp_malloc_fail -const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; - // Optionally allocated buffer for storing the first argument of an exception // allocated when the heap is locked. #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF @@ -96,7 +93,7 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) { // definition module-private so far, have it here. const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj}; -STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in); mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS; bool is_subclass = kind & PRINT_EXC_SUBCLASS; @@ -118,7 +115,7 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) { qstr qst = mp_errno_to_str(o->args->items[0]); if (qst != MP_QSTR_NULL) { - mp_printf(print, "[Errno %d] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst); + mp_printf(print, "[Errno " INT_FMT "] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst); return; } } @@ -189,7 +186,7 @@ mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) { } } -STATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); if (dest[0] != MP_OBJ_NULL) { // store/delete attribute @@ -212,37 +209,12 @@ STATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -STATIC mp_obj_t exc___init__(size_t n_args, const mp_obj_t *args) { - mp_obj_exception_t *self = MP_OBJ_TO_PTR(args[0]); - mp_obj_t argst = mp_obj_new_tuple(n_args - 1, args + 1); - self->args = MP_OBJ_TO_PTR(argst); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(exc___init___obj, 1, MP_OBJ_FUN_ARGS_MAX, exc___init__); - -STATIC const mp_rom_map_elem_t exc_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&exc___init___obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(exc_locals_dict, exc_locals_dict_table); - const mp_obj_type_t mp_type_BaseException = { { &mp_type_type }, .name = MP_QSTR_BaseException, .print = mp_obj_exception_print, .make_new = mp_obj_exception_make_new, - .attr = exception_attr, - .locals_dict = (mp_obj_dict_t*)&exc_locals_dict, -}; - -#define MP_DEFINE_EXCEPTION(exc_name, base_name) \ -const mp_obj_type_t mp_type_ ## exc_name = { \ - { &mp_type_type }, \ - .name = MP_QSTR_ ## exc_name, \ - .print = mp_obj_exception_print, \ - .make_new = mp_obj_exception_make_new, \ - .attr = exception_attr, \ - .parent = &mp_type_ ## base_name, \ + .attr = mp_obj_exception_attr, }; // List of all exceptions, arranged as in the table at: diff --git a/MicroPython_BUILD/components/micropython/py/objexcept.h b/MicroPython_BUILD/components/micropython/py/objexcept.h index f67651a7..7c307622 100644 --- a/MicroPython_BUILD/components/micropython/py/objexcept.h +++ b/MicroPython_BUILD/components/micropython/py/objexcept.h @@ -37,4 +37,17 @@ typedef struct _mp_obj_exception_t { mp_obj_tuple_t *args; } mp_obj_exception_t; +void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); +void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); + +#define MP_DEFINE_EXCEPTION(exc_name, base_name) \ +const mp_obj_type_t mp_type_ ## exc_name = { \ + { &mp_type_type }, \ + .name = MP_QSTR_ ## exc_name, \ + .print = mp_obj_exception_print, \ + .make_new = mp_obj_exception_make_new, \ + .attr = mp_obj_exception_attr, \ + .parent = &mp_type_ ## base_name, \ +}; + #endif // MICROPY_INCLUDED_PY_OBJEXCEPT_H diff --git a/MicroPython_BUILD/components/micropython/py/objfloat.c b/MicroPython_BUILD/components/micropython/py/objfloat.c index 743287be..aa85970c 100644 --- a/MicroPython_BUILD/components/micropython/py/objfloat.c +++ b/MicroPython_BUILD/components/micropython/py/objfloat.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -57,6 +58,17 @@ const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI}; #endif +// LoBo: Enable runtime float precision change +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C + int float_precision = 6; + #else + int float_precision = 7; + #endif +#else + int float_precision = 15; +#endif + #if MICROPY_FLOAT_HIGH_QUALITY_HASH // must return actual integer value if it fits in mp_int_t mp_int_t mp_float_hash(mp_float_t src) { @@ -109,17 +121,10 @@ typedef uint32_t mp_float_uint_t; STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_float_t o_val = mp_obj_float_get(o_in); -#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT - char buf[16]; - #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C - const int precision = 6; - #else - const int precision = 7; - #endif -#else + // LoBo: Runtime float precision change enabled char buf[32]; - const int precision = 16; -#endif + const int precision = float_precision; + mp_format_float(o_val, buf, sizeof(buf), 'g', precision, '\0'); mp_print_str(print, buf); if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) { @@ -137,12 +142,11 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size return mp_obj_new_float(0); case 1: - default: - if (MP_OBJ_IS_STR(args[0])) { - // a string, parse it - size_t l; - const char *s = mp_obj_str_get_data(args[0], &l); - return mp_parse_num_decimal(s, l, false, false, NULL); + default: { + mp_buffer_info_t bufinfo; + if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { + // a textual representation, parse it + return mp_parse_num_decimal(bufinfo.buf, bufinfo.len, false, false, NULL); } else if (mp_obj_is_float(args[0])) { // a float, just return it return args[0]; @@ -150,6 +154,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size // something else, try to cast it to a float return mp_obj_new_float(mp_obj_get_float(args[0])); } + } } } @@ -293,7 +298,7 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t break; case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: - if (lhs_val == 0 && rhs_val < 0) { + if (lhs_val == 0 && rhs_val < 0 && !isinf(rhs_val)) { goto zero_division_error; } if (lhs_val < 0 && rhs_val != MICROPY_FLOAT_C_FUN(floor)(rhs_val)) { diff --git a/MicroPython_BUILD/components/micropython/py/objfun.c b/MicroPython_BUILD/components/micropython/py/objfun.c index 030b3f7c..e6d33d28 100644 --- a/MicroPython_BUILD/components/micropython/py/objfun.c +++ b/MicroPython_BUILD/components/micropython/py/objfun.c @@ -195,32 +195,53 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) { // than this will try to use the heap, with fallback to stack allocation. #define VM_MAX_STATE_ON_STACK (11 * sizeof(mp_uint_t)) -// Set this to enable a simple stack overflow check. +// Set this to 1 to enable a simple stack overflow check. #define VM_DETECT_STACK_OVERFLOW (0) +#define DECODE_CODESTATE_SIZE(bytecode, n_state_out_var, state_size_out_var) \ + { \ + /* bytecode prelude: state size and exception stack size */ \ + n_state_out_var = mp_decode_uint_value(bytecode); \ + size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(bytecode)); \ + \ + n_state += VM_DETECT_STACK_OVERFLOW; \ + \ + /* state size in bytes */ \ + state_size_out_var = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); \ + } + +#define INIT_CODESTATE(code_state, _fun_bc, n_args, n_kw, args) \ + code_state->fun_bc = _fun_bc; \ + code_state->ip = 0; \ + mp_setup_code_state(code_state, n_args, n_kw, args); \ + code_state->old_globals = mp_globals_get(); + #if MICROPY_STACKLESS mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { MP_STACK_CHECK(); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); - // bytecode prelude: state size and exception stack size - size_t n_state = mp_decode_uint_value(self->bytecode); - size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode)); + size_t n_state, state_size; + DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size); - // allocate state for locals and stack - size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); mp_code_state_t *code_state; + #if MICROPY_ENABLE_PYSTACK + code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size); + #else + // If we use m_new_obj_var(), then on no memory, MemoryError will be + // raised. But this is not correct exception for a function call, + // RuntimeError should be raised instead. So, we use m_new_obj_var_maybe(), + // return NULL, then vm.c takes the needed action (either raise + // RuntimeError or fallback to stack allocation). code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); if (!code_state) { return NULL; } + #endif - code_state->fun_bc = self; - code_state->ip = 0; - mp_setup_code_state(code_state, n_args, n_kw, args); + INIT_CODESTATE(code_state, self, n_args, n_kw, args); // execute the byte code with the correct globals context - code_state->old_globals = mp_globals_get(); mp_globals_set(self->globals); return code_state; @@ -238,17 +259,14 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); DEBUG_printf("Func n_def_args: %d\n", self->n_def_args); - // bytecode prelude: state size and exception stack size - size_t n_state = mp_decode_uint_value(self->bytecode); - size_t n_exc_stack = mp_decode_uint_value(mp_decode_uint_skip(self->bytecode)); - -#if VM_DETECT_STACK_OVERFLOW - n_state += 1; -#endif + size_t n_state, state_size; + DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size); // allocate state for locals and stack - size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); mp_code_state_t *code_state = NULL; + #if MICROPY_ENABLE_PYSTACK + code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size); + #else if (state_size > VM_MAX_STATE_ON_STACK) { code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); } @@ -256,13 +274,11 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const code_state = alloca(sizeof(mp_code_state_t) + state_size); state_size = 0; // indicate that we allocated using alloca } + #endif - code_state->fun_bc = self; - code_state->ip = 0; - mp_setup_code_state(code_state, n_args, n_kw, args); + INIT_CODESTATE(code_state, self, n_args, n_kw, args); // execute the byte code with the correct globals context - code_state->old_globals = mp_globals_get(); mp_globals_set(self->globals); mp_vm_return_kind_t vm_return_kind = mp_execute_bytecode(code_state, MP_OBJ_NULL); mp_globals_set(code_state->old_globals); @@ -304,10 +320,14 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const result = code_state->state[n_state - 1]; } + #if MICROPY_ENABLE_PYSTACK + mp_pystack_free(code_state); + #else // free the state if it was allocated on the heap if (state_size != 0) { m_del_var(mp_code_state_t, byte, state_size, code_state); } + #endif if (vm_return_kind == MP_VM_RETURN_NORMAL) { return result; diff --git a/MicroPython_BUILD/components/micropython/py/objgenerator.c b/MicroPython_BUILD/components/micropython/py/objgenerator.c index bf0bbb0e..5fd13f83 100644 --- a/MicroPython_BUILD/components/micropython/py/objgenerator.c +++ b/MicroPython_BUILD/components/micropython/py/objgenerator.c @@ -4,7 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George - * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,6 +32,7 @@ #include "py/bc.h" #include "py/objgenerator.h" #include "py/objfun.h" +#include "py/stackctrl.h" /******************************************************************************/ /* generator wrapper */ @@ -92,6 +93,7 @@ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pri } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { + MP_STACK_CHECK(); mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance)); mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); if (self->code_state.ip == 0) { @@ -104,7 +106,16 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ mp_raise_TypeError("can't send non-None value to a just-started generator"); } } else { - *self->code_state.sp = send_value; + #if MICROPY_PY_GENERATOR_PEND_THROW + // If exception is pending (set using .pend_throw()), process it now. + if (*self->code_state.sp != mp_const_none) { + throw_value = *self->code_state.sp; + *self->code_state.sp = MP_OBJ_NULL; + } else + #endif + { + *self->code_state.sp = send_value; + } } mp_obj_dict_t *old_globals = mp_globals_get(); mp_globals_set(self->globals); @@ -125,9 +136,9 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ case MP_VM_RETURN_YIELD: *ret_val = *self->code_state.sp; - if (*ret_val == MP_OBJ_STOP_ITERATION) { - self->code_state.ip = 0; - } + #if MICROPY_PY_GENERATOR_PEND_THROW + *self->code_state.sp = mp_const_none; + #endif break; case MP_VM_RETURN_EXCEPTION: { @@ -222,10 +233,24 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close); +STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { + mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); + if (self->code_state.sp == self->code_state.state - 1) { + mp_raise_TypeError("can't pend throw to just-started generator"); + } + mp_obj_t prev = *self->code_state.sp; + *self->code_state.sp = exc_in; + return prev; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_pend_throw_obj, gen_instance_pend_throw); + STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gen_instance_close_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&gen_instance_send_obj) }, { MP_ROM_QSTR(MP_QSTR_throw), MP_ROM_PTR(&gen_instance_throw_obj) }, + #if MICROPY_PY_GENERATOR_PEND_THROW + { MP_ROM_QSTR(MP_QSTR_pend_throw), MP_ROM_PTR(&gen_instance_pend_throw_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table); diff --git a/MicroPython_BUILD/components/micropython/py/objint.c b/MicroPython_BUILD/components/micropython/py/objint.c index 4f2e610a..270e1696 100644 --- a/MicroPython_BUILD/components/micropython/py/objint.c +++ b/MicroPython_BUILD/components/micropython/py/objint.c @@ -222,27 +222,26 @@ size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char co char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { fmt_int_t num; + #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE + // Only have small ints; get the integer value to format. + num = MP_OBJ_SMALL_INT_VALUE(self_in); + #else if (MP_OBJ_IS_SMALL_INT(self_in)) { // A small int; get the integer value to format. num = MP_OBJ_SMALL_INT_VALUE(self_in); -#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE - } else if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) { + } else { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); // Not a small int. -#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG + #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG const mp_obj_int_t *self = self_in; // Get the value to format; mp_obj_get_int truncates to mp_int_t. num = self->val; -#else + #else // Delegate to the implementation for the long int. return mp_obj_int_formatted_impl(buf, buf_size, fmt_size, self_in, base, prefix, base_char, comma); -#endif -#endif - } else { - // Not an int. - **buf = '\0'; - *fmt_size = 0; - return *buf; + #endif } + #endif char sign = '\0'; if (num < 0) { @@ -378,7 +377,7 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp // true acts as 0 return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1)); } else if (op == MP_BINARY_OP_MULTIPLY) { - if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_bytes) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) { + if (MP_OBJ_IS_STR_OR_BYTES(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) { // multiply is commutative for these types, so delegate to them return mp_binary_op(op, rhs_in, lhs_in); } diff --git a/MicroPython_BUILD/components/micropython/py/objint_longlong.c b/MicroPython_BUILD/components/micropython/py/objint_longlong.c index 2e567c57..cb8d1672 100644 --- a/MicroPython_BUILD/components/micropython/py/objint_longlong.c +++ b/MicroPython_BUILD/components/micropython/py/objint_longlong.c @@ -124,10 +124,9 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i if (MP_OBJ_IS_SMALL_INT(lhs_in)) { lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in); - } else if (MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)) { - lhs_val = ((mp_obj_int_t*)lhs_in)->val; } else { - return MP_OBJ_NULL; // op not supported + assert(MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)); + lhs_val = ((mp_obj_int_t*)lhs_in)->val; } if (MP_OBJ_IS_SMALL_INT(rhs_in)) { @@ -151,9 +150,15 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_obj_new_int_from_ll(lhs_val * rhs_val); case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: + if (rhs_val == 0) { + goto zero_division; + } return mp_obj_new_int_from_ll(lhs_val / rhs_val); case MP_BINARY_OP_MODULO: case MP_BINARY_OP_INPLACE_MODULO: + if (rhs_val == 0) { + goto zero_division; + } return mp_obj_new_int_from_ll(lhs_val % rhs_val); case MP_BINARY_OP_AND: @@ -210,6 +215,9 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i default: return MP_OBJ_NULL; // op not supported } + +zero_division: + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } mp_obj_t mp_obj_new_int(mp_int_t value) { diff --git a/MicroPython_BUILD/components/micropython/py/objint_mpz.c b/MicroPython_BUILD/components/micropython/py/objint_mpz.c index 2cc6594f..c6c07bc0 100644 --- a/MicroPython_BUILD/components/micropython/py/objint_mpz.c +++ b/MicroPython_BUILD/components/micropython/py/objint_mpz.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -170,11 +171,9 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i if (MP_OBJ_IS_SMALL_INT(lhs_in)) { mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in)); zlhs = &z_int; - } else if (MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)) { - zlhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(lhs_in))->mpz; } else { - // unsupported type - return MP_OBJ_NULL; + assert(MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)); + zlhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(lhs_in))->mpz; } // if rhs is small int, then lhs was not (otherwise mp_binary_op handles it) @@ -207,7 +206,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_obj_new_float(flhs / frhs); #endif - } else if (op >= MP_BINARY_OP_INPLACE_OR) { + } else if (op >= MP_BINARY_OP_INPLACE_OR && op < MP_BINARY_OP_CONTAINS) { mp_obj_int_t *res = mp_obj_int_new_mpz(); switch (op) { @@ -411,14 +410,15 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { mp_raise_msg(&mp_type_OverflowError, "overflow converting long int to machine word"); } } + return 0; } -uint64_t mp_obj_int64_get_checked(mp_const_obj_t self_in) { +int64_t mp_obj_int64_get_checked(mp_const_obj_t self_in) { if (MP_OBJ_IS_SMALL_INT(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); } else { const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); - uint64_t value; + int64_t value; if (mpz_as_int64_checked(&self->mpz, &value)) { return value; } else { @@ -426,6 +426,23 @@ uint64_t mp_obj_int64_get_checked(mp_const_obj_t self_in) { mp_raise_msg(&mp_type_OverflowError, "overflow converting int64 to machine word"); } } + return 0; +} + +uint64_t mp_obj_uint64_get_checked(mp_const_obj_t self_in) { + if (MP_OBJ_IS_SMALL_INT(self_in)) { + return MP_OBJ_SMALL_INT_VALUE(self_in); + } else { + const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); + uint64_t value; + if (mpz_as_uint64_checked(&self->mpz, &value)) { + return value; + } else { + // overflow + mp_raise_msg(&mp_type_OverflowError, "overflow converting uint64 to machine word"); + } + } + return 0; } #if MICROPY_PY_BUILTINS_FLOAT diff --git a/MicroPython_BUILD/components/micropython/py/objlist.h b/MicroPython_BUILD/components/micropython/py/objlist.h index 28b5495a..a43663db 100644 --- a/MicroPython_BUILD/components/micropython/py/objlist.h +++ b/MicroPython_BUILD/components/micropython/py/objlist.h @@ -35,4 +35,6 @@ typedef struct _mp_obj_list_t { mp_obj_t *items; } mp_obj_list_t; +void mp_obj_list_init(mp_obj_list_t *o, size_t n); + #endif // MICROPY_INCLUDED_PY_OBJLIST_H diff --git a/MicroPython_BUILD/components/micropython/py/objmodule.c b/MicroPython_BUILD/components/micropython/py/objmodule.c index f9363e37..c4aba3a7 100644 --- a/MicroPython_BUILD/components/micropython/py/objmodule.c +++ b/MicroPython_BUILD/components/micropython/py/objmodule.c @@ -247,17 +247,7 @@ mp_obj_t mp_module_get(qstr module_name) { if (el == NULL) { return MP_OBJ_NULL; } - - if (MICROPY_MODULE_BUILTIN_INIT) { - // look for __init__ and call it if it exists - mp_obj_t dest[2]; - mp_load_method_maybe(el->value, MP_QSTR___init__, dest); - if (dest[0] != MP_OBJ_NULL) { - mp_call_method_n_kw(0, 0, dest); - // register module so __init__ is not called again - mp_module_register(module_name, el->value); - } - } + mp_module_call_init(module_name, el->value); } // module found, return it @@ -268,3 +258,19 @@ void mp_module_register(qstr qst, mp_obj_t module) { mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module; } + +#if MICROPY_MODULE_BUILTIN_INIT +void mp_module_call_init(qstr module_name, mp_obj_t module_obj) { + // Look for __init__ and call it if it exists + mp_obj_t dest[2]; + mp_load_method_maybe(module_obj, MP_QSTR___init__, dest); + if (dest[0] != MP_OBJ_NULL) { + mp_call_method_n_kw(0, 0, dest); + // Register module so __init__ is not called again. + // If a module can be referenced by more than one name (eg due to weak links) + // then __init__ will still be called for each distinct import, and it's then + // up to the particular module to make sure it's __init__ code only runs once. + mp_module_register(module_name, module_obj); + } +} +#endif diff --git a/MicroPython_BUILD/components/micropython/py/objmodule.h b/MicroPython_BUILD/components/micropython/py/objmodule.h index b5c07dc3..b7702ec5 100644 --- a/MicroPython_BUILD/components/micropython/py/objmodule.h +++ b/MicroPython_BUILD/components/micropython/py/objmodule.h @@ -34,4 +34,13 @@ extern const mp_map_t mp_builtin_module_weak_links_map; mp_obj_t mp_module_get(qstr module_name); void mp_module_register(qstr qstr, mp_obj_t module); +#if MICROPY_MODULE_BUILTIN_INIT +void mp_module_call_init(qstr module_name, mp_obj_t module_obj); +#else +static inline void mp_module_call_init(qstr module_name, mp_obj_t module_obj) { + (void)module_name; + (void)module_obj; +} +#endif + #endif // MICROPY_INCLUDED_PY_OBJMODULE_H diff --git a/MicroPython_BUILD/components/micropython/py/objnamedtuple.c b/MicroPython_BUILD/components/micropython/py/objnamedtuple.c index 38daccdf..e7de899c 100644 --- a/MicroPython_BUILD/components/micropython/py/objnamedtuple.c +++ b/MicroPython_BUILD/components/micropython/py/objnamedtuple.c @@ -30,20 +30,11 @@ #include "py/objtuple.h" #include "py/runtime.h" #include "py/objstr.h" +#include "py/objnamedtuple.h" #if MICROPY_PY_COLLECTIONS -typedef struct _mp_obj_namedtuple_type_t { - mp_obj_type_t base; - size_t n_fields; - qstr fields[]; -} mp_obj_namedtuple_type_t; - -typedef struct _mp_obj_namedtuple_t { - mp_obj_tuple_t tuple; -} mp_obj_namedtuple_t; - -STATIC size_t namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) { +size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) { for (size_t i = 0; i < type->n_fields; i++) { if (type->fields[i] == name) { return i; @@ -52,6 +43,23 @@ STATIC size_t namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr n return (size_t)-1; } +#if MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT +STATIC mp_obj_t namedtuple_asdict(mp_obj_t self_in) { + mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in); + const qstr *fields = ((mp_obj_namedtuple_type_t*)self->tuple.base.type)->fields; + mp_obj_t dict = mp_obj_new_dict(self->tuple.len); + //make it an OrderedDict + mp_obj_dict_t *dictObj = MP_OBJ_TO_PTR(dict); + dictObj->base.type = &mp_type_ordereddict; + dictObj->map.is_ordered = 1; + for (size_t i = 0; i < self->tuple.len; ++i) { + mp_obj_dict_store(dict, MP_OBJ_NEW_QSTR(fields[i]), self->tuple.items[i]); + } + return dict; +} +MP_DEFINE_CONST_FUN_OBJ_1(namedtuple_asdict_obj, namedtuple_asdict); +#endif + STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_namedtuple_t *o = MP_OBJ_TO_PTR(o_in); @@ -64,7 +72,14 @@ STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in); - size_t id = namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr); + #if MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT + if (attr == MP_QSTR__asdict) { + dest[0] = MP_OBJ_FROM_PTR(&namedtuple_asdict_obj); + dest[1] = self_in; + return; + } + #endif + size_t id = mp_obj_namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr); if (id == (size_t)-1) { return; } @@ -104,7 +119,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, memset(&tuple->items[n_args], 0, sizeof(mp_obj_t) * n_kw); for (size_t i = n_args; i < n_args + 2 * n_kw; i += 2) { qstr kw = mp_obj_str_get_qstr(args[i]); - size_t id = namedtuple_find_field(type, kw); + size_t id = mp_obj_namedtuple_find_field(type, kw); if (id == (size_t)-1) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); @@ -127,9 +142,18 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, return MP_OBJ_FROM_PTR(tuple); } -STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) { +mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields) { mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields); memset(&o->base, 0, sizeof(o->base)); + o->n_fields = n_fields; + for (size_t i = 0; i < n_fields; i++) { + o->fields[i] = mp_obj_str_get_qstr(fields[i]); + } + return o; +} + +STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) { + mp_obj_namedtuple_type_t *o = mp_obj_new_namedtuple_base(n_fields, fields); o->base.base.type = &mp_type_type; o->base.name = name; o->base.print = namedtuple_print; @@ -140,10 +164,6 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t o->base.subscr = mp_obj_tuple_subscr; o->base.getiter = mp_obj_tuple_getiter; o->base.parent = &mp_type_tuple; - o->n_fields = n_fields; - for (size_t i = 0; i < n_fields; i++) { - o->fields[i] = mp_obj_str_get_qstr(fields[i]); - } return MP_OBJ_FROM_PTR(o); } diff --git a/MicroPython_BUILD/components/micropython/drivers/memory/spiflash.h b/MicroPython_BUILD/components/micropython/py/objnamedtuple.h similarity index 66% rename from MicroPython_BUILD/components/micropython/drivers/memory/spiflash.h rename to MicroPython_BUILD/components/micropython/py/objnamedtuple.h index cd96b16f..d32af35a 100644 --- a/MicroPython_BUILD/components/micropython/drivers/memory/spiflash.h +++ b/MicroPython_BUILD/components/micropython/py/objnamedtuple.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Damien P. George + * Copyright (c) 2014-2017 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,18 +23,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H -#define MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H +#ifndef MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H +#define MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H -#include "extmod/machine_spi.h" +#include "py/objtuple.h" -typedef struct _mp_spiflash_t { - mp_hal_pin_obj_t cs; - mp_obj_base_t *spi; // object must have protocol pointing to mp_machine_spi_p_t struct -} mp_spiflash_t; +typedef struct _mp_obj_namedtuple_type_t { + mp_obj_type_t base; + size_t n_fields; + qstr fields[]; +} mp_obj_namedtuple_type_t; -void mp_spiflash_init(mp_spiflash_t *self); -void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest); -int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src); +typedef struct _mp_obj_namedtuple_t { + mp_obj_tuple_t tuple; +} mp_obj_namedtuple_t; -#endif // MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H +size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name); +mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields); + +#endif // MICROPY_INCLUDED_PY_OBJNAMEDTUPLE_H diff --git a/MicroPython_BUILD/components/micropython/py/objobject.c b/MicroPython_BUILD/components/micropython/py/objobject.c index 49d2ec62..265fcfbf 100644 --- a/MicroPython_BUILD/components/micropython/py/objobject.c +++ b/MicroPython_BUILD/components/micropython/py/objobject.c @@ -52,9 +52,12 @@ STATIC mp_obj_t object___new__(mp_obj_t cls) { if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) { mp_raise_TypeError("__new__ arg must be a user-type"); } - mp_obj_t o = MP_OBJ_SENTINEL; - mp_obj_t res = mp_obj_instance_make_new(MP_OBJ_TO_PTR(cls), 1, 0, &o); - return res; + // This executes only "__new__" part of instance creation. + // TODO: This won't work well for classes with native bases. + // TODO: This is a hack, should be resolved along the lines of + // https://github.com/micropython/micropython/issues/606#issuecomment-43685883 + const mp_obj_type_t *native_base; + return MP_OBJ_FROM_PTR(mp_obj_new_instance(MP_OBJ_TO_PTR(cls), &native_base)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj)); diff --git a/MicroPython_BUILD/components/micropython/py/objrange.c b/MicroPython_BUILD/components/micropython/py/objrange.c index 3874adb1..86aa0ccf 100644 --- a/MicroPython_BUILD/components/micropython/py/objrange.c +++ b/MicroPython_BUILD/components/micropython/py/objrange.c @@ -138,6 +138,24 @@ STATIC mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } +#if MICROPY_PY_BUILTINS_RANGE_BINOP +STATIC mp_obj_t range_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + if (!MP_OBJ_IS_TYPE(rhs_in, &mp_type_range) || op != MP_BINARY_OP_EQUAL) { + return MP_OBJ_NULL; // op not supported + } + mp_obj_range_t *lhs = MP_OBJ_TO_PTR(lhs_in); + mp_obj_range_t *rhs = MP_OBJ_TO_PTR(rhs_in); + mp_int_t lhs_len = range_len(lhs); + mp_int_t rhs_len = range_len(rhs); + return mp_obj_new_bool( + lhs_len == rhs_len + && (lhs_len == 0 + || (lhs->start == rhs->start + && (lhs_len == 1 || lhs->step == rhs->step))) + ); +} +#endif + STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // load @@ -195,6 +213,9 @@ const mp_obj_type_t mp_type_range = { .print = range_print, .make_new = range_make_new, .unary_op = range_unary_op, + #if MICROPY_PY_BUILTINS_RANGE_BINOP + .binary_op = range_binary_op, + #endif .subscr = range_subscr, .getiter = range_getiter, #if MICROPY_PY_BUILTINS_RANGE_ATTRS diff --git a/MicroPython_BUILD/components/micropython/py/objset.c b/MicroPython_BUILD/components/micropython/py/objset.c index 6ed15c79..799ba9df 100644 --- a/MicroPython_BUILD/components/micropython/py/objset.c +++ b/MicroPython_BUILD/components/micropython/py/objset.c @@ -351,11 +351,9 @@ STATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) { } STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) { + assert(is_set_or_frozenset(other_in)); check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); - if (!is_set_or_frozenset(other_in)) { - return mp_const_false; - } mp_obj_set_t *other = MP_OBJ_TO_PTR(other_in); if (self->set.used != other->set.used) { return mp_const_false; @@ -461,7 +459,7 @@ STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { #else bool update = true; #endif - if (op != MP_BINARY_OP_IN && !is_set_or_frozenset(rhs)) { + if (op != MP_BINARY_OP_CONTAINS && !is_set_or_frozenset(rhs)) { // For all ops except containment the RHS must be a set/frozenset return MP_OBJ_NULL; } @@ -507,7 +505,7 @@ STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { return set_issubset(lhs, rhs); case MP_BINARY_OP_MORE_EQUAL: return set_issuperset(lhs, rhs); - case MP_BINARY_OP_IN: { + case MP_BINARY_OP_CONTAINS: { mp_obj_set_t *o = MP_OBJ_TO_PTR(lhs); mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP); return mp_obj_new_bool(elem != MP_OBJ_NULL); diff --git a/MicroPython_BUILD/components/micropython/py/objstr.c b/MicroPython_BUILD/components/micropython/py/objstr.c index 51da7a41..da925234 100644 --- a/MicroPython_BUILD/components/micropython/py/objstr.c +++ b/MicroPython_BUILD/components/micropython/py/objstr.c @@ -164,7 +164,14 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ mp_raise_msg(&mp_type_UnicodeError, NULL); } #endif - mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len)); + + // Check if a qstr with this data already exists + qstr q = qstr_find_strn((const char*)str_data, str_len); + if (q != MP_QSTR_NULL) { + return MP_OBJ_NEW_QSTR(q); + } + + mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_copy(type, NULL, str_len)); o->data = str_data; o->hash = str_hash; return MP_OBJ_FROM_PTR(o); @@ -176,7 +183,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ mp_raise_msg(&mp_type_UnicodeError, NULL); } #endif - return mp_obj_new_str(bufinfo.buf, bufinfo.len, false); + return mp_obj_new_str(bufinfo.buf, bufinfo.len); } } } @@ -205,7 +212,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size if (str_hash == 0) { str_hash = qstr_compute_hash(str_data, str_len); } - mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len)); + mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_copy(&mp_type_bytes, NULL, str_len)); o->data = str_data; o->hash = str_hash; return MP_OBJ_FROM_PTR(o); @@ -216,7 +223,10 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size } if (MP_OBJ_IS_SMALL_INT(args[0])) { - uint len = MP_OBJ_SMALL_INT_VALUE(args[0]); + mp_int_t len = MP_OBJ_SMALL_INT_VALUE(args[0]); + if (len < 0) { + mp_raise_ValueError(NULL); + } vstr_t vstr; vstr_init_len(&vstr, len); memset(vstr.buf, 0, len); @@ -226,7 +236,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size // check if argument has the buffer protocol mp_buffer_info_t bufinfo; if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { - return mp_obj_new_str_of_type(&mp_type_bytes, bufinfo.buf, bufinfo.len); + return mp_obj_new_bytes(bufinfo.buf, bufinfo.len); } vstr_t vstr; @@ -377,8 +387,7 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return mp_obj_new_str_from_vstr(lhs_type, &vstr); } - case MP_BINARY_OP_IN: - /* NOTE `a in b` is `b.__contains__(a)` */ + case MP_BINARY_OP_CONTAINS: return mp_obj_new_bool(find_subbytes(lhs_data, lhs_len, rhs_data, rhs_len, 1) != NULL); //case MP_BINARY_OP_NOT_EQUAL: // This is never passed here @@ -423,7 +432,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (MICROPY_PY_BUILTINS_STR_UNICODE || type == &mp_type_bytes) { return MP_OBJ_NEW_SMALL_INT(self_data[index_val]); } else { - return mp_obj_new_str((char*)&self_data[index_val], 1, true); + return mp_obj_new_str_via_qstr((char*)&self_data[index_val], 1); } } else { return MP_OBJ_NULL; // op not supported @@ -654,9 +663,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { } res->items[idx--] = mp_obj_new_str_of_type(self_type, s + sep_len, last - s - sep_len); last = s; - if (splits > 0) { - splits--; - } + splits--; } if (idx != 0) { // We split less parts than split limit, now go cleanup surplus @@ -692,8 +699,13 @@ STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, b end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true); } + if (end < start) { + goto out_error; + } + const byte *p = find_subbytes(start, end - start, needle, needle_len, direction); if (p == NULL) { + out_error: // not found if (is_index) { mp_raise_ValueError("substring not found"); @@ -1046,7 +1058,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } else { const char *lookup; for (lookup = field_name; lookup < field_name_top && *lookup != '.' && *lookup != '['; lookup++); - mp_obj_t field_q = mp_obj_new_str(field_name, lookup - field_name, true/*?*/); + mp_obj_t field_q = mp_obj_new_str_via_qstr(field_name, lookup - field_name); // should it be via qstr? field_name = lookup; mp_map_elem_t *key_elem = mp_map_lookup(kwargs, field_q, MP_MAP_LOOKUP); if (key_elem == NULL) { @@ -1413,7 +1425,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ } ++str; } - mp_obj_t k_obj = mp_obj_new_str((const char*)key, str - key, true); + mp_obj_t k_obj = mp_obj_new_str_via_qstr((const char*)key, str - key); arg = mp_obj_dict_get(dict, k_obj); str++; } @@ -1698,7 +1710,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { // if needle_len is zero then we count each gap between characters as an occurrence if (needle_len == 0) { - return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char*)start, end - start) + 1); + return MP_OBJ_NEW_SMALL_INT(utf8_charlen(start, end - start) + 1); } // count the occurrences @@ -1977,8 +1989,9 @@ const mp_obj_type_t mp_type_bytes = { const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, (const byte*)""}; // Create a str/bytes object using the given data. New memory is allocated and -// the data is copied across. -mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len) { +// the data is copied across. This function should only be used if the type is bytes, +// or if the type is str and the string data is known to be not interned. +mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte* data, size_t len) { mp_obj_str_t *o = m_new_obj(mp_obj_str_t); o->base.type = type; o->len = len; @@ -1992,6 +2005,22 @@ mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, siz return MP_OBJ_FROM_PTR(o); } +// Create a str/bytes object using the given data. If the type is str and the string +// data is already interned, then a qstr object is returned. Otherwise new memory is +// allocated for the object and the data is copied across. +mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len) { + if (type == &mp_type_str) { + return mp_obj_new_str((const char*)data, len); + } else { + return mp_obj_new_bytes(data, len); + } +} + +// Create a str using a qstr to store the data; may use existing or new qstr. +mp_obj_t mp_obj_new_str_via_qstr(const char* data, size_t len) { + return MP_OBJ_NEW_QSTR(qstr_from_strn(data, len)); +} + // Create a str/bytes object from the given vstr. The vstr buffer is resized to // the exact length required and then reused for the str/bytes object. The vstr // is cleared and can safely be passed to vstr_free if it was heap allocated. @@ -2022,29 +2051,30 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { return MP_OBJ_FROM_PTR(o); } -mp_obj_t mp_obj_new_str(const char* data, size_t len, bool make_qstr_if_not_already) { - if (make_qstr_if_not_already) { - // use existing, or make a new qstr - return MP_OBJ_NEW_QSTR(qstr_from_strn(data, len)); +mp_obj_t mp_obj_new_str(const char* data, size_t len) { + qstr q = qstr_find_strn(data, len); + if (q != MP_QSTR_NULL) { + // qstr with this data already exists + return MP_OBJ_NEW_QSTR(q); } else { - qstr q = qstr_find_strn(data, len); - if (q != MP_QSTR_NULL) { - // qstr with this data already exists - return MP_OBJ_NEW_QSTR(q); - } else { - // no existing qstr, don't make one - return mp_obj_new_str_of_type(&mp_type_str, (const byte*)data, len); - } + // no existing qstr, don't make one + return mp_obj_new_str_copy(&mp_type_str, (const byte*)data, len); } } mp_obj_t mp_obj_str_intern(mp_obj_t str) { GET_STR_DATA_LEN(str, data, len); - return MP_OBJ_NEW_QSTR(qstr_from_strn((const char*)data, len)); + return mp_obj_new_str_via_qstr((const char*)data, len); +} + +mp_obj_t mp_obj_str_intern_checked(mp_obj_t obj) { + size_t len; + const char *data = mp_obj_str_get_data(obj, &len); + return mp_obj_new_str_via_qstr((const char*)data, len); } mp_obj_t mp_obj_new_bytes(const byte* data, size_t len) { - return mp_obj_new_str_of_type(&mp_type_bytes, data, len); + return mp_obj_new_str_copy(&mp_type_bytes, data, len); } bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) { @@ -2066,7 +2096,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) { } } -STATIC void bad_implicit_conversion(mp_obj_t self_in) { +STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("can't convert to str implicitly"); } else { @@ -2138,7 +2168,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { - mp_obj_t o_out = mp_obj_new_str((const char*)str + self->cur, 1, true); + mp_obj_t o_out = mp_obj_new_str_via_qstr((const char*)str + self->cur, 1); self->cur += 1; return o_out; } else { diff --git a/MicroPython_BUILD/components/micropython/py/objstr.h b/MicroPython_BUILD/components/micropython/py/objstr.h index 82501a76..4e55cad0 100644 --- a/MicroPython_BUILD/components/micropython/py/objstr.h +++ b/MicroPython_BUILD/components/micropython/py/objstr.h @@ -65,6 +65,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len); mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args); +mp_obj_t mp_obj_new_str_copy(const mp_obj_type_t *type, const byte* data, size_t len); mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len); mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); diff --git a/MicroPython_BUILD/components/micropython/py/objstringio.c b/MicroPython_BUILD/components/micropython/py/objstringio.c index 5c50aa31..b405ee21 100644 --- a/MicroPython_BUILD/components/micropython/py/objstringio.c +++ b/MicroPython_BUILD/components/micropython/py/objstringio.c @@ -143,6 +143,17 @@ STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, } case MP_STREAM_FLUSH: return 0; + case MP_STREAM_CLOSE: + #if MICROPY_CPYTHON_COMPAT + vstr_free(o->vstr); + o->vstr = NULL; + #else + vstr_clear(o->vstr); + o->vstr->alloc = 0; + o->vstr->len = 0; + o->pos = 0; + #endif + return 0; default: *errcode = MP_EINVAL; return MP_STREAM_ERROR; @@ -159,24 +170,9 @@ STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue); -STATIC mp_obj_t stringio_close(mp_obj_t self_in) { - mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in); -#if MICROPY_CPYTHON_COMPAT - vstr_free(self->vstr); - self->vstr = NULL; -#else - vstr_clear(self->vstr); - self->vstr->alloc = 0; - self->vstr->len = 0; - self->pos = 0; -#endif - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_close_obj, stringio_close); - STATIC mp_obj_t stringio___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; - return stringio_close(args[0]); + return mp_stream_close(args[0]); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio___exit__); @@ -233,7 +229,7 @@ STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&stringio_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, { MP_ROM_QSTR(MP_QSTR_getvalue), MP_ROM_PTR(&stringio_getvalue_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&stringio___exit___obj) }, diff --git a/MicroPython_BUILD/components/micropython/py/objstrunicode.c b/MicroPython_BUILD/components/micropython/py/objstrunicode.c index 29f7695b..badb569d 100644 --- a/MicroPython_BUILD/components/micropython/py/objstrunicode.c +++ b/MicroPython_BUILD/components/micropython/py/objstrunicode.c @@ -104,7 +104,7 @@ STATIC mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(str_len != 0); case MP_UNARY_OP_LEN: - return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char *)str_data, str_len)); + return MP_OBJ_NEW_SMALL_INT(utf8_charlen(str_data, str_len)); default: return MP_OBJ_NULL; // op not supported } @@ -216,7 +216,7 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { ++len; } } - return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string + return mp_obj_new_str_via_qstr((const char*)s, len); // This will create a one-character string } else { return MP_OBJ_NULL; // op not supported } @@ -291,7 +291,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { if (self->cur < len) { const byte *cur = str + self->cur; const byte *end = utf8_next_char(str + self->cur); - mp_obj_t o_out = mp_obj_new_str((const char*)cur, end - cur, true); + mp_obj_t o_out = mp_obj_new_str_via_qstr((const char*)cur, end - cur); self->cur += end - cur; return o_out; } else { diff --git a/MicroPython_BUILD/components/micropython/py/objtype.c b/MicroPython_BUILD/components/micropython/py/objtype.c index 6e2ab6c9..7df349ce 100644 --- a/MicroPython_BUILD/components/micropython/py/objtype.c +++ b/MicroPython_BUILD/components/micropython/py/objtype.c @@ -46,14 +46,6 @@ STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_ /******************************************************************************/ // instance object -STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, size_t subobjs) { - mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs); - o->base.type = class; - mp_map_init(&o->members, 0); - mp_seq_clear(o->subobj, 0, subobjs, sizeof(*o->subobj)); - return MP_OBJ_FROM_PTR(o); -} - STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) { int count = 0; for (;;) { @@ -67,6 +59,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t } else if (type->parent == NULL) { // No parents so end search here. return count; + #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) { // Multiple parents, search through them all recursively. const mp_obj_tuple_t *parent_tuple = type->parent; @@ -78,6 +71,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t count += instance_count_native_bases(bt, last_native_base); } return count; + #endif } else { // A single parent, use iteration to continue the search. type = type->parent; @@ -85,6 +79,35 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t } } +// This wrapper function is allows a subclass of a native type to call the +// __init__() method (corresponding to type->make_new) of the native type. +STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *args) { + mp_obj_instance_t *self = MP_OBJ_TO_PTR(args[0]); + const mp_obj_type_t *native_base = NULL; + instance_count_native_bases(self->base.type, &native_base); + self->subobj[0] = native_base->make_new(native_base, n_args - 1, 0, args + 1); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(native_base_init_wrapper_obj, 1, MP_OBJ_FUN_ARGS_MAX, native_base_init_wrapper); + +#if !MICROPY_CPYTHON_COMPAT +STATIC +#endif +mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_type_t **native_base) { + size_t num_native_bases = instance_count_native_bases(class, native_base); + assert(num_native_bases < 2); + mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, num_native_bases); + o->base.type = class; + mp_map_init(&o->members, 0); + // Initialise the native base-class slot (should be 1 at most) with a valid + // object. It doesn't matter which object, so long as it can be uniquely + // distinguished from a native class that is initialised. + if (num_native_bases != 0) { + o->subobj[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj); + } + return o; +} + // TODO // This implements depth-first left-to-right MRO, which is not compliant with Python3 MRO // http://python-history.blogspot.com/2010/06/method-resolution-order.html @@ -172,6 +195,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_ if (type->parent == NULL) { DEBUG_printf("mp_obj_class_lookup: No more parents\n"); return; + #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) { const mp_obj_tuple_t *parent_tuple = type->parent; const mp_obj_t *item = parent_tuple->items; @@ -192,6 +216,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_ // search last base (simple tail recursion elimination) assert(MP_OBJ_IS_TYPE(*item, &mp_type_type)); type = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item); + #endif } else { type = type->parent; } @@ -247,20 +272,6 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_instance_type(self)); - const mp_obj_type_t *native_base; - size_t num_native_bases = instance_count_native_bases(self, &native_base); - assert(num_native_bases < 2); - - mp_obj_instance_t *o = MP_OBJ_TO_PTR(mp_obj_new_instance(self, num_native_bases)); - - // This executes only "__new__" part of instance creation. - // TODO: This won't work well for classes with native bases. - // TODO: This is a hack, should be resolved along the lines of - // https://github.com/micropython/micropython/issues/606#issuecomment-43685883 - if (n_args == 1 && *args == MP_OBJ_SENTINEL) { - return MP_OBJ_FROM_PTR(o); - } - // look for __new__ function mp_obj_t init_fn[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { @@ -272,13 +283,22 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size }; mp_obj_class_lookup(&lookup, self); - mp_obj_t new_ret = MP_OBJ_FROM_PTR(o); - if (init_fn[0] == MP_OBJ_SENTINEL) { - // Native type's constructor is what wins - it gets all our arguments, - // and none Python classes are initialized at all. - o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args); - } else if (init_fn[0] != MP_OBJ_NULL) { - // now call Python class __new__ function with all args + const mp_obj_type_t *native_base = NULL; + mp_obj_instance_t *o; + if (init_fn[0] == MP_OBJ_NULL || init_fn[0] == MP_OBJ_SENTINEL) { + // Either there is no __new__() method defined or there is a native + // constructor. In both cases create a blank instance. + o = mp_obj_new_instance(self, &native_base); + + // Since type->make_new() implements both __new__() and __init__() in + // one go, of which the latter may be overridden by the Python subclass, + // we defer (see the end of this function) the call of the native + // constructor to give a chance for the Python __init__() method to call + // said native constructor. + + } else { + // Call Python class __new__ function with all args to create an instance + mp_obj_t new_ret; if (n_args == 0 && n_kw == 0) { mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)}; new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2); @@ -290,17 +310,20 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw); } - } + // https://docs.python.org/3.4/reference/datamodel.html#object.__new__ + // "If __new__() does not return an instance of cls, then the new + // instance's __init__() method will not be invoked." + if (mp_obj_get_type(new_ret) != self) { + return new_ret; + } - // https://docs.python.org/3.4/reference/datamodel.html#object.__new__ - // "If __new__() does not return an instance of cls, then the new instance's __init__() method will not be invoked." - if (mp_obj_get_type(new_ret) != self) { - return new_ret; + // The instance returned by __new__() becomes the new object + o = MP_OBJ_TO_PTR(new_ret); } - o = MP_OBJ_TO_PTR(new_ret); - // now call Python class __init__ function with all args + // This method has a chance to call super().__init__() to construct a + // possible native base class. init_fn[0] = init_fn[1] = MP_OBJ_NULL; lookup.obj = o; lookup.attr = MP_QSTR___init__; @@ -329,6 +352,12 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size } + // If the type had a native base that was not explicitly initialised + // (constructed) by the Python __init__() method then construct it now. + if (native_base != NULL && o->subobj[0] == MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj)) { + o->subobj[0] = native_base->make_new(native_base, n_args, n_kw, args); + } + return MP_OBJ_FROM_PTR(o); } @@ -420,7 +449,7 @@ const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = { [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__, [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__, // MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result - [MP_BINARY_OP_IN] = MP_QSTR___contains__, + [MP_BINARY_OP_CONTAINS] = MP_QSTR___contains__, // All inplace methods are optional, and normal methods will be used // as a fallback. @@ -946,21 +975,21 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (self->locals_dict != NULL) { assert(self->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now mp_map_t *locals_map = &self->locals_dict->map; + if (locals_map->is_fixed) { + // can't apply delete/store to a fixed map + return; + } if (dest[1] == MP_OBJ_NULL) { // delete attribute mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND); - // note that locals_map may be in ROM, so remove will fail in that case if (elem != NULL) { dest[0] = MP_OBJ_NULL; // indicate success } } else { // store attribute mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); - // note that locals_map may be in ROM, so add will fail in that case - if (elem != NULL) { - elem->value = dest[1]; - dest[0] = MP_OBJ_NULL; // indicate success - } + elem->value = dest[1]; + dest[0] = MP_OBJ_NULL; // indicate success } } } @@ -983,12 +1012,12 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // TODO might need to make a copy of locals_dict; at least that's how CPython does it // Basic validation of base classes - size_t len; - mp_obj_t *items; - mp_obj_tuple_get(bases_tuple, &len, &items); - for (size_t i = 0; i < len; i++) { - assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); - mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]); + size_t bases_len; + mp_obj_t *bases_items; + mp_obj_tuple_get(bases_tuple, &bases_len, &bases_items); + for (size_t i = 0; i < bases_len; i++) { + assert(MP_OBJ_IS_TYPE(bases_items[i], &mp_type_type)); + mp_obj_type_t *t = MP_OBJ_TO_PTR(bases_items[i]); // TODO: Verify with CPy, tested on function type if (t->make_new == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { @@ -1014,17 +1043,21 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) //o->iternext = ; not implemented o->buffer_p.get_buffer = instance_get_buffer; - if (len > 0) { + if (bases_len > 0) { // Inherit protocol from a base class. This allows to define an // abstract base class which would translate C-level protocol to // Python method calls, and any subclass inheriting from it will // support this feature. - o->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(items[0]))->protocol; + o->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(bases_items[0]))->protocol; - if (len >= 2) { + if (bases_len >= 2) { + #if MICROPY_MULTIPLE_INHERITANCE o->parent = MP_OBJ_TO_PTR(bases_tuple); + #else + mp_raise_NotImplementedError("multiple inheritance not supported"); + #endif } else { - o->parent = MP_OBJ_TO_PTR(items[0]); + o->parent = MP_OBJ_TO_PTR(bases_items[0]); } } @@ -1099,26 +1132,48 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { .is_type = false, }; + // Allow a call super().__init__() to reach any native base classes + if (attr == MP_QSTR___init__) { + lookup.meth_offset = offsetof(mp_obj_type_t, make_new); + } + if (type->parent == NULL) { // no parents, do nothing + #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) { const mp_obj_tuple_t *parent_tuple = type->parent; size_t len = parent_tuple->len; const mp_obj_t *items = parent_tuple->items; for (size_t i = 0; i < len; i++) { assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); + if (MP_OBJ_TO_PTR(items[i]) == &mp_type_object) { + // The "object" type will be searched at the end of this function, + // and we don't want to lookup native methods in object. + continue; + } mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i])); if (dest[0] != MP_OBJ_NULL) { - return; + break; } } - } else { + #endif + } else if (type->parent != &mp_type_object) { mp_obj_class_lookup(&lookup, type->parent); - if (dest[0] != MP_OBJ_NULL) { - return; + } + + if (dest[0] != MP_OBJ_NULL) { + if (dest[0] == MP_OBJ_SENTINEL) { + // Looked up native __init__ so defer to it + dest[0] = MP_OBJ_FROM_PTR(&native_base_init_wrapper_obj); + dest[1] = self->obj; } + return; } + // Reset meth_offset so we don't look up any native methods in object, + // because object never takes up the native base-class slot. + lookup.meth_offset = 0; + mp_obj_class_lookup(&lookup, &mp_type_object); } @@ -1158,6 +1213,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { if (self->parent == NULL) { // type has no parents return false; + #if MICROPY_MULTIPLE_INHERITANCE } else if (((mp_obj_base_t*)self->parent)->type == &mp_type_tuple) { // get the base objects (they should be type objects) const mp_obj_tuple_t *parent_tuple = self->parent; @@ -1173,6 +1229,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { // search last base (simple tail recursion elimination) object = *item; + #endif } else { // type has 1 parent object = MP_OBJ_FROM_PTR(self->parent); diff --git a/MicroPython_BUILD/components/micropython/py/objtype.h b/MicroPython_BUILD/components/micropython/py/objtype.h index 52419f3c..1f431308 100644 --- a/MicroPython_BUILD/components/micropython/py/objtype.h +++ b/MicroPython_BUILD/components/micropython/py/objtype.h @@ -37,6 +37,11 @@ typedef struct _mp_obj_instance_t { // TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them } mp_obj_instance_t; +#if MICROPY_CPYTHON_COMPAT +// this is needed for object.__new__ +mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *cls, const mp_obj_type_t **native_base); +#endif + // this needs to be exposed for MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE to work void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); diff --git a/MicroPython_BUILD/components/micropython/py/opmethods.c b/MicroPython_BUILD/components/micropython/py/opmethods.c index 1200ba39..247fa5bb 100644 --- a/MicroPython_BUILD/components/micropython/py/opmethods.c +++ b/MicroPython_BUILD/components/micropython/py/opmethods.c @@ -24,7 +24,7 @@ * THE SOFTWARE. */ -#include "py/runtime0.h" +#include "py/obj.h" #include "py/builtin.h" STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { @@ -47,6 +47,6 @@ MP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem); STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_type_t *type = mp_obj_get_type(lhs_in); - return type->binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in); + return type->binary_op(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains); diff --git a/MicroPython_BUILD/components/micropython/py/parse.c b/MicroPython_BUILD/components/micropython/py/parse.c index 8c51b034..8c128649 100644 --- a/MicroPython_BUILD/components/micropython/py/parse.c +++ b/MicroPython_BUILD/components/micropython/py/parse.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013-2015 Damien P. George + * Copyright (c) 2013-2017 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -58,15 +58,6 @@ // (un)comment to use rule names; for debugging //#define USE_RULE_NAME (1) -typedef struct _rule_t { - byte rule_id; - byte act; -#ifdef USE_RULE_NAME - const char *rule_name; -#endif - uint16_t arg[]; -} rule_t; - enum { // define rules with a compile function #define DEF_RULE(rule, comp, kind, ...) RULE_##rule, @@ -84,6 +75,8 @@ enum { #undef DEF_RULE_NC }; +// Define an array of actions corresponding to each rule +STATIC const uint8_t rule_act_table[] = { #define or(n) (RULE_ACT_OR | n) #define and(n) (RULE_ACT_AND | n) #define and_ident(n) (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT) @@ -91,44 +84,128 @@ enum { #define one_or_more (RULE_ACT_LIST | 2) #define list (RULE_ACT_LIST | 1) #define list_with_end (RULE_ACT_LIST | 3) -#define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t) -#define rule(r) (RULE_ARG_RULE | RULE_##r) -#define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r) -#ifdef USE_RULE_NAME -#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } }; -#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } }; -#else -#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } }; -#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } }; -#endif + +#define DEF_RULE(rule, comp, kind, ...) kind, +#define DEF_RULE_NC(rule, kind, ...) +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC + + 0, // RULE_const_object + +#define DEF_RULE(rule, comp, kind, ...) +#define DEF_RULE_NC(rule, kind, ...) kind, #include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC + #undef or #undef and +#undef and_ident +#undef and_blank +#undef one_or_more #undef list #undef list_with_end +}; + +// Define the argument data for each rule, as a combined array +STATIC const uint16_t rule_arg_combined_table[] = { +#define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t) +#define rule(r) (RULE_ARG_RULE | RULE_##r) +#define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r) + +#define DEF_RULE(rule, comp, kind, ...) __VA_ARGS__, +#define DEF_RULE_NC(rule, kind, ...) +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC + +#define DEF_RULE(rule, comp, kind, ...) +#define DEF_RULE_NC(rule, kind, ...) __VA_ARGS__, +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC + #undef tok #undef rule #undef opt_rule -#undef one_or_more +}; + +// Macro to create a list of N identifiers where N is the number of variable arguments to the macro +#define RULE_EXPAND(x) x +#define RULE_PADDING(rule, ...) RULE_PADDING2(rule, __VA_ARGS__, RULE_PADDING_IDS(rule)) +#define RULE_PADDING2(rule, ...) RULE_EXPAND(RULE_PADDING3(rule, __VA_ARGS__)) +#define RULE_PADDING3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) __VA_ARGS__ +#define RULE_PADDING_IDS(r) PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r, + +// Use an enum to create constants specifying how much room a rule takes in rule_arg_combined_table +enum { +#define DEF_RULE(rule, comp, kind, ...) RULE_PADDING(rule, __VA_ARGS__) +#define DEF_RULE_NC(rule, kind, ...) +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC +#define DEF_RULE(rule, comp, kind, ...) +#define DEF_RULE_NC(rule, kind, ...) RULE_PADDING(rule, __VA_ARGS__) +#include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC +}; -STATIC const rule_t *const rules[] = { -// define rules with a compile function -#define DEF_RULE(rule, comp, kind, ...) &rule_##rule, +// Macro to compute the start of a rule in rule_arg_combined_table +#define RULE_ARG_OFFSET(rule, ...) RULE_ARG_OFFSET2(rule, __VA_ARGS__, RULE_ARG_OFFSET_IDS(rule)) +#define RULE_ARG_OFFSET2(rule, ...) RULE_EXPAND(RULE_ARG_OFFSET3(rule, __VA_ARGS__)) +#define RULE_ARG_OFFSET3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) _13 +#define RULE_ARG_OFFSET_IDS(r) PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r, PAD0_##r, + +// Use the above enum values to create a table of offsets for each rule's arg +// data, which indexes rule_arg_combined_table. The offsets require 9 bits of +// storage but only the lower 8 bits are stored here. The 9th bit is computed +// in get_rule_arg using the FIRST_RULE_WITH_OFFSET_ABOVE_255 constant. +STATIC const uint8_t rule_arg_offset_table[] = { +#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC - NULL, // RULE_const_object + 0, // RULE_const_object +#define DEF_RULE(rule, comp, kind, ...) +#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff, +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC +}; -// define rules without a compile function +// Define a constant that's used to determine the 9th bit of the values in rule_arg_offset_table +static const size_t FIRST_RULE_WITH_OFFSET_ABOVE_255 = +#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule : +#define DEF_RULE_NC(rule, kind, ...) +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC #define DEF_RULE(rule, comp, kind, ...) -#define DEF_RULE_NC(rule, kind, ...) &rule_##rule, +#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule : +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC +0; + +#if USE_RULE_NAME +// Define an array of rule names corresponding to each rule +STATIC const char *const rule_name_table[] = { +#define DEF_RULE(rule, comp, kind, ...) #rule, +#define DEF_RULE_NC(rule, kind, ...) +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC + "", // RULE_const_object +#define DEF_RULE(rule, comp, kind, ...) +#define DEF_RULE_NC(rule, kind, ...) #rule, #include "py/grammar.h" #undef DEF_RULE #undef DEF_RULE_NC }; +#endif typedef struct _rule_stack_t { size_t src_line : 8 * sizeof(size_t) - 8; // maximum bits storing source line number @@ -164,6 +241,14 @@ typedef struct _parser_t { #endif } parser_t; +STATIC const uint16_t *get_rule_arg(uint8_t r_id) { + size_t off = rule_arg_offset_table[r_id]; + if (r_id >= FIRST_RULE_WITH_OFFSET_ABOVE_255) { + off |= 0x100; + } + return &rule_arg_combined_table[off]; +} + STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) { // use a custom memory allocator to store parse nodes sequentially in large chunks @@ -205,7 +290,7 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) { return ret; } -STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) { +STATIC void push_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t arg_i) { if (parser->rule_stack_top >= parser->rule_stack_alloc) { rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC); parser->rule_stack = rs; @@ -213,21 +298,22 @@ STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, siz } rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++]; rs->src_line = src_line; - rs->rule_id = rule->rule_id; + rs->rule_id = rule_id; rs->arg_i = arg_i; } STATIC void push_rule_from_arg(parser_t *parser, size_t arg) { assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE); size_t rule_id = arg & RULE_ARG_ARG_MASK; - push_rule(parser, parser->lexer->tok_line, rules[rule_id], 0); + push_rule(parser, parser->lexer->tok_line, rule_id, 0); } -STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) { +STATIC uint8_t pop_rule(parser_t *parser, size_t *arg_i, size_t *src_line) { parser->rule_stack_top -= 1; - *rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id]; + uint8_t rule_id = parser->rule_stack[parser->rule_stack_top].rule_id; *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i; *src_line = parser->rule_stack[parser->rule_stack_top].src_line; + return rule_id; } bool mp_parse_node_is_const_false(mp_parse_node_t pn) { @@ -313,11 +399,11 @@ void mp_parse_node_print(mp_parse_node_t pn, size_t indent) { #endif } else { size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); -#ifdef USE_RULE_NAME - printf("%s(%u) (n=%u)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n); -#else + #if USE_RULE_NAME + printf("%s(%u) (n=%u)\n", rule_name_table[MP_PARSE_NODE_STRUCT_KIND(pns)], (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n); + #else printf("rule(%u) (n=%u)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), (uint)n); -#endif + #endif for (size_t i = 0; i < n; i++) { mp_parse_node_print(pns->nodes[i], indent + 2); } @@ -369,7 +455,19 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, return (mp_parse_node_t)pn; } -STATIC void push_result_token(parser_t *parser, const rule_t *rule) { +STATIC mp_parse_node_t mp_parse_node_new_small_int_checked(parser_t *parser, mp_obj_t o_val) { + (void)parser; + mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_val); + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D + // A parse node is only 32-bits and the small-int value must fit in 31-bits + if (((val ^ (val << 1)) & 0xffffffff80000000) != 0) { + return make_node_const_object(parser, 0, o_val); + } + #endif + return mp_parse_node_new_small_int(val); +} + +STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { mp_parse_node_t pn; mp_lexer_t *lex = parser->lexer; if (lex->tok_kind == MP_TOKEN_NAME) { @@ -377,10 +475,10 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) { #if MICROPY_COMP_CONST // if name is a standalone identifier, look it up in the table of dynamic constants mp_map_elem_t *elem; - if (rule->rule_id == RULE_atom + if (rule_id == RULE_atom && (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) { if (MP_OBJ_IS_SMALL_INT(elem->value)) { - pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value)); + pn = mp_parse_node_new_small_int_checked(parser, elem->value); } else { pn = make_node_const_object(parser, lex->tok_line, elem->value); } @@ -388,13 +486,13 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) { pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id); } #else - (void)rule; + (void)rule_id; pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id); #endif } else if (lex->tok_kind == MP_TOKEN_INTEGER) { mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex); if (MP_OBJ_IS_SMALL_INT(o)) { - pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(o)); + pn = mp_parse_node_new_small_int_checked(parser, o); } else { pn = make_node_const_object(parser, lex->tok_line, o); } @@ -417,7 +515,7 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) { pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst); } else { // not interned, make a node holding a pointer to the string/bytes object - mp_obj_t o = mp_obj_new_str_of_type( + mp_obj_t o = mp_obj_new_str_copy( lex->tok_kind == MP_TOKEN_STRING ? &mp_type_str : &mp_type_bytes, (const byte*)lex->vstr.buf, lex->vstr.len); pn = make_node_const_object(parser, lex->tok_line, o); @@ -442,12 +540,12 @@ STATIC const mp_rom_map_elem_t mp_constants_table[] = { STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table); #endif -STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args); +STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args); #if MICROPY_COMP_CONST_FOLDING -STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t *num_args) { - if (rule->rule_id == RULE_or_test - || rule->rule_id == RULE_and_test) { +STATIC bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) { + if (rule_id == RULE_or_test + || rule_id == RULE_and_test) { // folding for binary logical ops: or and size_t copy_to = *num_args; for (size_t i = copy_to; i > 0;) { @@ -457,7 +555,7 @@ STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t // always need to keep the last value break; } - if (rule->rule_id == RULE_or_test) { + if (rule_id == RULE_or_test) { if (mp_parse_node_is_const_true(pn)) { // break; @@ -484,7 +582,7 @@ STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t // we did a complete folding if there's only 1 arg left return *num_args == 1; - } else if (rule->rule_id == RULE_not_test_2) { + } else if (rule_id == RULE_not_test_2) { // folding for unary logical op: not mp_parse_node_t pn = peek_result(parser, 0); if (mp_parse_node_is_const_false(pn)) { @@ -502,23 +600,23 @@ STATIC bool fold_logical_constants(parser_t *parser, const rule_t *rule, size_t return false; } -STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args) { +STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4 // it does not do partial folding, eg 1 + 2 + x -> 3 + x mp_obj_t arg0; - if (rule->rule_id == RULE_expr - || rule->rule_id == RULE_xor_expr - || rule->rule_id == RULE_and_expr) { + if (rule_id == RULE_expr + || rule_id == RULE_xor_expr + || rule_id == RULE_and_expr) { // folding for binary ops: | ^ & mp_parse_node_t pn = peek_result(parser, num_args - 1); if (!mp_parse_node_get_int_maybe(pn, &arg0)) { return false; } mp_binary_op_t op; - if (rule->rule_id == RULE_expr) { + if (rule_id == RULE_expr) { op = MP_BINARY_OP_OR; - } else if (rule->rule_id == RULE_xor_expr) { + } else if (rule_id == RULE_xor_expr) { op = MP_BINARY_OP_XOR; } else { op = MP_BINARY_OP_AND; @@ -531,9 +629,9 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args } arg0 = mp_binary_op(op, arg0, arg1); } - } else if (rule->rule_id == RULE_shift_expr - || rule->rule_id == RULE_arith_expr - || rule->rule_id == RULE_term) { + } else if (rule_id == RULE_shift_expr + || rule_id == RULE_arith_expr + || rule_id == RULE_term) { // folding for binary ops: << >> + - * / % // mp_parse_node_t pn = peek_result(parser, num_args - 1); if (!mp_parse_node_get_int_maybe(pn, &arg0)) { @@ -577,7 +675,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args } arg0 = mp_binary_op(op, arg0, arg1); } - } else if (rule->rule_id == RULE_factor_2) { + } else if (rule_id == RULE_factor_2) { // folding for unary ops: + - ~ mp_parse_node_t pn = peek_result(parser, 0); if (!mp_parse_node_get_int_maybe(pn, &arg0)) { @@ -596,7 +694,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args arg0 = mp_unary_op(op, arg0); #if MICROPY_COMP_CONST - } else if (rule->rule_id == RULE_expr_stmt) { + } else if (rule_id == RULE_expr_stmt) { mp_parse_node_t pn1 = peek_result(parser, 0); if (!MP_PARSE_NODE_IS_NULL(pn1) && !(MP_PARSE_NODE_IS_STRUCT_KIND(pn1, RULE_expr_stmt_augassign) @@ -635,7 +733,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args if (qstr_str(id)[0] == '_') { pop_result(parser); // pop const(value) pop_result(parser); // pop id - push_result_rule(parser, 0, rules[RULE_pass_stmt], 0); // replace with "pass" + push_result_rule(parser, 0, RULE_pass_stmt, 0); // replace with "pass" return true; } @@ -651,7 +749,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args #endif #if MICROPY_COMP_MODULE_CONST - } else if (rule->rule_id == RULE_atom_expr_normal) { + } else if (rule_id == RULE_atom_expr_normal) { mp_parse_node_t pn0 = peek_result(parser, 1); mp_parse_node_t pn1 = peek_result(parser, 0); if (!(MP_PARSE_NODE_IS_ID(pn0) @@ -686,7 +784,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args pop_result(parser); } if (MP_OBJ_IS_SMALL_INT(arg0)) { - push_result_node(parser, mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(arg0))); + push_result_node(parser, mp_parse_node_new_small_int_checked(parser, arg0)); } else { // TODO reuse memory for parse node struct? push_result_node(parser, make_node_const_object(parser, 0, arg0)); @@ -696,9 +794,9 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args } #endif -STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t num_args) { +STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args) { // optimise away parenthesis around an expression if possible - if (rule->rule_id == RULE_atom_paren) { + if (rule_id == RULE_atom_paren) { // there should be just 1 arg for this rule mp_parse_node_t pn = peek_result(parser, 0); if (MP_PARSE_NODE_IS_NULL(pn)) { @@ -712,11 +810,11 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru } #if MICROPY_COMP_CONST_FOLDING - if (fold_logical_constants(parser, rule, &num_args)) { + if (fold_logical_constants(parser, rule_id, &num_args)) { // we folded this rule so return straight away return; } - if (fold_constants(parser, rule, num_args)) { + if (fold_constants(parser, rule_id, num_args)) { // we folded this rule so return straight away return; } @@ -724,7 +822,7 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args); pn->source_line = src_line; - pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8); + pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8); for (size_t i = num_args; i > 0; i--) { pn->nodes[i - 1] = pop_result(parser); } @@ -761,14 +859,11 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break; default: top_level_rule = RULE_file_input; } - push_rule(&parser, lex->tok_line, rules[top_level_rule], 0); + push_rule(&parser, lex->tok_line, top_level_rule, 0); // parse! - size_t n, i; // state for the current rule - size_t rule_src_line; // source line for the first token matched by the current rule bool backtrack = false; - const rule_t *rule = NULL; for (;;) { next_rule: @@ -776,19 +871,24 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { break; } - pop_rule(&parser, &rule, &i, &rule_src_line); - n = rule->act & RULE_ACT_ARG_MASK; + // Pop the next rule to process it + size_t i; // state for the current rule + size_t rule_src_line; // source line for the first token matched by the current rule + uint8_t rule_id = pop_rule(&parser, &i, &rule_src_line); + uint8_t rule_act = rule_act_table[rule_id]; + const uint16_t *rule_arg = get_rule_arg(rule_id); + size_t n = rule_act & RULE_ACT_ARG_MASK; - /* + #if 0 // debugging - printf("depth=%d ", parser.rule_stack_top); + printf("depth=" UINT_FMT " ", parser.rule_stack_top); for (int j = 0; j < parser.rule_stack_top; ++j) { printf(" "); } - printf("%s n=%d i=%d bt=%d\n", rule->rule_name, n, i, backtrack); - */ + printf("%s n=" UINT_FMT " i=" UINT_FMT " bt=%d\n", rule_name_table[rule_id], n, i, backtrack); + #endif - switch (rule->act & RULE_ACT_KIND_MASK) { + switch (rule_act & RULE_ACT_KIND_MASK) { case RULE_ACT_OR: if (i > 0 && !backtrack) { goto next_rule; @@ -796,19 +896,19 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { backtrack = false; } for (; i < n; ++i) { - uint16_t kind = rule->arg[i] & RULE_ARG_KIND_MASK; + uint16_t kind = rule_arg[i] & RULE_ARG_KIND_MASK; if (kind == RULE_ARG_TOK) { - if (lex->tok_kind == (rule->arg[i] & RULE_ARG_ARG_MASK)) { - push_result_token(&parser, rule); + if (lex->tok_kind == (rule_arg[i] & RULE_ARG_ARG_MASK)) { + push_result_token(&parser, rule_id); mp_lexer_to_next(lex); goto next_rule; } } else { assert(kind == RULE_ARG_RULE); if (i + 1 < n) { - push_rule(&parser, rule_src_line, rule, i + 1); // save this or-rule + push_rule(&parser, rule_src_line, rule_id, i + 1); // save this or-rule } - push_rule_from_arg(&parser, rule->arg[i]); // push child of or-rule + push_rule_from_arg(&parser, rule_arg[i]); // push child of or-rule goto next_rule; } } @@ -820,7 +920,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { // failed, backtrack if we can, else syntax error if (backtrack) { assert(i > 0); - if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) { + if ((rule_arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) { // an optional rule that failed, so continue with next arg push_result_node(&parser, MP_PARSE_NODE_NULL); backtrack = false; @@ -837,13 +937,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { // progress through the rule for (; i < n; ++i) { - if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { + if ((rule_arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { // need to match a token - mp_token_kind_t tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK; + mp_token_kind_t tok_kind = rule_arg[i] & RULE_ARG_ARG_MASK; if (lex->tok_kind == tok_kind) { // matched token if (tok_kind == MP_TOKEN_NAME) { - push_result_token(&parser, rule); + push_result_token(&parser, rule_id); } mp_lexer_to_next(lex); } else { @@ -858,8 +958,8 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { } } } else { - push_rule(&parser, rule_src_line, rule, i + 1); // save this and-rule - push_rule_from_arg(&parser, rule->arg[i]); // push child of and-rule + push_rule(&parser, rule_src_line, rule_id, i + 1); // save this and-rule + push_rule_from_arg(&parser, rule_arg[i]); // push child of and-rule goto next_rule; } } @@ -870,7 +970,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { #if !MICROPY_ENABLE_DOC_STRING // this code discards lonely statements, such as doc strings - if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) { + if (input_kind != MP_PARSE_SINGLE_INPUT && rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) { mp_parse_node_t p = peek_result(&parser, 1); if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p)) || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_const_object)) { @@ -879,7 +979,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { // Pushing the "pass" rule here will overwrite any RULE_const_object // entry that was on the result stack, allowing the GC to reclaim // the memory from the const object when needed. - push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0); + push_result_rule(&parser, rule_src_line, RULE_pass_stmt, 0); break; } } @@ -890,8 +990,8 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { size_t num_not_nil = 0; for (size_t x = n; x > 0;) { --x; - if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { - mp_token_kind_t tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK; + if ((rule_arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { + mp_token_kind_t tok_kind = rule_arg[x] & RULE_ARG_ARG_MASK; if (tok_kind == MP_TOKEN_NAME) { // only tokens which were names are pushed to stack i += 1; @@ -906,7 +1006,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { } } - if (num_not_nil == 1 && (rule->act & RULE_ACT_ALLOW_IDENT)) { + if (num_not_nil == 1 && (rule_act & RULE_ACT_ALLOW_IDENT)) { // this rule has only 1 argument and should not be emitted mp_parse_node_t pn = MP_PARSE_NODE_NULL; for (size_t x = 0; x < i; ++x) { @@ -919,19 +1019,19 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { } else { // this rule must be emitted - if (rule->act & RULE_ACT_ADD_BLANK) { + if (rule_act & RULE_ACT_ADD_BLANK) { // and add an extra blank node at the end (used by the compiler to store data) push_result_node(&parser, MP_PARSE_NODE_NULL); i += 1; } - push_result_rule(&parser, rule_src_line, rule, i); + push_result_rule(&parser, rule_src_line, rule_id, i); } break; } default: { - assert((rule->act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST); + assert((rule_act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST); // n=2 is: item item* // n=1 is: item (sep item)* @@ -969,13 +1069,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { } } else { for (;;) { - size_t arg = rule->arg[i & 1 & n]; + size_t arg = rule_arg[i & 1 & n]; if ((arg & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { if (lex->tok_kind == (arg & RULE_ARG_ARG_MASK)) { if (i & 1 & n) { // separators which are tokens are not pushed to result stack } else { - push_result_token(&parser, rule); + push_result_token(&parser, rule_id); } mp_lexer_to_next(lex); // got element of list, so continue parsing list @@ -988,7 +1088,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { } } else { assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE); - push_rule(&parser, rule_src_line, rule, i + 1); // save this list-rule + push_rule(&parser, rule_src_line, rule_id, i + 1); // save this list-rule push_rule_from_arg(&parser, arg); // push child of list-rule goto next_rule; } @@ -998,7 +1098,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { // compute number of elements in list, result in i i -= 1; - if ((n & 1) && (rule->arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { + if ((n & 1) && (rule_arg[1] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { // don't count separators when they are tokens i = (i + 1) / 2; } @@ -1007,12 +1107,12 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { // list matched single item if (had_trailing_sep) { // if there was a trailing separator, make a list of a single item - push_result_rule(&parser, rule_src_line, rule, i); + push_result_rule(&parser, rule_src_line, rule_id, i); } else { // just leave single item on stack (ie don't wrap in a list) } } else { - push_result_rule(&parser, rule_src_line, rule, i); + push_result_rule(&parser, rule_src_line, rule_id, i); } break; } diff --git a/MicroPython_BUILD/components/micropython/py/parsenum.c b/MicroPython_BUILD/components/micropython/py/parsenum.c index b62029f7..124489c6 100644 --- a/MicroPython_BUILD/components/micropython/py/parsenum.c +++ b/MicroPython_BUILD/components/micropython/py/parsenum.c @@ -170,6 +170,19 @@ typedef enum { mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex) { #if MICROPY_PY_BUILTINS_FLOAT + +// DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing +// SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define DEC_VAL_MAX 1e20F +#define SMALL_NORMAL_VAL (1e-37F) +#define SMALL_NORMAL_EXP (-37) +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define DEC_VAL_MAX 1e200 +#define SMALL_NORMAL_VAL (1e-307) +#define SMALL_NORMAL_EXP (-307) +#endif + const char *top = str + len; mp_float_t dec_val = 0; bool dec_neg = false; @@ -214,8 +227,8 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool // string should be a decimal number parse_dec_in_t in = PARSE_DEC_IN_INTG; bool exp_neg = false; - mp_float_t frac_mult = 0.1; mp_int_t exp_val = 0; + mp_int_t exp_extra = 0; while (str < top) { mp_uint_t dig = *str++; if ('0' <= dig && dig <= '9') { @@ -223,11 +236,18 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool if (in == PARSE_DEC_IN_EXP) { exp_val = 10 * exp_val + dig; } else { - if (in == PARSE_DEC_IN_FRAC) { - dec_val += dig * frac_mult; - frac_mult *= MICROPY_FLOAT_CONST(0.1); - } else { + if (dec_val < DEC_VAL_MAX) { + // dec_val won't overflow so keep accumulating dec_val = 10 * dec_val + dig; + if (in == PARSE_DEC_IN_FRAC) { + --exp_extra; + } + } else { + // dec_val might overflow and we anyway can't represent more digits + // of precision, so ignore the digit and just adjust the exponent + if (in == PARSE_DEC_IN_INTG) { + ++exp_extra; + } } } } else if (in == PARSE_DEC_IN_INTG && dig == '.') { @@ -260,7 +280,12 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool exp_val = -exp_val; } - // apply the exponent + // apply the exponent, making sure it's not a subnormal value + exp_val += exp_extra; + if (exp_val < SMALL_NORMAL_EXP) { + exp_val -= SMALL_NORMAL_EXP; + dec_val *= SMALL_NORMAL_VAL; + } dec_val *= MICROPY_FLOAT_C_FUN(pow)(10, exp_val); } diff --git a/MicroPython_BUILD/components/micropython/py/persistentcode.c b/MicroPython_BUILD/components/micropython/py/persistentcode.c index e0bb8f1d..7113b0dc 100644 --- a/MicroPython_BUILD/components/micropython/py/persistentcode.c +++ b/MicroPython_BUILD/components/micropython/py/persistentcode.c @@ -200,7 +200,11 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) { // create raw_code and return it mp_raw_code_t *rc = mp_emit_glue_new_raw_code(); - mp_emit_glue_assign_bytecode(rc, bytecode, bc_len, const_table, + mp_emit_glue_assign_bytecode(rc, bytecode, + #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS + bc_len, + #endif + const_table, #if MICROPY_PERSISTENT_CODE_SAVE n_obj, n_raw_code, #endif diff --git a/MicroPython_BUILD/components/micropython/py/py.mk b/MicroPython_BUILD/components/micropython/py/py.mk index e69618b1..3c4baeec 100644 --- a/MicroPython_BUILD/components/micropython/py/py.mk +++ b/MicroPython_BUILD/components/micropython/py/py.mk @@ -62,6 +62,7 @@ endif # py object files PY_O_BASENAME = \ mpstate.o \ + nlr.o \ nlrx86.o \ nlrx64.o \ nlrthumb.o \ @@ -69,6 +70,7 @@ PY_O_BASENAME = \ nlrsetjmp.o \ malloc.o \ gc.o \ + pystack.o \ qstr.o \ vstr.o \ mpprint.o \ @@ -115,6 +117,7 @@ PY_O_BASENAME = \ objcell.o \ objclosure.o \ objcomplex.o \ + objdeque.o \ objdict.o \ objenumerate.o \ objexcept.o \ @@ -191,9 +194,7 @@ PY_O_BASENAME = \ ../extmod/vfs.o \ ../extmod/vfs_reader.o \ ../extmod/utime_mphal.o \ - ../extmod/uos_dupterm.o \ ../lib/embed/abort_.o \ - ../lib/utils/printf.o \ ../extmod/vfs_native.o \ ../extmod/vfs_native_file.o \ ../extmod/vfs_native_misc.o diff --git a/MicroPython_BUILD/components/micropython/py/pystack.c b/MicroPython_BUILD/components/micropython/py/pystack.c new file mode 100644 index 00000000..552e59d5 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/pystack.c @@ -0,0 +1,57 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Damien P. George + * + * 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 + +#include "py/runtime.h" + +#if MICROPY_ENABLE_PYSTACK + +void mp_pystack_init(void *start, void *end) { + MP_STATE_THREAD(pystack_start) = start; + MP_STATE_THREAD(pystack_end) = end; + MP_STATE_THREAD(pystack_cur) = start; +} + +void *mp_pystack_alloc(size_t n_bytes) { + n_bytes = (n_bytes + (MICROPY_PYSTACK_ALIGN - 1)) & ~(MICROPY_PYSTACK_ALIGN - 1); + #if MP_PYSTACK_DEBUG + n_bytes += MICROPY_PYSTACK_ALIGN; + #endif + if (MP_STATE_THREAD(pystack_cur) + n_bytes > MP_STATE_THREAD(pystack_end)) { + // out of memory in the pystack + nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError, + MP_OBJ_NEW_QSTR(MP_QSTR_pystack_space_exhausted))); + } + void *ptr = MP_STATE_THREAD(pystack_cur); + MP_STATE_THREAD(pystack_cur) += n_bytes; + #if MP_PYSTACK_DEBUG + *(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN) = n_bytes; + #endif + return ptr; +} + +#endif diff --git a/MicroPython_BUILD/components/micropython/py/pystack.h b/MicroPython_BUILD/components/micropython/py/pystack.h new file mode 100644 index 00000000..82ac3743 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/py/pystack.h @@ -0,0 +1,123 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Damien P. George + * + * 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 MICROPY_INCLUDED_PY_PYSTACK_H +#define MICROPY_INCLUDED_PY_PYSTACK_H + +#include "py/mpstate.h" + +// Enable this debugging option to check that the amount of memory freed is +// consistent with amounts that were previously allocated. +#define MP_PYSTACK_DEBUG (0) + +#if MICROPY_ENABLE_PYSTACK + +void mp_pystack_init(void *start, void *end); +void *mp_pystack_alloc(size_t n_bytes); + +// This function can free multiple continuous blocks at once: just pass the +// pointer to the block that was allocated first and it and all subsequently +// allocated blocks will be freed. +static inline void mp_pystack_free(void *ptr) { + assert((uint8_t*)ptr >= MP_STATE_THREAD(pystack_start)); + assert((uint8_t*)ptr <= MP_STATE_THREAD(pystack_cur)); + #if MP_PYSTACK_DEBUG + size_t n_bytes_to_free = MP_STATE_THREAD(pystack_cur) - (uint8_t*)ptr; + size_t n_bytes = *(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN); + while (n_bytes < n_bytes_to_free) { + n_bytes += *(size_t*)(MP_STATE_THREAD(pystack_cur) - n_bytes - MICROPY_PYSTACK_ALIGN); + } + if (n_bytes != n_bytes_to_free) { + mp_printf(&mp_plat_print, "mp_pystack_free() failed: %u != %u\n", (uint)n_bytes_to_free, + (uint)*(size_t*)(MP_STATE_THREAD(pystack_cur) - MICROPY_PYSTACK_ALIGN)); + assert(0); + } + #endif + MP_STATE_THREAD(pystack_cur) = (uint8_t*)ptr; +} + +static inline void mp_pystack_realloc(void *ptr, size_t n_bytes) { + mp_pystack_free(ptr); + mp_pystack_alloc(n_bytes); +} + +static inline size_t mp_pystack_usage(void) { + return MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start); +} + +static inline size_t mp_pystack_limit(void) { + return MP_STATE_THREAD(pystack_end) - MP_STATE_THREAD(pystack_start); +} + +#endif + +#if !MICROPY_ENABLE_PYSTACK + +#define mp_local_alloc(n_bytes) alloca(n_bytes) + +static inline void mp_local_free(void *ptr) { + (void)ptr; +} + +static inline void *mp_nonlocal_alloc(size_t n_bytes) { + return m_new(uint8_t, n_bytes); +} + +static inline void *mp_nonlocal_realloc(void *ptr, size_t old_n_bytes, size_t new_n_bytes) { + return m_renew(uint8_t, ptr, old_n_bytes, new_n_bytes); +} + +static inline void mp_nonlocal_free(void *ptr, size_t n_bytes) { + m_del(uint8_t, ptr, n_bytes); +} + +#else + +static inline void *mp_local_alloc(size_t n_bytes) { + return mp_pystack_alloc(n_bytes); +} + +static inline void mp_local_free(void *ptr) { + mp_pystack_free(ptr); +} + +static inline void *mp_nonlocal_alloc(size_t n_bytes) { + return mp_pystack_alloc(n_bytes); +} + +static inline void *mp_nonlocal_realloc(void *ptr, size_t old_n_bytes, size_t new_n_bytes) { + (void)old_n_bytes; + mp_pystack_realloc(ptr, new_n_bytes); + return ptr; +} + +static inline void mp_nonlocal_free(void *ptr, size_t n_bytes) { + (void)n_bytes; + mp_pystack_free(ptr); +} + +#endif + +#endif // MICROPY_INCLUDED_PY_PYSTACK_H diff --git a/MicroPython_BUILD/components/micropython/py/qstr.c b/MicroPython_BUILD/components/micropython/py/qstr.c index 95c9b683..08c3e250 100644 --- a/MicroPython_BUILD/components/micropython/py/qstr.c +++ b/MicroPython_BUILD/components/micropython/py/qstr.c @@ -127,14 +127,12 @@ void qstr_init(void) { STATIC const byte *find_qstr(qstr q) { // search pool for this qstr - for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) { - if (q >= pool->total_prev_len) { - return pool->qstrs[q - pool->total_prev_len]; - } + // total_prev_len==0 in the final pool, so the loop will always terminate + qstr_pool_t *pool = MP_STATE_VM(last_pool); + while (q < pool->total_prev_len) { + pool = pool->prev; } - - // not found - return 0; + return pool->qstrs[q - pool->total_prev_len]; } // qstr_mutex must be taken while in this function @@ -243,29 +241,6 @@ qstr qstr_from_strn(const char *str, size_t len) { return q; } -byte *qstr_build_start(size_t len, byte **q_ptr) { - assert(len < (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN))); - *q_ptr = m_new(byte, MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1); - Q_SET_LENGTH(*q_ptr, len); - return Q_GET_DATA(*q_ptr); -} - -qstr qstr_build_end(byte *q_ptr) { - QSTR_ENTER(); - qstr q = qstr_find_strn((const char*)Q_GET_DATA(q_ptr), Q_GET_LENGTH(q_ptr)); - if (q == 0) { - size_t len = Q_GET_LENGTH(q_ptr); - mp_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len); - Q_SET_HASH(q_ptr, hash); - q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\0'; - q = qstr_add(q_ptr); - } else { - m_del(byte, q_ptr, Q_GET_ALLOC(q_ptr)); - } - QSTR_EXIT(); - return q; -} - mp_uint_t qstr_hash(qstr q) { return Q_GET_HASH(find_qstr(q)); } diff --git a/MicroPython_BUILD/components/micropython/py/qstr.h b/MicroPython_BUILD/components/micropython/py/qstr.h index e2bdcc35..f4375ee0 100644 --- a/MicroPython_BUILD/components/micropython/py/qstr.h +++ b/MicroPython_BUILD/components/micropython/py/qstr.h @@ -56,6 +56,7 @@ typedef struct _qstr_pool_t { } qstr_pool_t; #define QSTR_FROM_STR_STATIC(s) (qstr_from_strn((s), strlen(s))) +#define QSTR_TOTAL() (MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len) void qstr_init(void); @@ -65,9 +66,6 @@ qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTR_NULL if qstr qstr_from_str(const char *str); qstr qstr_from_strn(const char *str, size_t len); -byte *qstr_build_start(size_t len, byte **q_ptr); -qstr qstr_build_end(byte *q_ptr); - mp_uint_t qstr_hash(qstr q); const char *qstr_str(qstr q); size_t qstr_len(qstr q); diff --git a/MicroPython_BUILD/components/micropython/py/qstrdefs.h b/MicroPython_BUILD/components/micropython/py/qstrdefs.h index 4ded5be0..a6090581 100644 --- a/MicroPython_BUILD/components/micropython/py/qstrdefs.h +++ b/MicroPython_BUILD/components/micropython/py/qstrdefs.h @@ -40,6 +40,7 @@ Q(/) Q(%#o) Q(%#x) Q({:#b}) +Q( ) Q(\n) Q(maximum recursion depth exceeded) Q() @@ -51,3 +52,7 @@ Q() Q() Q() Q(utf-8) + +#if MICROPY_ENABLE_PYSTACK +Q(pystack exhausted) +#endif diff --git a/MicroPython_BUILD/components/micropython/py/repl.c b/MicroPython_BUILD/components/micropython/py/repl.c index 7e8922e1..5dce8bbb 100644 --- a/MicroPython_BUILD/components/micropython/py/repl.c +++ b/MicroPython_BUILD/components/micropython/py/repl.c @@ -27,6 +27,7 @@ #include #include "py/obj.h" #include "py/runtime.h" +#include "py/builtin.h" #include "py/repl.h" #if MICROPY_HELPER_REPL @@ -136,8 +137,11 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print } } - // begin search in locals dict - mp_obj_dict_t *dict = mp_locals_get(); + size_t nqstr = QSTR_TOTAL(); + + // begin search in outer global dict which is accessed from __main__ + mp_obj_t obj = MP_OBJ_FROM_PTR(&mp_module___main__); + mp_obj_t dest[2]; for (;;) { // get next word in string to complete @@ -148,43 +152,20 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print size_t s_len = str - s_start; if (str < top) { - // a complete word, lookup in current dict - - mp_obj_t obj = MP_OBJ_NULL; - for (size_t i = 0; i < dict->map.alloc; i++) { - if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { - size_t d_len; - const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len); - if (s_len == d_len && strncmp(s_start, d_str, d_len) == 0) { - obj = dict->map.table[i].value; - break; - } - } + // a complete word, lookup in current object + qstr q = qstr_find_strn(s_start, s_len); + if (q == MP_QSTR_NULL) { + // lookup will fail + return 0; } + mp_load_method_protected(obj, q, dest, true); + obj = dest[0]; // attribute, method, or MP_OBJ_NULL if nothing found if (obj == MP_OBJ_NULL) { // lookup failed return 0; } - // found an object of this name; try to get its dict - if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) { - dict = mp_obj_module_get_globals(obj); - } else { - mp_obj_type_t *type; - if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) { - type = MP_OBJ_TO_PTR(obj); - } else { - type = mp_obj_get_type(obj); - } - if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) { - dict = type->locals_dict; - } else { - // obj has no dict - return 0; - } - } - // skip '.' to move to next word ++str; @@ -192,14 +173,15 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print // end of string, do completion on this partial name // look for matches - int n_found = 0; const char *match_str = NULL; size_t match_len = 0; - for (size_t i = 0; i < dict->map.alloc; i++) { - if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { - size_t d_len; - const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len); - if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { + qstr q_first = 0, q_last = 0; + for (qstr q = MP_QSTR_ + 1; q < nqstr; ++q) { + size_t d_len; + const char *d_str = (const char*)qstr_data(q, &d_len); + if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { + mp_load_method_protected(obj, q, dest, true); + if (dest[0] != MP_OBJ_NULL) { if (match_str == NULL) { match_str = d_str; match_len = d_len; @@ -213,13 +195,16 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print } } } - ++n_found; + if (q_first == 0) { + q_first = q; + } + q_last = q; } } } // nothing found - if (n_found == 0) { + if (q_first == 0) { // If there're no better alternatives, and if it's first word // in the line, try to complete "import". if (s_start == org_str) { @@ -234,7 +219,7 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print } // 1 match found, or multiple matches with a common prefix - if (n_found == 1 || match_len > s_len) { + if (q_first == q_last || match_len > s_len) { *compl_str = match_str + s_len; return match_len - s_len; } @@ -245,11 +230,12 @@ size_t mp_repl_autocomplete(const char *str, size_t len, const mp_print_t *print #define MAX_LINE_LEN (4 * WORD_SLOT_LEN) int line_len = MAX_LINE_LEN; // force a newline for first word - for (size_t i = 0; i < dict->map.alloc; i++) { - if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { - size_t d_len; - const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len); - if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { + for (qstr q = q_first; q <= q_last; ++q) { + size_t d_len; + const char *d_str = (const char*)qstr_data(q, &d_len); + if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { + mp_load_method_protected(obj, q, dest, true); + if (dest[0] != MP_OBJ_NULL) { int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len; if (gap < 2) { gap += WORD_SLOT_LEN; diff --git a/MicroPython_BUILD/components/micropython/py/ringbuf.h b/MicroPython_BUILD/components/micropython/py/ringbuf.h index 399849b9..b9b40aa4 100644 --- a/MicroPython_BUILD/components/micropython/py/ringbuf.h +++ b/MicroPython_BUILD/components/micropython/py/ringbuf.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/MicroPython_BUILD/components/micropython/py/runtime.c b/MicroPython_BUILD/components/micropython/py/runtime.c index 0599f808..7db041b0 100644 --- a/MicroPython_BUILD/components/micropython/py/runtime.c +++ b/MicroPython_BUILD/components/micropython/py/runtime.c @@ -70,7 +70,7 @@ void mp_init(void) { #endif #if MICROPY_KBD_EXCEPTION - // initialise the exception object for raising KeyboardInterrupt + // initialize the exception object for raising KeyboardInterrupt MP_STATE_VM(mp_kbd_exception).base.type = &mp_type_KeyboardInterrupt; MP_STATE_VM(mp_kbd_exception).traceback_alloc = 0; MP_STATE_VM(mp_kbd_exception).traceback_len = 0; @@ -83,8 +83,10 @@ void mp_init(void) { MICROPY_PORT_INIT_FUNC; #endif + #if MICROPY_ENABLE_COMPILER // optimization disabled by default MP_STATE_VM(mp_optimise_value) = 0; + #endif // init global module dict mp_obj_dict_init(&MP_STATE_VM(mp_loaded_modules_dict), 3); @@ -122,7 +124,6 @@ void mp_init(void) { #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); - MP_STATE_VM(thread_lock) = 0; #endif MP_THREAD_GIL_ENTER(); @@ -215,7 +216,7 @@ void mp_delete_global(qstr qst) { } mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { - DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg); + DEBUG_OP_printf("unary " UINT_FMT " %q %p\n", op, mp_unary_op_method_name[op], arg); if (op == MP_UNARY_OP_NOT) { // "not x" is the negative of whether "x" is true per Python semantics @@ -276,7 +277,7 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) { } mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { - DEBUG_OP_printf("binary " UINT_FMT " %p %p\n", op, lhs, rhs); + DEBUG_OP_printf("binary " UINT_FMT " %q %p %p\n", op, mp_binary_op_method_name[op], lhs, rhs); // TODO correctly distinguish inplace operators for mutable objects // lookup logic that CPython uses for +=: @@ -414,7 +415,6 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { // use standard precision return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val); } - break; } case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: @@ -489,10 +489,10 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { return MP_OBJ_FROM_PTR(tuple); } - case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); break; - case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); break; - case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); break; - case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); break; + case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); + case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); + case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); + case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); default: goto unsupported_op; @@ -524,38 +524,12 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } } - /* deal with `in` - * - * NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch - * needs to go below with swapped arguments - */ + // Convert MP_BINARY_OP_IN to MP_BINARY_OP_CONTAINS with swapped args. if (op == MP_BINARY_OP_IN) { - mp_obj_type_t *type = mp_obj_get_type(rhs); - if (type->binary_op != NULL) { - mp_obj_t res = type->binary_op(op, rhs, lhs); - if (res != MP_OBJ_NULL) { - return res; - } - } - if (type->getiter != NULL) { - /* second attempt, walk the iterator */ - mp_obj_iter_buf_t iter_buf; - mp_obj_t iter = mp_getiter(rhs, &iter_buf); - mp_obj_t next; - while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { - if (mp_obj_equal(next, lhs)) { - return mp_const_true; - } - } - return mp_const_false; - } - - if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - mp_raise_TypeError("object not iterable"); - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, - "'%s' object is not iterable", mp_obj_get_type_str(rhs))); - } + op = MP_BINARY_OP_CONTAINS; + mp_obj_t temp = lhs; + lhs = rhs; + rhs = temp; } // generic binary_op supplied by type @@ -584,6 +558,20 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } #endif + if (op == MP_BINARY_OP_CONTAINS) { + // If type didn't support containment then explicitly walk the iterator. + // mp_getiter will raise the appropriate exception if lhs is not iterable. + mp_obj_iter_buf_t iter_buf; + mp_obj_t iter = mp_getiter(lhs, &iter_buf); + mp_obj_t next; + while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { + if (mp_obj_equal(next, rhs)) { + return mp_const_true; + } + } + return mp_const_false; + } + unsupported_op: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_TypeError("unsupported type for operator"); @@ -682,7 +670,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ // allocate memory for the new array of args args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len); - args2 = m_new(mp_obj_t, args2_alloc); + args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t)); // copy the self if (self != MP_OBJ_NULL) { @@ -703,7 +691,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ // allocate memory for the new array of args args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len); - args2 = m_new(mp_obj_t, args2_alloc); + args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t)); // copy the self if (self != MP_OBJ_NULL) { @@ -719,7 +707,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ // allocate memory for the new array of args args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len) + 3; - args2 = m_new(mp_obj_t, args2_alloc); + args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t)); // copy the self if (self != MP_OBJ_NULL) { @@ -736,7 +724,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ mp_obj_t item; while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (args2_len >= args2_alloc) { - args2 = m_renew(mp_obj_t, args2, args2_alloc, args2_alloc * 2); + args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), args2_alloc * 2 * sizeof(mp_obj_t)); args2_alloc *= 2; } args2[args2_len++] = item; @@ -762,8 +750,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ if (MP_MAP_SLOT_IS_FILLED(map, i)) { // the key must be a qstr, so intern it if it's a string mp_obj_t key = map->table[i].key; - if (MP_OBJ_IS_TYPE(key, &mp_type_str)) { - key = mp_obj_str_intern(key); + if (!MP_OBJ_IS_QSTR(key)) { + key = mp_obj_str_intern_checked(key); } args2[args2_len++] = key; args2[args2_len++] = map->table[i].value; @@ -787,13 +775,13 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ if (new_alloc < 4) { new_alloc = 4; } - args2 = m_renew(mp_obj_t, args2, args2_alloc, new_alloc); + args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), new_alloc * sizeof(mp_obj_t)); args2_alloc = new_alloc; } // the key must be a qstr, so intern it if it's a string - if (MP_OBJ_IS_TYPE(key, &mp_type_str)) { - key = mp_obj_str_intern(key); + if (!MP_OBJ_IS_QSTR(key)) { + key = mp_obj_str_intern_checked(key); } // get the value corresponding to the key @@ -819,7 +807,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args); mp_obj_t res = mp_call_function_n_kw(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); - m_del(mp_obj_t, out_args.args, out_args.n_alloc); + mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t)); return res; } @@ -1098,6 +1086,22 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { } } +// Acts like mp_load_method_maybe but catches AttributeError, and all other exceptions if requested +void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_load_method_maybe(obj, attr, dest); + nlr_pop(); + } else { + if (!catch_all_exc + && !mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), + MP_OBJ_FROM_PTR(&mp_type_AttributeError))) { + // Re-raise the exception + nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); + } + } +} + void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value); mp_obj_type_t *type = mp_obj_get_type(base); @@ -1229,13 +1233,12 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th if (type->iternext != NULL && send_value == mp_const_none) { mp_obj_t ret = type->iternext(self_in); + *ret_val = ret; if (ret != MP_OBJ_STOP_ITERATION) { - *ret_val = ret; return MP_VM_RETURN_YIELD; } else { // Emulate raise StopIteration() // Special case, handled in vm.c - *ret_val = MP_OBJ_NULL; return MP_VM_RETURN_NORMAL; } } @@ -1297,7 +1300,7 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th // will be propagated up. This behavior is approved by test_pep380.py // test_delegation_of_close_to_non_generator(), // test_delegating_throw_to_non_generator() - *ret_val = throw_value; + *ret_val = mp_make_raise_obj(throw_value); return MP_VM_RETURN_EXCEPTION; } } @@ -1351,6 +1354,8 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name) { return dest[0]; } + #if MICROPY_ENABLE_EXTERNAL_IMPORT + // See if it's a package, then can try FS import if (!mp_obj_is_package(module)) { goto import_error; @@ -1361,11 +1366,12 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name) { const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len); const uint dot_name_len = pkg_name_len + 1 + qstr_len(name); - char *dot_name = alloca(dot_name_len); + char *dot_name = mp_local_alloc(dot_name_len); memcpy(dot_name, pkg_name, pkg_name_len); dot_name[pkg_name_len] = '.'; memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name)); qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len); + mp_local_free(dot_name); mp_obj_t args[5]; args[0] = MP_OBJ_NEW_QSTR(dot_name_q); @@ -1376,6 +1382,13 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name) { // TODO lookup __import__ and call that instead of going straight to builtin implementation return mp_builtin___import__(5, args); + + #else + + // Package import not supported with external imports disabled + goto import_error; + + #endif } void mp_import_all(mp_obj_t module) { @@ -1469,3 +1482,10 @@ NORETURN void mp_raise_OSError(int errno_) { NORETURN void mp_raise_NotImplementedError(const char *msg) { mp_raise_msg(&mp_type_NotImplementedError, msg); } + +#if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK +NORETURN void mp_raise_recursion_depth(void) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError, + MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded))); +} +#endif diff --git a/MicroPython_BUILD/components/micropython/py/runtime.h b/MicroPython_BUILD/components/micropython/py/runtime.h index b27c237a..42a6f93a 100644 --- a/MicroPython_BUILD/components/micropython/py/runtime.h +++ b/MicroPython_BUILD/components/micropython/py/runtime.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +28,7 @@ #define MICROPY_INCLUDED_PY_RUNTIME_H #include "py/mpstate.h" +#include "py/pystack.h" typedef enum { MP_VM_RETURN_NORMAL, @@ -59,7 +61,7 @@ typedef struct _mp_arg_t { #if MICROPY_ENABLE_SCHEDULER //-------------------------- -#define MP_SCHED_CTYPE_MAX_ITEMS 4 +#define MP_SCHED_CTYPE_MAX_ITEMS 6 #define MP_SCHED_CTYPE_NONE 0 #define MP_SCHED_CTYPE_SINGLE 1 @@ -148,8 +150,9 @@ mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args); mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args); // Call function and catch/dump exception - for Python callbacks from C code -void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg); -void mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2); +// (return MP_OBJ_NULL in case of exception). +mp_obj_t mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg); +mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2); typedef struct _mp_call_args_t { mp_obj_t fun; @@ -172,6 +175,7 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr); void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest); void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest); void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest); +void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc); void mp_load_super_method(qstr attr, mp_obj_t *dest); void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val); @@ -192,7 +196,7 @@ NORETURN void mp_raise_ValueError(const char *msg); NORETURN void mp_raise_TypeError(const char *msg); NORETURN void mp_raise_NotImplementedError(const char *msg); NORETURN void mp_raise_OSError(int errno_); -NORETURN void mp_exc_recursion_depth(void); +NORETURN void mp_raise_recursion_depth(void); #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG #undef mp_check_self diff --git a/MicroPython_BUILD/components/micropython/py/runtime0.h b/MicroPython_BUILD/components/micropython/py/runtime0.h index a72b7feb..960532d1 100644 --- a/MicroPython_BUILD/components/micropython/py/runtime0.h +++ b/MicroPython_BUILD/components/micropython/py/runtime0.h @@ -131,6 +131,10 @@ typedef enum { #endif , + // The runtime will convert MP_BINARY_OP_IN to this operator with swapped args. + // A type should implement this containment operator instead of MP_BINARY_OP_IN. + MP_BINARY_OP_CONTAINS, + MP_BINARY_OP_NUM_RUNTIME, // These 2 are not supported by the runtime and must be synthesised by the emitter diff --git a/MicroPython_BUILD/components/micropython/py/runtime_utils.c b/MicroPython_BUILD/components/micropython/py/runtime_utils.c index a5c5403b..b92c6bd7 100644 --- a/MicroPython_BUILD/components/micropython/py/runtime_utils.c +++ b/MicroPython_BUILD/components/micropython/py/runtime_utils.c @@ -27,22 +27,26 @@ #include "py/runtime.h" -void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) { +mp_obj_t mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_call_function_1(fun, arg); + mp_obj_t ret = mp_call_function_1(fun, arg); nlr_pop(); + return ret; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + return MP_OBJ_NULL; } } -void mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) { +mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_call_function_2(fun, arg1, arg2); + mp_obj_t ret = mp_call_function_2(fun, arg1, arg2); nlr_pop(); + return ret; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + return MP_OBJ_NULL; } } diff --git a/MicroPython_BUILD/components/micropython/py/scheduler.c b/MicroPython_BUILD/components/micropython/py/scheduler.c index d4cbd3bd..bb4906fb 100644 --- a/MicroPython_BUILD/components/micropython/py/scheduler.c +++ b/MicroPython_BUILD/components/micropython/py/scheduler.c @@ -29,9 +29,18 @@ #include #include "py/runtime.h" +#include "py/objstr.h" #if MICROPY_ENABLE_SCHEDULER +#define FREE_CBOBJECT_AFTER 0 +#define MAX_CB_OBJECTS 64 + +#if FREE_CBOBJECT_AFTER +static mp_obj_t cb_objects[MAX_CB_OBJECTS]; +#endif + + // A variant of this is inlined in the VM at the pending exception check void mp_handle_pending(void) { if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { @@ -65,6 +74,7 @@ void free_carg(mp_sched_carg_t *carg) } } free(carg->entry[i]); + carg->entry[i] = NULL; } } free(carg); @@ -74,7 +84,17 @@ void free_carg(mp_sched_carg_t *carg) //--------------------------------------------------------------------------------------------------------------------------- mp_sched_carg_t *make_carg_entry(mp_sched_carg_t *carg, int idx, uint8_t type, int val, const uint8_t *sval, const char *key) { - carg->entry[idx] = calloc(sizeof(mp_sched_carg_entry_t), 1); + if (idx >= MP_SCHED_CTYPE_MAX_ITEMS) { + free_carg(carg); + return NULL; + } + + if (carg->entry[idx]) { + free_carg(carg); + return NULL; + } + + carg->entry[idx] = calloc(sizeof(mp_sched_carg_entry_t), 1); if (carg->entry[idx] == NULL) { free_carg(carg); return NULL; @@ -129,41 +149,56 @@ mp_sched_carg_t *make_cargs(int type) return carg; } -//------------------------------------------------------------------ -static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level) +//---------------------------------------------------------------------------------- +static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level, int *n_cbitems) { mp_obj_t arg = mp_const_none; - if (carg->type == MP_SCHED_CTYPE_DICT) { + + if (carg->type == MP_SCHED_CTYPE_DICT) { //dictionary mp_obj_dict_t *dct = mp_obj_new_dict(0); for (int i = 0; i < carg->n; i++) { + mp_obj_t val; mp_sched_carg_entry_t *entry = (mp_sched_carg_entry_t *)carg->entry[i]; if (entry->type == MP_SCHED_ENTRY_TYPE_INT) { - mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false), - mp_obj_new_int(entry->ival)); + mp_obj_dict_store(dct, mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->key, strlen(entry->key)), mp_obj_new_int(entry->ival)); } else if (entry->type == MP_SCHED_ENTRY_TYPE_BOOL) { - mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false), - mp_obj_new_bool(entry->ival)); + mp_obj_dict_store(dct, mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->key, strlen(entry->key)), mp_obj_new_bool(entry->ival)); } else if (entry->type == MP_SCHED_ENTRY_TYPE_FLOAT) { - mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false), - mp_obj_new_float(entry->fval)); + val = mp_obj_new_float(entry->fval); + mp_obj_dict_store(dct, mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->key, strlen(entry->key)), val); + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = val; + #endif } else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) { - mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false), - mp_obj_new_str((const char*)entry->sval, entry->ival, false)); + val = mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->sval, entry->ival); + mp_obj_dict_store(dct, mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->key, strlen(entry->key)), val); + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = val; + #endif } else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) { - mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false), - mp_obj_new_bytes((const byte*)entry->sval, entry->ival)); + val = mp_obj_new_bytes((const byte*)entry->sval, entry->ival); + mp_obj_dict_store(dct, mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->key, strlen(entry->key)), val); + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = val; + #endif } else if ((level == 0) && (entry->type == MP_SCHED_ENTRY_TYPE_CARG) && (strlen(entry->key) > 0) && (entry->carg)) { - mp_obj_t darg = make_arg_from_carg(entry->carg, 1); - mp_obj_dict_store(dct, mp_obj_new_str(entry->key, strlen(entry->key), false), darg); + mp_obj_t darg = make_arg_from_carg(entry->carg, 1, n_cbitems); + mp_obj_dict_store(dct, mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->key, strlen(entry->key)), darg); + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = darg; + #endif } } arg = dct; + #if FREE_CBOBJECT_AFTER + cb_objects[(*n_cbitems)++] = arg; + #endif } else if (carg->type == MP_SCHED_CTYPE_TUPLE) { //tuple @@ -178,19 +213,35 @@ static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level) } else if (entry->type == MP_SCHED_ENTRY_TYPE_FLOAT) { tuple[i] = mp_obj_new_float(entry->fval); + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = tuple[i]; + #endif } else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) { - tuple[i] = mp_obj_new_str((const char*)entry->sval, entry->ival, false); + tuple[i] = mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->sval, entry->ival); + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = tuple[i]; + #endif } else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) { tuple[i] = mp_obj_new_bytes((const byte*)entry->sval, entry->ival); + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = tuple[i]; + #endif } else if ((level == 0) && (entry->type == MP_SCHED_ENTRY_TYPE_CARG) && (entry->carg)) { - tuple[i] = make_arg_from_carg(entry->carg, 1); + mp_obj_t darg = make_arg_from_carg(entry->carg, 1, n_cbitems); + tuple[i] = darg; + #if FREE_CBOBJECT_AFTER + if (*n_cbitems < (MAX_CB_OBJECTS-1)) cb_objects[(*n_cbitems)++] = tuple[i]; + #endif } else tuple[i] = mp_const_none; } arg = mp_obj_new_tuple(carg->n, tuple); + #if FREE_CBOBJECT_AFTER + cb_objects[(*n_cbitems)++] = arg; + #endif } else { // Simple type, single entry @@ -203,30 +254,39 @@ static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level) } else if (entry->type == MP_SCHED_ENTRY_TYPE_FLOAT) { arg = mp_obj_new_float(entry->fval); + #if FREE_CBOBJECT_AFTER + cb_objects[(*n_cbitems)++] = arg; + #endif } else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) { - arg = mp_obj_new_str((const char*)entry->sval, entry->ival, false); + arg = mp_obj_new_str_copy(&mp_type_str, (const byte*)entry->sval, entry->ival); + #if FREE_CBOBJECT_AFTER + cb_objects[(*n_cbitems)++] = arg; + #endif } else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) { arg = mp_obj_new_bytes((const byte*)entry->sval, entry->ival); + #if FREE_CBOBJECT_AFTER + cb_objects[(*n_cbitems)++] = arg; + #endif } } + // Free C-argument structure free_carg(carg); + return arg; } -// This function should only be called be mp_sched_handle_pending, +// This function should only be called by mp_sched_handle_pending, // or by the VM's inlined version of that function. //--------------------------------------------------- void mp_handle_pending_tail(mp_uint_t atomic_state) { MP_STATE_VM(sched_state) = MP_SCHED_LOCKED; if (MP_STATE_VM(sched_sp) > 0) { - // Get scheduled item, decrease stack counter - //mp_sched_item_t item = MP_STATE_VM(sched_stack)[--MP_STATE_VM(sched_sp)]; - + int n_cbitems = 0; // get the first scheduled item from stack mp_sched_item_t item = MP_STATE_VM(sched_stack)[0]; - // Move other items + // Move other items down on stack MP_STATE_VM(sched_sp)--; int i = 0; while (i < MP_STATE_VM(sched_sp)) { @@ -237,11 +297,22 @@ void mp_handle_pending_tail(mp_uint_t atomic_state) { mp_obj_t arg = mp_const_none; if (item.carg != NULL) { // === C argument is present, create the MicroPython object argument from it === - arg = make_arg_from_carg((mp_sched_carg_t *)item.carg, 0); + arg = make_arg_from_carg((mp_sched_carg_t *)item.carg, 0, &n_cbitems); } else arg = item.arg; + MICROPY_END_ATOMIC_SECTION(atomic_state); + // Execute callback function mp_call_function_1_protected(item.func, arg); + + #if FREE_CBOBJECT_AFTER + if (n_cbitems) { + // Free all allocated objects + for (int i=0; i < n_cbitems; i++) { + m_free(cb_objects[i]); + } + } + #endif } else { MICROPY_END_ATOMIC_SECTION(atomic_state); } diff --git a/MicroPython_BUILD/components/micropython/py/smallint.h b/MicroPython_BUILD/components/micropython/py/smallint.h index 42679a78..6a3c7523 100644 --- a/MicroPython_BUILD/components/micropython/py/smallint.h +++ b/MicroPython_BUILD/components/micropython/py/smallint.h @@ -50,10 +50,10 @@ #elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D -#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffffffff80000000) >> 1)) -#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffffffff80000000) == 0) +#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffff800000000000) >> 1)) +#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffff800000000000) == 0) // Mask to truncate mp_int_t to positive value -#define MP_SMALL_INT_POSITIVE_MASK ~(0xffffffff80000000 | (0xffffffff80000000 >> 1)) +#define MP_SMALL_INT_POSITIVE_MASK ~(0xffff800000000000 | (0xffff800000000000 >> 1)) #endif diff --git a/MicroPython_BUILD/components/micropython/py/stackctrl.c b/MicroPython_BUILD/components/micropython/py/stackctrl.c index 7cd35fee..5c07796b 100644 --- a/MicroPython_BUILD/components/micropython/py/stackctrl.c +++ b/MicroPython_BUILD/components/micropython/py/stackctrl.c @@ -48,14 +48,9 @@ void mp_stack_set_limit(mp_uint_t limit) { MP_STATE_THREAD(stack_limit) = limit; } -void mp_exc_recursion_depth(void) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError, - MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded))); -} - void mp_stack_check(void) { if (mp_stack_usage() >= MP_STATE_THREAD(stack_limit)) { - mp_exc_recursion_depth(); + mp_raise_recursion_depth(); } } diff --git a/MicroPython_BUILD/components/micropython/py/stream.c b/MicroPython_BUILD/components/micropython/py/stream.c index 453dee76..393988d2 100644 --- a/MicroPython_BUILD/components/micropython/py/stream.c +++ b/MicroPython_BUILD/components/micropython/py/stream.c @@ -32,13 +32,6 @@ #include "py/stream.h" #include "py/runtime.h" -#if MICROPY_STREAMS_NON_BLOCK -#include -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) -#define EWOULDBLOCK 140 -#endif -#endif - // This file defines generic Python stream read/write methods which // dispatch to the underlying stream interface of an object. @@ -105,13 +98,6 @@ const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { return stream_p; } -mp_obj_t mp_stream_close(mp_obj_t stream) { - // TODO: Still consider using ioctl for close - mp_obj_t dest[2]; - mp_load_method(stream, MP_QSTR_close, dest); - return mp_call_method_n_kw(0, 0, dest); -} - STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { const mp_stream_p_t *stream_p = mp_get_stream_raise(args[0], MP_STREAM_OP_READ); @@ -434,6 +420,17 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) { return MP_OBJ_STOP_ITERATION; } +mp_obj_t mp_stream_close(mp_obj_t stream) { + const mp_stream_p_t *stream_p = mp_get_stream_raise(stream, MP_STREAM_OP_IOCTL); + int error; + mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error); + if (res == MP_STREAM_ERROR) { + mp_raise_OSError(error); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_close_obj, mp_stream_close); + STATIC mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) { const mp_stream_p_t *stream_p = mp_get_stream_raise(args[0], MP_STREAM_OP_IOCTL); diff --git a/MicroPython_BUILD/components/micropython/py/stream.h b/MicroPython_BUILD/components/micropython/py/stream.h index fbe3d7d8..a1d1c4f8 100644 --- a/MicroPython_BUILD/components/micropython/py/stream.h +++ b/MicroPython_BUILD/components/micropython/py/stream.h @@ -35,7 +35,7 @@ #define MP_STREAM_FLUSH (1) #define MP_STREAM_SEEK (2) #define MP_STREAM_POLL (3) -//#define MP_STREAM_CLOSE (4) // Not yet implemented +#define MP_STREAM_CLOSE (4) #define MP_STREAM_TIMEOUT (5) // Get/set timeout (single op) #define MP_STREAM_GET_OPTS (6) // Get stream options #define MP_STREAM_SET_OPTS (7) // Set stream options @@ -69,6 +69,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_stream_write1_obj); +MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_close_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_tell_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_flush_obj); @@ -106,7 +107,7 @@ int mp_stream_posix_fsync(mp_obj_t stream); #endif #if MICROPY_STREAMS_NON_BLOCK -#define mp_is_nonblocking_error(errno) ((errno) == EAGAIN || (errno) == EWOULDBLOCK) +#define mp_is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK) #else #define mp_is_nonblocking_error(errno) (0) #endif diff --git a/MicroPython_BUILD/components/micropython/py/unicode.c b/MicroPython_BUILD/components/micropython/py/unicode.c index 140b7ba7..935dc901 100644 --- a/MicroPython_BUILD/components/micropython/py/unicode.c +++ b/MicroPython_BUILD/components/micropython/py/unicode.c @@ -67,9 +67,9 @@ STATIC const uint8_t attr[] = { AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0 }; -// TODO: Rename to str_get_char -unichar utf8_get_char(const byte *s) { #if MICROPY_PY_BUILTINS_STR_UNICODE + +unichar utf8_get_char(const byte *s) { unichar ord = *s++; if (!UTF8_IS_NONASCII(ord)) return ord; ord &= 0x7F; @@ -80,22 +80,14 @@ unichar utf8_get_char(const byte *s) { ord = (ord << 6) | (*s++ & 0x3F); } return ord; -#else - return *s; -#endif } -// TODO: Rename to str_next_char const byte *utf8_next_char(const byte *s) { -#if MICROPY_PY_BUILTINS_STR_UNICODE ++s; while (UTF8_IS_CONT(*s)) { ++s; } return s; -#else - return s + 1; -#endif } mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr) { @@ -109,21 +101,18 @@ mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr) { return i; } -// TODO: Rename to str_charlen -mp_uint_t unichar_charlen(const char *str, mp_uint_t len) { -#if MICROPY_PY_BUILTINS_STR_UNICODE - mp_uint_t charlen = 0; - for (const char *top = str + len; str < top; ++str) { +size_t utf8_charlen(const byte *str, size_t len) { + size_t charlen = 0; + for (const byte *top = str + len; str < top; ++str) { if (!UTF8_IS_CONT(*str)) { ++charlen; } } return charlen; -#else - return len; -#endif } +#endif + // Be aware: These unichar_is* functions are actually ASCII-only! bool unichar_isspace(unichar c) { return c < 128 && (attr[c] & FL_SPACE) != 0; @@ -183,6 +172,8 @@ mp_uint_t unichar_xdigit_value(unichar c) { return n; } +#if MICROPY_PY_BUILTINS_STR_UNICODE + bool utf8_check(const byte *p, size_t len) { uint8_t need = 0; const byte *end = p + len; @@ -210,3 +201,5 @@ bool utf8_check(const byte *p, size_t len) { } return need == 0; // no pending fragments allowed } + +#endif diff --git a/MicroPython_BUILD/components/micropython/py/vm.c b/MicroPython_BUILD/components/micropython/py/vm.c index bf6074df..e1797cac 100644 --- a/MicroPython_BUILD/components/micropython/py/vm.c +++ b/MicroPython_BUILD/components/micropython/py/vm.c @@ -5,6 +5,7 @@ * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +30,7 @@ #include #include #include "mphalport.h" +#include "soc/cpu.h" #include "py/emitglue.h" #include "py/objtype.h" @@ -36,7 +38,7 @@ #include "py/bc0.h" #include "py/bc.h" -#if 0 +#if 0 && MICROPY_DEBUG_PRINTERS #define TRACE(ip) printf("sp=%d ", (int)(sp - &code_state->state[0] + 1)); mp_bytecode_print2(ip, 1, code_state->fun_bc->const_table); #else #define TRACE(ip) @@ -49,14 +51,6 @@ // top element. // Exception stack also grows up, top element is also pointed at. -// Exception stack unwind reasons (WHY_* in CPython-speak) -// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds -// left to do encoded in the JUMP number -typedef enum { - UNWIND_RETURN = 1, - UNWIND_JUMP, -} mp_unwind_reason_t; - #define DECODE_UINT \ mp_uint_t unum = 0; \ do { \ @@ -125,9 +119,10 @@ typedef enum { // MP_VM_RETURN_NORMAL, sp valid, return value in *sp // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp // MP_VM_RETURN_EXCEPTION, exception in fastn[0] -mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) { +//================================================================================================ +mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) +{ mp_hal_set_wdt_tmo(); // LoBo - #define SELECTIVE_EXC_IP (0) #if SELECTIVE_EXC_IP #define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */ @@ -616,29 +611,18 @@ run_code_state: ; mp_call_method_n_kw(3, 0, sp); SET_TOP(mp_const_none); } else if (MP_OBJ_IS_SMALL_INT(TOP())) { - mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP()); - if (cause_val == UNWIND_RETURN) { - // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN) - mp_obj_t ret_val = sp[-1]; - sp[-1] = mp_const_none; - sp[0] = mp_const_none; - sp[1] = mp_const_none; - mp_call_method_n_kw(3, 0, sp - 3); - sp[-3] = ret_val; - sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN); - } else { - assert(cause_val == UNWIND_JUMP); - // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP) - mp_obj_t dest_ip = sp[-2]; - mp_obj_t num_exc = sp[-1]; - sp[-2] = mp_const_none; - sp[-1] = mp_const_none; - sp[0] = mp_const_none; - mp_call_method_n_kw(3, 0, sp - 4); - sp[-4] = dest_ip; - sp[-3] = num_exc; - sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP); - } + // Getting here there are two distinct cases: + // - unwind return, stack: (..., __exit__, ctx_mgr, ret_val, SMALL_INT(-1)) + // - unwind jump, stack: (..., __exit__, ctx_mgr, dest_ip, SMALL_INT(num_exc)) + // For both cases we do exactly the same thing. + mp_obj_t data = sp[-1]; + mp_obj_t cause = sp[0]; + sp[-1] = mp_const_none; + sp[0] = mp_const_none; + sp[1] = mp_const_none; + mp_call_method_n_kw(3, 0, sp - 3); + sp[-3] = data; + sp[-2] = cause; sp -= 2; // we removed (__exit__, ctx_mgr) } else { assert(mp_obj_is_exception_instance(TOP())); @@ -683,10 +667,11 @@ unwind_jump:; // of a "with" block contains the context manager info. // We're going to run "finally" code as a coroutine // (not calling it recursively). Set up a sentinel - // on a stack so it can return back to us when it is + // on the stack so it can return back to us when it is // done (when WITH_CLEANUP or END_FINALLY reached). - PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind - PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel + // The sentinel is the number of exception handlers left to + // unwind, which is a non-negative integer. + PUSH(MP_OBJ_NEW_SMALL_INT(unum)); ip = exc_sp->handler; // get exception handler byte code address exc_sp--; // pop exception handler goto dispatch_loop; // run the exception handler @@ -723,11 +708,14 @@ unwind_jump:; } else if (MP_OBJ_IS_SMALL_INT(TOP())) { // We finished "finally" coroutine and now dispatch back // to our caller, based on TOS value - mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP()); - if (reason == UNWIND_RETURN) { + mp_int_t cause = MP_OBJ_SMALL_INT_VALUE(POP()); + if (cause < 0) { + // A negative cause indicates unwind return goto unwind_return; } else { - assert(reason == UNWIND_JUMP); + // Otherwise it's an unwind jump and we must push as a raw + // number the number of exception handlers to unwind + PUSH((mp_obj_t)cause); goto unwind_jump; } } else { @@ -929,18 +917,22 @@ unwind_jump:; code_state->sp = sp; code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block); mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1); - if (new_state) { + #if !MICROPY_ENABLE_PYSTACK + if (new_state == NULL) { + // Couldn't allocate codestate on heap: in the strict case raise + // an exception, otherwise just fall through to stack allocation. + #if MICROPY_STACKLESS_STRICT + deep_recursion_error: + mp_raise_recursion_depth(); + #endif + } else + #endif + { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } - #if MICROPY_STACKLESS_STRICT - else { - deep_recursion_error: - mp_exc_recursion_depth(); - } - #endif } #endif SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1)); @@ -966,18 +958,26 @@ unwind_jump:; mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); - m_del(mp_obj_t, out_args.args, out_args.n_alloc); - if (new_state) { + #if !MICROPY_ENABLE_PYSTACK + // Freeing args at this point does not follow a LIFO order so only do it if + // pystack is not enabled. For pystack, they are freed when code_state is. + mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t)); + #endif + #if !MICROPY_ENABLE_PYSTACK + if (new_state == NULL) { + // Couldn't allocate codestate on heap: in the strict case raise + // an exception, otherwise just fall through to stack allocation. + #if MICROPY_STACKLESS_STRICT + goto deep_recursion_error; + #endif + } else + #endif + { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } - #if MICROPY_STACKLESS_STRICT - else { - goto deep_recursion_error; - } - #endif } #endif SET_TOP(mp_call_method_n_kw_var(false, unum, sp)); @@ -1001,17 +1001,21 @@ unwind_jump:; int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1; mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust); - if (new_state) { + #if !MICROPY_ENABLE_PYSTACK + if (new_state == NULL) { + // Couldn't allocate codestate on heap: in the strict case raise + // an exception, otherwise just fall through to stack allocation. + #if MICROPY_STACKLESS_STRICT + goto deep_recursion_error; + #endif + } else + #endif + { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } - #if MICROPY_STACKLESS_STRICT - else { - goto deep_recursion_error; - } - #endif } #endif SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp)); @@ -1037,18 +1041,26 @@ unwind_jump:; mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); - m_del(mp_obj_t, out_args.args, out_args.n_alloc); - if (new_state) { + #if !MICROPY_ENABLE_PYSTACK + // Freeing args at this point does not follow a LIFO order so only do it if + // pystack is not enabled. For pystack, they are freed when code_state is. + mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t)); + #endif + #if !MICROPY_ENABLE_PYSTACK + if (new_state == NULL) { + // Couldn't allocate codestate on heap: in the strict case raise + // an exception, otherwise just fall through to stack allocation. + #if MICROPY_STACKLESS_STRICT + goto deep_recursion_error; + #endif + } else + #endif + { new_state->prev = code_state; code_state = new_state; nlr_pop(); goto run_code_state; } - #if MICROPY_STACKLESS_STRICT - else { - goto deep_recursion_error; - } - #endif } #endif SET_TOP(mp_call_method_n_kw_var(true, unum, sp)); @@ -1084,7 +1096,7 @@ unwind_jump:; // (not calling it recursively). Set up a sentinel // on a stack so it can return back to us when it is // done (when WITH_CLEANUP or END_FINALLY reached). - PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN)); + PUSH(MP_OBJ_NEW_SMALL_INT(-1)); ip = exc_sp->handler; exc_sp--; goto dispatch_loop; @@ -1099,7 +1111,15 @@ unwind_jump:; if (code_state->prev != NULL) { mp_obj_t res = *sp; mp_globals_set(code_state->old_globals); - code_state = code_state->prev; + mp_code_state_t *new_code_state = code_state->prev; + #if MICROPY_ENABLE_PYSTACK + // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var + // (The latter is implicitly freed when using pystack due to its LIFO nature.) + // The sizeof in the following statement does not include the size of the variable + // part of the struct. This arg is anyway not used if pystack is enabled. + mp_nonlocal_free(code_state, sizeof(mp_code_state_t)); + #endif + code_state = new_code_state; *code_state->sp = res; goto run_code_state; } @@ -1108,7 +1128,7 @@ unwind_jump:; ENTRY(MP_BC_RAISE_VARARGS): { MARK_EXC_IP_SELECTIVE(); - mp_uint_t unum = *ip++; + mp_uint_t unum = *ip; mp_obj_t obj; if (unum == 2) { mp_warning("exception chaining not supported"); @@ -1129,7 +1149,7 @@ unwind_jump:; RAISE(obj); } } else { - obj = POP(); + obj = TOP(); } obj = mp_make_raise_obj(obj); RAISE(obj); @@ -1152,6 +1172,7 @@ unwind_jump:; mp_obj_t send_value = POP(); mp_obj_t t_exc = MP_OBJ_NULL; mp_obj_t ret_value; + code_state->sp = sp; // Save sp because it's needed if mp_resume raises StopIteration if (inject_exc != MP_OBJ_NULL) { t_exc = inject_exc; inject_exc = MP_OBJ_NULL; @@ -1167,8 +1188,7 @@ unwind_jump:; } else if (ret_kind == MP_VM_RETURN_NORMAL) { // Pop exhausted gen sp--; - // TODO: When ret_value can be MP_OBJ_NULL here?? - if (ret_value == MP_OBJ_NULL || ret_value == MP_OBJ_STOP_ITERATION) { + if (ret_value == MP_OBJ_STOP_ITERATION) { // Optimize StopIteration // TODO: get StopIteration's value PUSH(mp_const_none); @@ -1308,23 +1328,31 @@ unwind_jump:; #if MICROPY_PY_THREAD_GIL #if MICROPY_PY_THREAD_GIL_VM_DIVISOR - if (--gil_divisor == 0) { - gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR; - #else - { + if (--gil_divisor == 0) #endif - #if MICROPY_ENABLE_SCHEDULER - // can only switch threads if the scheduler is unlocked - if ((MP_STATE_VM(sched_state) == MP_SCHED_IDLE) && !MP_STATE_VM(thread_lock)) + { + #if MICROPY_PY_THREAD_GIL_VM_DIVISOR + gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR; #endif - { - mp_hal_reset_wdt();// LoBo - // *** Switch threads *** - MP_THREAD_GIL_EXIT(); - MP_THREAD_GIL_ENTER(); + if (!MP_STATE_VM(thread_lock)) { // LoBo + #if MICROPY_ENABLE_SCHEDULER + // can only switch threads if the scheduler is unlocked + if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) + #endif + { + // LoBo + volatile uint32_t sp = (uint32_t)get_sp(); + mp_thread_set_sp((void *)sp, MP_STATE_THREAD(stack_top)); + void **ptrs = (void**)(void*)&mp_state_ctx; + mp_thread_set_ptrs(ptrs, offsetof(mp_state_ctx_t, vm.qstr_last_chunk) / sizeof(void*)); + mp_hal_reset_wdt(); + // Switch threads + MP_THREAD_GIL_EXIT(); + MP_THREAD_GIL_ENTER(); + } } } - #endif // MICROPY_PY_THREAD_GIL + #endif } // for loop @@ -1353,7 +1381,8 @@ unwind_jump:; } else if (*code_state->ip == MP_BC_YIELD_FROM) { // StopIteration inside yield from call means return a value of // yield from, so inject exception's value as yield from's result - *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + // (Instead of stack pop then push we just replace exhausted gen with value) + *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); code_state->ip++; // yield from is over, move to next instruction goto outer_dispatch_loop; // continue with dispatch loop } @@ -1366,8 +1395,7 @@ unwind_jump:; // set file and line number that the exception occurred at // TODO: don't set traceback for exceptions re-raised by END_FINALLY. // But consider how to handle nested exceptions. - // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj) - if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) { + if (nlr.ret_val != &mp_const_GeneratorExit_obj) { const byte *ip = code_state->fun_bc->bytecode; ip = mp_decode_uint_skip(ip); // skip n_state ip = mp_decode_uint_skip(ip); // skip n_exc_stack @@ -1443,7 +1471,15 @@ unwind_jump:; #if MICROPY_STACKLESS } else if (code_state->prev != NULL) { mp_globals_set(code_state->old_globals); - code_state = code_state->prev; + mp_code_state_t *new_code_state = code_state->prev; + #if MICROPY_ENABLE_PYSTACK + // Free code_state, and args allocated by mp_call_prepare_args_n_kw_var + // (The latter is implicitly freed when using pystack due to its LIFO nature.) + // The sizeof in the following statement does not include the size of the variable + // part of the struct. This arg is anyway not used if pystack is enabled. + mp_nonlocal_free(code_state, sizeof(mp_code_state_t)); + #endif + code_state = new_code_state; size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode); fastn = &code_state->state[n_state - 1]; exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); @@ -1461,4 +1497,5 @@ unwind_jump:; } } } + return MP_VM_RETURN_NORMAL; } diff --git a/MicroPython_BUILD/components/micropython/tools/mpy-tool.py b/MicroPython_BUILD/components/micropython/tools/mpy-tool.py index ac7b2c1c..eeb760a5 100755 --- a/MicroPython_BUILD/components/micropython/tools/mpy-tool.py +++ b/MicroPython_BUILD/components/micropython/tools/mpy-tool.py @@ -287,7 +287,9 @@ def freeze(self, parent_name): # generate constant objects for i, obj in enumerate(self.objs): obj_name = 'const_obj_%s_%u' % (self.escaped_name, i) - if is_str_type(obj) or is_bytes_type(obj): + if obj is Ellipsis: + print('#define %s mp_const_ellipsis_obj' % obj_name) + elif is_str_type(obj) or is_bytes_type(obj): if is_str_type(obj): obj = bytes_cons(obj, 'utf8') obj_type = 'mp_type_str' @@ -328,7 +330,6 @@ def freeze(self, parent_name): print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};' % (obj_name, obj.real, obj.imag)) else: - # TODO raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,)) # generate constant table, if it has any entries diff --git a/MicroPython_BUILD/components/mkfatfs/src/sdkconfig.h b/MicroPython_BUILD/components/mkfatfs/src/sdkconfig.h index dff7b79f..ffad0764 100644 --- a/MicroPython_BUILD/components/mkfatfs/src/sdkconfig.h +++ b/MicroPython_BUILD/components/mkfatfs/src/sdkconfig.h @@ -6,3 +6,7 @@ #define CONFIG_FATFS_CODEPAGE 437 #define CONFIG_FATFS_LFN_HEAP 1 #define CONFIG_FATFS_MAX_LFN 127 + +#ifndef CONFIG_MICROPY_USE_TFT +#define CONFIG_MICROPY_USE_TFT +#endif \ No newline at end of file diff --git a/MicroPython_BUILD/components/mklittlefs/.gitignore b/MicroPython_BUILD/components/mklittlefs/.gitignore new file mode 100644 index 00000000..050966d7 --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/.gitignore @@ -0,0 +1,11 @@ +*.o +*.d +mklfs +mklfs.exe +out.* +*.tar.gz + +# eclipse wokspace files and dirs +.project +.cproject +.settings diff --git a/MicroPython_BUILD/components/mklittlefs/Makefile b/MicroPython_BUILD/components/mklittlefs/Makefile new file mode 100644 index 00000000..1822d553 --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/Makefile @@ -0,0 +1,97 @@ +TARGET = mklfs + +ifeq ($(OS),Windows_NT) + TARGET_OS := WINDOWS + DIST_SUFFIX := windows + ARCHIVE_CMD := 7z a + ARCHIVE_EXTENSION := zip + TARGET := mklfs.exe + TARGET_CFLAGS := -mno-ms-bitfields + TARGET_LDFLAGS := -Wl,-static -static-libgcc + CC=gcc + CXX=g++ +else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + TARGET_OS := LINUX + UNAME_P := $(shell uname -p) + ifeq ($(UNAME_P),x86_64) + DIST_SUFFIX := linux64 + endif + ifneq ($(filter %86,$(UNAME_P)),) + DIST_SUFFIX := linux32 + endif + CC = cc + AR = ar + endif + ifeq ($(UNAME_S),Darwin) + TARGET_OS := OSX + DIST_SUFFIX := osx + CC=clang + CXX=clang++ + TARGET_CFLAGS = -mmacosx-version-min=10.7 -arch i386 -arch x86_64 + TARGET_CXXFLAGS = -mmacosx-version-min=10.7 -arch i386 -arch x86_64 -stdlib=libc++ + TARGET_LDFLAGS = -arch i386 -arch x86_64 -stdlib=libc++ + endif + ARCHIVE_CMD := tar czf + ARCHIVE_EXTENSION := tar.gz + TARGET := mklfs +endif + +OS := $(shell uname -s) + +SIZE = size + +SRC += $(wildcard *.c littlefs/*.c) +OBJ := $(SRC:.c=.o) +DEP := $(SRC:.c=.d) +ASM := $(SRC:.c=.s) + +ifdef DEBUG +override CFLAGS += -O0 -g3 +else +override CFLAGS += -Os +endif +ifdef WORD +override CFLAGS += -m$(WORD) +endif + +override CFLAGS += -I. -Ilittlefs +override CFLAGS += -std=c99 -Wall -pedantic $(TARGET_CFLAGS) +override CFLAGS += -D_FILE_OFFSET_BITS=64 +override CFLAGS += -D_XOPEN_SOURCE=700 + +override LFLAGS += -lfuse + +ifeq ($(OS), FreeBSD) +override CFLAGS += -I /usr/local/include +override CFLAGS += -D __BSD_VISIBLE +override LFLAGS += -L /usr/local/lib +endif + +all: $(TARGET) + +asm: $(ASM) + +size: $(OBJ) + $(SIZE) -t $^ + +-include $(DEP) + +$(TARGET): $(OBJ) + $(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ + +%.a: $(OBJ) + $(AR) rcs $@ $^ + +%.o: %.c + $(CC) -c -MMD $(CFLAGS) $< -o $@ + +%.s: %.c + $(CC) -S $(CFLAGS) $< -o $@ + +clean: + rm -f $(TARGET) + rm -f $(OBJ) + rm -f $(DEP) + rm -f $(ASM) diff --git a/MicroPython_BUILD/components/mklittlefs/littlefs/LICENSE.md b/MicroPython_BUILD/components/mklittlefs/littlefs/LICENSE.md new file mode 100644 index 00000000..59cd3f8a --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/littlefs/LICENSE.md @@ -0,0 +1,165 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. diff --git a/MicroPython_BUILD/components/mklittlefs/littlefs/lfs.c b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs.c new file mode 100644 index 00000000..093de95e --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs.c @@ -0,0 +1,2676 @@ +/* + * The little filesystem + * + * Copyright (c) 2017 ARM Limited + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "lfs.h" +#include "lfs_util.h" + +#define ATTRIBUTE_LEN 5 + +static uint8_t lfs_dir_compute_attribute(uint8_t *buf); +static int lfs_dir_extract_attribute(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, struct lfs_info *info); + +/// Caching block device operations /// +static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache, + const lfs_cache_t *pcache, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size) { + uint8_t *data = buffer; + LFS_ASSERT(block < lfs->cfg->block_count); + + while (size > 0) { + if (pcache && block == pcache->block && off >= pcache->off && + off < pcache->off + lfs->cfg->prog_size) { + // is already in pcache? + lfs_size_t diff = lfs_min(size, + lfs->cfg->prog_size - (off-pcache->off)); + memcpy(data, &pcache->buffer[off-pcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + if (block == rcache->block && off >= rcache->off && + off < rcache->off + lfs->cfg->read_size) { + // is already in rcache? + lfs_size_t diff = lfs_min(size, + lfs->cfg->read_size - (off-rcache->off)); + memcpy(data, &rcache->buffer[off-rcache->off], diff); + + data += diff; + off += diff; + size -= diff; + continue; + } + + if (off % lfs->cfg->read_size == 0 && size >= lfs->cfg->read_size) { + // bypass cache? + lfs_size_t diff = size - (size % lfs->cfg->read_size); + int err = lfs->cfg->read(lfs->cfg, block, off, data, diff); + if (err) { + return err; + } + + data += diff; + off += diff; + size -= diff; + continue; + } + + // load to cache, first condition can no longer fail + rcache->block = block; + rcache->off = off - (off % lfs->cfg->read_size); + int err = lfs->cfg->read(lfs->cfg, rcache->block, + rcache->off, rcache->buffer, lfs->cfg->read_size); + if (err) { + return err; + } + } + + return 0; +} + +static int lfs_cache_cmp(lfs_t *lfs, lfs_cache_t *rcache, + const lfs_cache_t *pcache, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + const uint8_t *data = buffer; + + for (lfs_off_t i = 0; i < size; i++) { + uint8_t c; + int err = lfs_cache_read(lfs, rcache, pcache, + block, off+i, &c, 1); + if (err) { + return err; + } + + if (c != data[i]) { + return false; + } + } + + return true; +} + +static int lfs_cache_crc(lfs_t *lfs, lfs_cache_t *rcache, + const lfs_cache_t *pcache, lfs_block_t block, + lfs_off_t off, lfs_size_t size, uint32_t *crc) { + for (lfs_off_t i = 0; i < size; i++) { + uint8_t c; + int err = lfs_cache_read(lfs, rcache, pcache, + block, off+i, &c, 1); + if (err) { + return err; + } + + lfs_crc(crc, &c, 1); + } + + return 0; +} + +static int lfs_cache_flush(lfs_t *lfs, + lfs_cache_t *pcache, lfs_cache_t *rcache) { + if (pcache->block != 0xffffffff) { + int err = lfs->cfg->prog(lfs->cfg, pcache->block, + pcache->off, pcache->buffer, lfs->cfg->prog_size); + if (err) { + return err; + } + + if (rcache) { + int res = lfs_cache_cmp(lfs, rcache, NULL, pcache->block, + pcache->off, pcache->buffer, lfs->cfg->prog_size); + if (res < 0) { + return res; + } + + if (!res) { + return LFS_ERR_CORRUPT; + } + } + + pcache->block = 0xffffffff; + } + + return 0; +} + +static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache, + lfs_cache_t *rcache, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + const uint8_t *data = buffer; + LFS_ASSERT(block < lfs->cfg->block_count); + + while (size > 0) { + if (block == pcache->block && off >= pcache->off && + off < pcache->off + lfs->cfg->prog_size) { + // is already in pcache? + lfs_size_t diff = lfs_min(size, + lfs->cfg->prog_size - (off-pcache->off)); + memcpy(&pcache->buffer[off-pcache->off], data, diff); + + data += diff; + off += diff; + size -= diff; + + if (off % lfs->cfg->prog_size == 0) { + // eagerly flush out pcache if we fill up + int err = lfs_cache_flush(lfs, pcache, rcache); + if (err) { + return err; + } + } + + continue; + } + + // pcache must have been flushed, either by programming and + // entire block or manually flushing the pcache + LFS_ASSERT(pcache->block == 0xffffffff); + + if (off % lfs->cfg->prog_size == 0 && + size >= lfs->cfg->prog_size) { + // bypass pcache? + lfs_size_t diff = size - (size % lfs->cfg->prog_size); + int err = lfs->cfg->prog(lfs->cfg, block, off, data, diff); + if (err) { + return err; + } + + if (rcache) { + int res = lfs_cache_cmp(lfs, rcache, NULL, + block, off, data, diff); + if (res < 0) { + return res; + } + + if (!res) { + return LFS_ERR_CORRUPT; + } + } + + data += diff; + off += diff; + size -= diff; + continue; + } + + // prepare pcache, first condition can no longer fail + pcache->block = block; + pcache->off = off - (off % lfs->cfg->prog_size); + } + + return 0; +} + + +/// General lfs block device operations /// +static int lfs_bd_read(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size) { + // if we ever do more than writes to alternating pairs, + // this may need to consider pcache + return lfs_cache_read(lfs, &lfs->rcache, NULL, + block, off, buffer, size); +} + +static int lfs_bd_prog(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + return lfs_cache_prog(lfs, &lfs->pcache, NULL, + block, off, buffer, size); +} + +static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size) { + return lfs_cache_cmp(lfs, &lfs->rcache, NULL, block, off, buffer, size); +} + +static int lfs_bd_crc(lfs_t *lfs, lfs_block_t block, + lfs_off_t off, lfs_size_t size, uint32_t *crc) { + return lfs_cache_crc(lfs, &lfs->rcache, NULL, block, off, size, crc); +} + +static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { + return lfs->cfg->erase(lfs->cfg, block); +} + +static int lfs_bd_sync(lfs_t *lfs) { + lfs->rcache.block = 0xffffffff; + + int err = lfs_cache_flush(lfs, &lfs->pcache, NULL); + if (err) { + return err; + } + + return lfs->cfg->sync(lfs->cfg); +} + + +/// Internal operations predeclared here /// +int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); +static int lfs_pred(lfs_t *lfs, const lfs_block_t dir[2], lfs_dir_t *pdir); +static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2], + lfs_dir_t *parent, lfs_entry_t *entry); +static int lfs_moved(lfs_t *lfs, const void *e); +static int lfs_relocate(lfs_t *lfs, + const lfs_block_t oldpair[2], const lfs_block_t newpair[2]); +int lfs_deorphan(lfs_t *lfs); + + +/// Block allocator /// +static int lfs_alloc_lookahead(void *p, lfs_block_t block) { + lfs_t *lfs = p; + + lfs_block_t off = (((lfs_soff_t)(block - lfs->free.begin) + % (lfs_soff_t)(lfs->cfg->block_count)) + + lfs->cfg->block_count) % lfs->cfg->block_count; + + if (off < lfs->free.size) { + lfs->free.buffer[off / 32] |= 1U << (off % 32); + } + + return 0; +} + +//--------------------------------------------- +int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { + while (true) { + while (lfs->free.off != lfs->free.size) { + lfs_block_t off = lfs->free.off; + lfs->free.off += 1; + + if (!(lfs->free.buffer[off / 32] & (1U << (off % 32)))) { + // found a free block + *block = (lfs->free.begin + off) % lfs->cfg->block_count; + return 0; + } + } + + // check if we have looked at all blocks since last ack + if (lfs->free.off == lfs->free.ack - lfs->free.begin) { + LFS_WARN("No more free space %d", lfs->free.off + lfs->free.begin); + return LFS_ERR_NOSPC; + } + + lfs->free.begin += lfs->free.size; + lfs->free.size = lfs_min(lfs->cfg->lookahead, + lfs->free.ack - lfs->free.begin); + lfs->free.off = 0; + + // find mask of free blocks from tree + memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); + int err = lfs_traverse(lfs, lfs_alloc_lookahead, lfs); + if (err) { + return err; + } + } +} + +static void lfs_alloc_ack(lfs_t *lfs) { + lfs->free.ack = lfs->free.off-1 + lfs->free.begin + lfs->cfg->block_count; +} + + +/// Endian swapping functions /// +static void lfs_dir_fromle32(struct lfs_disk_dir *d) { + d->rev = lfs_fromle32(d->rev); + d->size = lfs_fromle32(d->size); + d->tail[0] = lfs_fromle32(d->tail[0]); + d->tail[1] = lfs_fromle32(d->tail[1]); +} + +static void lfs_dir_tole32(struct lfs_disk_dir *d) { + d->rev = lfs_tole32(d->rev); + d->size = lfs_tole32(d->size); + d->tail[0] = lfs_tole32(d->tail[0]); + d->tail[1] = lfs_tole32(d->tail[1]); +} + +static void lfs_entry_fromle32(struct lfs_disk_entry *d) { + d->u.dir[0] = lfs_fromle32(d->u.dir[0]); + d->u.dir[1] = lfs_fromle32(d->u.dir[1]); +} + +static void lfs_entry_tole32(struct lfs_disk_entry *d) { + d->u.dir[0] = lfs_tole32(d->u.dir[0]); + d->u.dir[1] = lfs_tole32(d->u.dir[1]); +} + +static void lfs_superblock_fromle32(struct lfs_disk_superblock *d) { + d->root[0] = lfs_fromle32(d->root[0]); + d->root[1] = lfs_fromle32(d->root[1]); + d->block_size = lfs_fromle32(d->block_size); + d->block_count = lfs_fromle32(d->block_count); + d->version = lfs_fromle32(d->version); +} + +static void lfs_superblock_tole32(struct lfs_disk_superblock *d) { + d->root[0] = lfs_tole32(d->root[0]); + d->root[1] = lfs_tole32(d->root[1]); + d->block_size = lfs_tole32(d->block_size); + d->block_count = lfs_tole32(d->block_count); + d->version = lfs_tole32(d->version); +} + + +/// Metadata pair and directory operations /// +static inline void lfs_pairswap(lfs_block_t pair[2]) { + lfs_block_t t = pair[0]; + pair[0] = pair[1]; + pair[1] = t; +} + +static inline bool lfs_pairisnull(const lfs_block_t pair[2]) { + return pair[0] == 0xffffffff || pair[1] == 0xffffffff; +} + +static inline int lfs_paircmp( + const lfs_block_t paira[2], + const lfs_block_t pairb[2]) { + return !(paira[0] == pairb[0] || paira[1] == pairb[1] || + paira[0] == pairb[1] || paira[1] == pairb[0]); +} + +static inline bool lfs_pairsync( + const lfs_block_t paira[2], + const lfs_block_t pairb[2]) { + return (paira[0] == pairb[0] && paira[1] == pairb[1]) || + (paira[0] == pairb[1] && paira[1] == pairb[0]); +} + +static inline lfs_size_t lfs_entry_size(const lfs_entry_t *entry) { + return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; +} + +static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) { + // allocate pair of dir blocks + for (int i = 0; i < 2; i++) { + int err = lfs_alloc(lfs, &dir->pair[i]); + if (err) { + return err; + } + } + + // rather than clobbering one of the blocks we just pretend + // the revision may be valid + int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->d.rev, 4); + dir->d.rev = lfs_fromle32(dir->d.rev); + if (err) { + return err; + } + + // set defaults + dir->d.rev += 1; + dir->d.size = sizeof(dir->d)+4; + dir->d.tail[0] = 0xffffffff; + dir->d.tail[1] = 0xffffffff; + dir->off = sizeof(dir->d); + + // don't write out yet, let caller take care of that + return 0; +} + +static int lfs_dir_fetch(lfs_t *lfs, + lfs_dir_t *dir, const lfs_block_t pair[2]) { + // copy out pair, otherwise may be aliasing dir + const lfs_block_t tpair[2] = {pair[0], pair[1]}; + bool valid = false; + + // check both blocks for the most recent revision + for (int i = 0; i < 2; i++) { + struct lfs_disk_dir test; + int err = lfs_bd_read(lfs, tpair[i], 0, &test, sizeof(test)); + lfs_dir_fromle32(&test); + if (err) { + return err; + } + + if (valid && lfs_scmp(test.rev, dir->d.rev) < 0) { + continue; + } + + if ((0x7fffffff & test.size) < sizeof(test)+4 || + (0x7fffffff & test.size) > lfs->cfg->block_size) { + continue; + } + + uint32_t crc = 0xffffffff; + lfs_dir_tole32(&test); + lfs_crc(&crc, &test, sizeof(test)); + lfs_dir_fromle32(&test); + err = lfs_bd_crc(lfs, tpair[i], sizeof(test), + (0x7fffffff & test.size) - sizeof(test), &crc); + if (err) { + return err; + } + + if (crc != 0) { + continue; + } + + valid = true; + + // setup dir in case it's valid + dir->pair[0] = tpair[(i+0) % 2]; + dir->pair[1] = tpair[(i+1) % 2]; + dir->off = sizeof(dir->d); + dir->d = test; + } + + if (!valid) { + LFS_ERROR("Corrupted dir pair at %d %d", tpair[0], tpair[1]); + return LFS_ERR_CORRUPT; + } + + return 0; +} + +struct lfs_region { + lfs_off_t oldoff; + lfs_size_t oldlen; + const void *newdata; + lfs_size_t newlen; +}; + +static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, + const struct lfs_region *regions, int count) { + // increment revision count + dir->d.rev += 1; + + // keep pairs in order such that pair[0] is most recent + lfs_pairswap(dir->pair); + for (int i = 0; i < count; i++) { + dir->d.size += regions[i].newlen - regions[i].oldlen; + } + + const lfs_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; + bool relocated = false; + + while (true) { + if (true) { + int err = lfs_bd_erase(lfs, dir->pair[0]); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + uint32_t crc = 0xffffffff; + lfs_dir_tole32(&dir->d); + lfs_crc(&crc, &dir->d, sizeof(dir->d)); + err = lfs_bd_prog(lfs, dir->pair[0], 0, &dir->d, sizeof(dir->d)); + lfs_dir_fromle32(&dir->d); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + int i = 0; + lfs_off_t oldoff = sizeof(dir->d); + lfs_off_t newoff = sizeof(dir->d); + while (newoff < (0x7fffffff & dir->d.size)-4) { + if (i < count && regions[i].oldoff == oldoff) { + lfs_crc(&crc, regions[i].newdata, regions[i].newlen); + err = lfs_bd_prog(lfs, dir->pair[0], + newoff, regions[i].newdata, regions[i].newlen); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + oldoff += regions[i].oldlen; + newoff += regions[i].newlen; + i += 1; + } else { + uint8_t data; + err = lfs_bd_read(lfs, oldpair[1], oldoff, &data, 1); + if (err) { + return err; + } + + lfs_crc(&crc, &data, 1); + err = lfs_bd_prog(lfs, dir->pair[0], newoff, &data, 1); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + oldoff += 1; + newoff += 1; + } + } + + crc = lfs_tole32(crc); + err = lfs_bd_prog(lfs, dir->pair[0], newoff, &crc, 4); + crc = lfs_fromle32(crc); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + err = lfs_bd_sync(lfs); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // successful commit, check checksum to make sure + uint32_t ncrc = 0xffffffff; + err = lfs_bd_crc(lfs, dir->pair[0], 0, + (0x7fffffff & dir->d.size)-4, &ncrc); + if (err) { + return err; + } + + if (ncrc != crc) { + goto relocate; + } + } + + break; +relocate: + //commit was corrupted + LFS_DEBUG("Bad block at %d", dir->pair[0]); + + // drop caches and prepare to relocate block + relocated = true; + lfs->pcache.block = 0xffffffff; + + // can't relocate superblock, filesystem is now frozen + if (lfs_paircmp(oldpair, (const lfs_block_t[2]){0, 1}) == 0) { + LFS_WARN("Superblock %d has become unwritable", oldpair[0]); + return LFS_ERR_CORRUPT; + } + + // relocate half of pair + int err = lfs_alloc(lfs, &dir->pair[0]); + if (err) { + return err; + } + } + + if (relocated) { + // update references if we relocated + LFS_DEBUG("Relocating %d %d to %d %d", + oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); + int err = lfs_relocate(lfs, oldpair, dir->pair); + if (err) { + return err; + } + } + + // shift over any directories that are affected + for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { + if (lfs_paircmp(d->pair, dir->pair) == 0) { + d->pair[0] = dir->pair[0]; + d->pair[1] = dir->pair[1]; + } + } + + return 0; +} + +//--------------------------------------------------- +static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, + lfs_entry_t *entry, const void *data, const void *attribute) { + lfs_entry_tole32(&entry->d); + int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, + {entry->off+sizeof(entry->d), entry->d.alen, attribute, entry->d.alen}, + {entry->off+sizeof(entry->d)+entry->d.alen, entry->d.nlen, data, entry->d.nlen} + }, data ? 3 : attribute ? 2 : 1); + lfs_entry_fromle32(&entry->d); + return err; +} + +//------------------------------------------------------------------------------------------------------------------ +static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, const void *data, const void *attribute) { + // check if we fit, if top bit is set we do not and move on + while (true) { + if (dir->d.size + lfs_entry_size(entry) <= lfs->cfg->block_size) { + entry->off = dir->d.size - 4; + + lfs_entry_tole32(&entry->d); + int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, 0, &entry->d, sizeof(entry->d)}, + {entry->off, 0, attribute, entry->d.alen}, + {entry->off, 0, data, entry->d.nlen} + }, 3); + lfs_entry_fromle32(&entry->d); + return err; + } + + // we need to allocate a new dir block + if (!(0x80000000 & dir->d.size)) { + lfs_dir_t olddir = *dir; + int err = lfs_dir_alloc(lfs, dir); + if (err) { + return err; + } + + dir->d.tail[0] = olddir.d.tail[0]; + dir->d.tail[1] = olddir.d.tail[1]; + entry->off = dir->d.size - 4; + lfs_entry_tole32(&entry->d); + err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, 0, &entry->d, sizeof(entry->d)}, + {entry->off, 0, attribute, entry->d.alen}, + {entry->off, 0, data, entry->d.nlen} + }, 3); + lfs_entry_fromle32(&entry->d); + if (err) { + return err; + } + + olddir.d.size |= 0x80000000; + olddir.d.tail[0] = dir->pair[0]; + olddir.d.tail[1] = dir->pair[1]; + return lfs_dir_commit(lfs, &olddir, NULL, 0); + } + + int err = lfs_dir_fetch(lfs, dir, dir->d.tail); + if (err) { + return err; + } + } +} + +static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { + // check if we should just drop the directory block + if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + + lfs_entry_size(entry)) { + lfs_dir_t pdir; + int res = lfs_pred(lfs, dir->pair, &pdir); + if (res < 0) { + return res; + } + + if (pdir.d.size & 0x80000000) { + pdir.d.size &= dir->d.size | 0x7fffffff; + pdir.d.tail[0] = dir->d.tail[0]; + pdir.d.tail[1] = dir->d.tail[1]; + return lfs_dir_commit(lfs, &pdir, NULL, 0); + } + } + + // shift out the entry + int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, lfs_entry_size(entry), NULL, 0}, + }, 1); + if (err) { + return err; + } + + // shift over any files/directories that are affected + for (lfs_file_t *f = lfs->files; f; f = f->next) { + if (lfs_paircmp(f->pair, dir->pair) == 0) { + if (f->poff == entry->off) { + f->pair[0] = 0xffffffff; + f->pair[1] = 0xffffffff; + } else if (f->poff > entry->off) { + f->poff -= lfs_entry_size(entry); + } + } + } + + for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { + if (lfs_paircmp(d->pair, dir->pair) == 0) { + if (d->off > entry->off) { + d->off -= lfs_entry_size(entry); + d->pos -= lfs_entry_size(entry); + } + } + } + + return 0; +} + +static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { + while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) { + if (!(0x80000000 & dir->d.size)) { + entry->off = dir->off; + return LFS_ERR_NOENT; + } + + int err = lfs_dir_fetch(lfs, dir, dir->d.tail); + if (err) { + return err; + } + + dir->off = sizeof(dir->d); + dir->pos += sizeof(dir->d) + 4; + } + + int err = lfs_bd_read(lfs, dir->pair[0], dir->off, + &entry->d, sizeof(entry->d)); + lfs_entry_fromle32(&entry->d); + if (err) { + return err; + } + + entry->off = dir->off; + dir->off += lfs_entry_size(entry); + dir->pos += lfs_entry_size(entry); + return 0; +} + +static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, + lfs_entry_t *entry, const char **path) { + const char *pathname = *path; + size_t pathlen; + + while (true) { + nextname: + // skip slashes + pathname += strspn(pathname, "/"); + pathlen = strcspn(pathname, "/"); + + // special case for root dir + if (pathname[0] == '\0') { + *entry = (lfs_entry_t){ + .d.type = LFS_TYPE_DIR, + .d.elen = sizeof(entry->d) - 4, + .d.alen = 0, + .d.nlen = 0, + .d.u.dir[0] = lfs->root[0], + .d.u.dir[1] = lfs->root[1], + }; + return 0; + } + + // skip '.' and root '..' + if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) || + (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) { + pathname += pathlen; + goto nextname; + } + + // skip if matched by '..' in name + const char *suffix = pathname + pathlen; + size_t sufflen; + int depth = 1; + while (true) { + suffix += strspn(suffix, "/"); + sufflen = strcspn(suffix, "/"); + if (sufflen == 0) { + break; + } + + if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { + depth -= 1; + if (depth == 0) { + pathname = suffix + sufflen; + goto nextname; + } + } else { + depth += 1; + } + + suffix += sufflen; + } + + // update what we've found + *path = pathname; + + // find path + while (true) { + int err = lfs_dir_next(lfs, dir, entry); + if (err) { + return err; + } + + if (((0x7f & entry->d.type) != LFS_TYPE_REG && + (0x7f & entry->d.type) != LFS_TYPE_DIR) || + entry->d.nlen != pathlen) { + continue; + } + + int res = lfs_bd_cmp(lfs, dir->pair[0], + entry->off + 4+entry->d.elen+entry->d.alen, + pathname, pathlen); + if (res < 0) { + return res; + } + + // found match + if (res) { + break; + } + } + + // check that entry has not been moved + if (entry->d.type & 0x80) { + int moved = lfs_moved(lfs, &entry->d.u); + if (moved < 0 || moved) { + return (moved < 0) ? moved : LFS_ERR_NOENT; + } + + entry->d.type &= ~0x80; + } + + pathname += pathlen; + pathname += strspn(pathname, "/"); + if (pathname[0] == '\0') { + return 0; + } + + // continue on if we hit a directory + if (entry->d.type != LFS_TYPE_DIR) { + return LFS_ERR_NOTDIR; + } + + int err = lfs_dir_fetch(lfs, dir, entry->d.u.dir); + if (err) { + return err; + } + } +} + + +/// Top level directory operations /// + +//------------------------------------------- +int lfs_mkdir(lfs_t *lfs, const char *path) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + // fetch parent directory + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) { + return err ? err : LFS_ERR_EXIST; + } + + // build up new directory + lfs_alloc_ack(lfs); + + lfs_dir_t dir; + err = lfs_dir_alloc(lfs, &dir); + if (err) { + return err; + } + dir.d.tail[0] = cwd.d.tail[0]; + dir.d.tail[1] = cwd.d.tail[1]; + + err = lfs_dir_commit(lfs, &dir, NULL, 0); + if (err) { + return err; + } + + uint8_t attribute[ATTRIBUTE_LEN]; + entry.d.type = LFS_TYPE_DIR; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = lfs_dir_compute_attribute(attribute); + entry.d.nlen = strlen(path); + entry.d.u.dir[0] = dir.pair[0]; + entry.d.u.dir[1] = dir.pair[1]; + + cwd.d.tail[0] = dir.pair[0]; + cwd.d.tail[1] = dir.pair[1]; + + err = lfs_dir_append(lfs, &cwd, &entry, path, attribute); + if (err) { + return err; + } + + lfs_alloc_ack(lfs); + return 0; +} + +int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { + dir->pair[0] = lfs->root[0]; + dir->pair[1] = lfs->root[1]; + + int err = lfs_dir_fetch(lfs, dir, dir->pair); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, dir, &entry, &path); + if (err) { + return err; + } else if (entry.d.type != LFS_TYPE_DIR) { + return LFS_ERR_NOTDIR; + } + + err = lfs_dir_fetch(lfs, dir, entry.d.u.dir); + if (err) { + return err; + } + + // setup head dir + // special offset for '.' and '..' + dir->head[0] = dir->pair[0]; + dir->head[1] = dir->pair[1]; + dir->pos = sizeof(dir->d) - 2; + dir->off = sizeof(dir->d); + + // add to list of directories + dir->next = lfs->dirs; + lfs->dirs = dir; + + return 0; +} + +int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) { + // remove from list of directories + for (lfs_dir_t **p = &lfs->dirs; *p; p = &(*p)->next) { + if (*p == dir) { + *p = dir->next; + break; + } + } + + return 0; +} + +//------------------------------------------------------------------- +int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { + memset(info, 0, sizeof(*info)); + + // special offset for '.' and '..' + if (dir->pos == sizeof(dir->d) - 2) { + info->type = LFS_TYPE_DIR; + strcpy(info->name, "."); + dir->pos += 1; + return 1; + } else if (dir->pos == sizeof(dir->d) - 1) { + info->type = LFS_TYPE_DIR; + strcpy(info->name, ".."); + dir->pos += 1; + return 1; + } + + lfs_entry_t entry; + while (true) { + int err = lfs_dir_next(lfs, dir, &entry); + if (err) { + return (err == LFS_ERR_NOENT) ? 0 : err; + } + + if ((0x7f & entry.d.type) != LFS_TYPE_REG && + (0x7f & entry.d.type) != LFS_TYPE_DIR) { + continue; + } + + // check that entry has not been moved + if (entry.d.type & 0x80) { + int moved = lfs_moved(lfs, &entry.d.u); + if (moved < 0) { + return moved; + } + + if (moved) { + continue; + } + + entry.d.type &= ~0x80; + } + + break; + } + + info->type = entry.d.type; + if (info->type == LFS_TYPE_REG) { + info->size = entry.d.u.file.size; + } + + int err = 0; + if (entry.d.alen > 0) { + err = lfs_dir_extract_attribute(lfs, dir, &entry, info); + } + + err = lfs_bd_read(lfs, dir->pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); + if (err) { + return err; + } + + return 1; +} + +int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) { + // simply walk from head dir + int err = lfs_dir_rewind(lfs, dir); + if (err) { + return err; + } + dir->pos = off; + + while (off > (0x7fffffff & dir->d.size)) { + off -= 0x7fffffff & dir->d.size; + if (!(0x80000000 & dir->d.size)) { + return LFS_ERR_INVAL; + } + + err = lfs_dir_fetch(lfs, dir, dir->d.tail); + if (err) { + return err; + } + } + + dir->off = off; + return 0; +} + +lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) { + (void)lfs; + return dir->pos; +} + +int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) { + // reload the head dir + int err = lfs_dir_fetch(lfs, dir, dir->head); + if (err) { + return err; + } + + dir->pair[0] = dir->head[0]; + dir->pair[1] = dir->head[1]; + dir->pos = sizeof(dir->d) - 2; + dir->off = sizeof(dir->d); + return 0; +} + + +/// File index list operations /// +static int lfs_ctz_index(lfs_t *lfs, lfs_off_t *off) { + lfs_off_t size = *off; + lfs_off_t b = lfs->cfg->block_size - 2*4; + lfs_off_t i = size / b; + if (i == 0) { + return 0; + } + + i = (size - 4*(lfs_popc(i-1)+2)) / b; + *off = size - b*i - 4*lfs_popc(i); + return i; +} + +static int lfs_ctz_find(lfs_t *lfs, + lfs_cache_t *rcache, const lfs_cache_t *pcache, + lfs_block_t head, lfs_size_t size, + lfs_size_t pos, lfs_block_t *block, lfs_off_t *off) { + if (size == 0) { + *block = 0xffffffff; + *off = 0; + return 0; + } + + lfs_off_t current = lfs_ctz_index(lfs, &(lfs_off_t){size-1}); + lfs_off_t target = lfs_ctz_index(lfs, &pos); + + while (current > target) { + lfs_size_t skip = lfs_min( + lfs_npw2(current-target+1) - 1, + lfs_ctz(current)); + + int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4); + head = lfs_fromle32(head); + if (err) { + return err; + } + + LFS_ASSERT(head >= 2 && head <= lfs->cfg->block_count); + current -= 1 << skip; + } + + *block = head; + *off = pos; + return 0; +} + +//----------------------------------- +static int lfs_ctz_extend(lfs_t *lfs, + lfs_cache_t *rcache, lfs_cache_t *pcache, + lfs_block_t head, lfs_size_t size, + lfs_block_t *block, lfs_off_t *off) { + + memset(pcache->buffer, 0xFF, lfs->cfg->prog_size); + + while (true) { + // go ahead and grab a block + lfs_block_t nblock; + int err = lfs_alloc(lfs, &nblock); + if (err) { + return err; + } + LFS_ASSERT(nblock >= 2 && nblock <= lfs->cfg->block_count); + + if (true) { + err = lfs_bd_erase(lfs, nblock); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (size == 0) { + *block = nblock; + *off = 0; + return 0; + } + + size -= 1; + lfs_off_t index = lfs_ctz_index(lfs, &size); + size += 1; + + // just copy out the last block if it is incomplete + if (size != lfs->cfg->block_size) { + for (lfs_off_t i = 0; i < size; i++) { + uint8_t data; + err = lfs_cache_read(lfs, rcache, NULL, + head, i, &data, 1); + if (err) { + return err; + } + + err = lfs_cache_prog(lfs, pcache, rcache, + nblock, i, &data, 1); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + *block = nblock; + *off = size; + return 0; + } + + // append block + index += 1; + lfs_size_t skips = lfs_ctz(index) + 1; + + for (lfs_off_t i = 0; i < skips; i++) { + head = lfs_tole32(head); + err = lfs_cache_prog(lfs, pcache, rcache, + nblock, 4*i, &head, 4); + head = lfs_fromle32(head); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + if (i != skips-1) { + err = lfs_cache_read(lfs, rcache, NULL, + head, 4*i, &head, 4); + head = lfs_fromle32(head); + if (err) { + return err; + } + } + + LFS_ASSERT(head >= 2 && head <= lfs->cfg->block_count); + } + + *block = nblock; + *off = 4*skips; + return 0; + } + +relocate: + LFS_DEBUG("Bad block at %d", nblock); + + // just clear cache and try a new block + pcache->block = 0xffffffff; + } +} + +static int lfs_ctz_traverse(lfs_t *lfs, + lfs_cache_t *rcache, const lfs_cache_t *pcache, + lfs_block_t head, lfs_size_t size, + int (*cb)(void*, lfs_block_t), void *data) { + if (size == 0) { + return 0; + } + + lfs_off_t index = lfs_ctz_index(lfs, &(lfs_off_t){size-1}); + + while (true) { + int err = cb(data, head); + if (err) { + return err; + } + + if (index == 0) { + return 0; + } + + lfs_block_t heads[2]; + int count = 2 - (index & 1); + err = lfs_cache_read(lfs, rcache, pcache, head, 0, &heads, count*4); + heads[0] = lfs_fromle32(heads[0]); + heads[1] = lfs_fromle32(heads[1]); + if (err) { + return err; + } + + for (int i = 0; i < count-1; i++) { + err = cb(data, heads[i]); + if (err) { + return err; + } + } + + head = heads[count-1]; + index -= count; + } +} + + +/// Top level file operations /// + +//---------------------------------------------------------------------------- +int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) { + // deorphan if we haven't yet, needed at most once after poweron + if ((flags & 3) != LFS_O_RDONLY && !lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + // allocate entry for file if it doesn't exist + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL)) { + return err; + } + + if (err == LFS_ERR_NOENT) { + if (!(flags & LFS_O_CREAT)) { + return LFS_ERR_NOENT; + } + + uint8_t attribute[ATTRIBUTE_LEN]; + + // create entry to remember name + entry.d.type = LFS_TYPE_REG; + entry.d.elen = sizeof(entry.d) - 4; + entry.d.alen = lfs_dir_compute_attribute(attribute); + entry.d.nlen = strlen(path); + entry.d.u.file.head = 0xffffffff; + entry.d.u.file.size = 0; + err = lfs_dir_append(lfs, &cwd, &entry, path, attribute); + if (err) { + return err; + } + } + else if (entry.d.type == LFS_TYPE_DIR) { + return LFS_ERR_ISDIR; + } + else if (flags & LFS_O_EXCL) { + return LFS_ERR_EXIST; + } + + // setup file struct + file->pair[0] = cwd.pair[0]; + file->pair[1] = cwd.pair[1]; + file->poff = entry.off; + file->head = entry.d.u.file.head; + file->size = entry.d.u.file.size; + file->flags = flags; + file->pos = 0; + + if (flags & LFS_O_TRUNC) { + if (file->size != 0) { + file->flags |= LFS_F_DIRTY; + } + file->head = 0xffffffff; + file->size = 0; + } + + // allocate buffer if needed + file->cache.block = 0xffffffff; + if (lfs->cfg->file_buffer) { + file->cache.buffer = lfs->cfg->file_buffer; + } + else if ((file->flags & 3) == LFS_O_RDONLY) { + file->cache.buffer = lfs_malloc(lfs->cfg->read_size); + if (!file->cache.buffer) { + return LFS_ERR_NOMEM; + } + } + else { + file->cache.buffer = lfs_malloc(lfs->cfg->prog_size); + if (!file->cache.buffer) { + return LFS_ERR_NOMEM; + } + } + + // add to list of files + file->next = lfs->files; + lfs->files = file; + + return 0; +} + +int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { + int err = lfs_file_sync(lfs, file); + + // remove from list of files + for (lfs_file_t **p = &lfs->files; *p; p = &(*p)->next) { + if (*p == file) { + *p = file->next; + break; + } + } + + // clean up memory + if (!lfs->cfg->file_buffer) { + lfs_free(file->cache.buffer); + } + + return err; +} + +static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { +relocate: + LFS_DEBUG("Bad block at %d", file->block); + + // just relocate what exists into new block + lfs_block_t nblock; + int err = lfs_alloc(lfs, &nblock); + if (err) { + return err; + } + + err = lfs_bd_erase(lfs, nblock); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + // either read from dirty cache or disk + for (lfs_off_t i = 0; i < file->off; i++) { + uint8_t data; + err = lfs_cache_read(lfs, &lfs->rcache, &file->cache, + file->block, i, &data, 1); + if (err) { + return err; + } + + err = lfs_cache_prog(lfs, &lfs->pcache, &lfs->rcache, + nblock, i, &data, 1); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + } + + // copy over new state of file + memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->prog_size); + file->cache.block = lfs->pcache.block; + file->cache.off = lfs->pcache.off; + lfs->pcache.block = 0xffffffff; + + file->block = nblock; + return 0; +} + +static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { + if (file->flags & LFS_F_READING) { + // just drop read cache + file->cache.block = 0xffffffff; + file->flags &= ~LFS_F_READING; + } + + if (file->flags & LFS_F_WRITING) { + lfs_off_t pos = file->pos; + + // copy over anything after current branch + lfs_file_t orig = { + .head = file->head, + .size = file->size, + .flags = LFS_O_RDONLY, + .pos = file->pos, + .cache = lfs->rcache, + }; + lfs->rcache.block = 0xffffffff; + + while (file->pos < file->size) { + // copy over a byte at a time, leave it up to caching + // to make this efficient + uint8_t data; + lfs_ssize_t res = lfs_file_read(lfs, &orig, &data, 1); + if (res < 0) { + return res; + } + + res = lfs_file_write(lfs, file, &data, 1); + if (res < 0) { + return res; + } + + // keep our reference to the rcache in sync + if (lfs->rcache.block != 0xffffffff) { + orig.cache.block = 0xffffffff; + lfs->rcache.block = 0xffffffff; + } + } + + // write out what we have + while (true) { + int err = lfs_cache_flush(lfs, &file->cache, &lfs->rcache); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + return err; + } + + break; +relocate: + err = lfs_file_relocate(lfs, file); + if (err) { + return err; + } + } + + // actual file updates + file->head = file->block; + file->size = file->pos; + file->flags &= ~LFS_F_WRITING; + file->flags |= LFS_F_DIRTY; + + file->pos = pos; + } + + return 0; +} + +//----------------------------------------------- +int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + + if ((file->flags & LFS_F_DIRTY) && + !(file->flags & LFS_F_ERRED) && + !lfs_pairisnull(file->pair)) { + // update dir entry + lfs_dir_t cwd; + err = lfs_dir_fetch(lfs, &cwd, file->pair); + if (err) { + return err; + } + + lfs_entry_t entry = {.off = file->poff}; + err = lfs_bd_read(lfs, cwd.pair[0], entry.off, + &entry.d, sizeof(entry.d)); + lfs_entry_fromle32(&entry.d); + if (err) { + return err; + } + + LFS_ASSERT(entry.d.type == LFS_TYPE_REG); + uint8_t attribute[ATTRIBUTE_LEN]; + entry.d.u.file.head = file->head; + entry.d.u.file.size = file->size; + entry.d.alen = lfs_dir_compute_attribute(attribute); + + err = lfs_dir_update(lfs, &cwd, &entry, NULL, attribute); + if (err) { + return err; + } + + file->flags &= ~LFS_F_DIRTY; + } + + return 0; +} + +lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, + void *buffer, lfs_size_t size) { + uint8_t *data = buffer; + lfs_size_t nsize = size; + + if ((file->flags & 3) == LFS_O_WRONLY) { + return LFS_ERR_BADF; + } + + if (file->flags & LFS_F_WRITING) { + // flush out any writes + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + } + + if (file->pos >= file->size) { + // eof if past end + return 0; + } + + size = lfs_min(size, file->size - file->pos); + nsize = size; + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS_F_READING) || + file->off == lfs->cfg->block_size) { + int err = lfs_ctz_find(lfs, &file->cache, NULL, + file->head, file->size, + file->pos, &file->block, &file->off); + if (err) { + return err; + } + + file->flags |= LFS_F_READING; + } + + // read as much as we can in current block + lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); + int err = lfs_cache_read(lfs, &file->cache, NULL, + file->block, file->off, data, diff); + if (err) { + return err; + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + } + + return size; +} + +lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, + const void *buffer, lfs_size_t size) { + const uint8_t *data = buffer; + lfs_size_t nsize = size; + + if ((file->flags & 3) == LFS_O_RDONLY) { + return LFS_ERR_BADF; + } + + if (file->flags & LFS_F_READING) { + // drop any reads + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + } + + if ((file->flags & LFS_O_APPEND) && file->pos < file->size) { + file->pos = file->size; + } + + if (!(file->flags & LFS_F_WRITING) && file->pos > file->size) { + // fill with zeros + lfs_off_t pos = file->pos; + file->pos = file->size; + + while (file->pos < pos) { + lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1); + if (res < 0) { + return res; + } + } + } + + while (nsize > 0) { + // check if we need a new block + if (!(file->flags & LFS_F_WRITING) || + file->off == lfs->cfg->block_size) { + if (!(file->flags & LFS_F_WRITING) && file->pos > 0) { + // find out which block we're extending from + int err = lfs_ctz_find(lfs, &file->cache, NULL, + file->head, file->size, + file->pos-1, &file->block, &file->off); + if (err) { + file->flags |= LFS_F_ERRED; + return err; + } + + // mark cache as dirty since we may have read data into it + file->cache.block = 0xffffffff; + } + + // extend file with new blocks + lfs_alloc_ack(lfs); + int err = lfs_ctz_extend(lfs, &lfs->rcache, &file->cache, + file->block, file->pos, + &file->block, &file->off); + if (err) { + file->flags |= LFS_F_ERRED; + return err; + } + + file->flags |= LFS_F_WRITING; + } + + // program as much as we can in current block + lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off); + while (true) { + int err = lfs_cache_prog(lfs, &file->cache, &lfs->rcache, + file->block, file->off, data, diff); + if (err) { + if (err == LFS_ERR_CORRUPT) { + goto relocate; + } + file->flags |= LFS_F_ERRED; + return err; + } + + break; +relocate: + err = lfs_file_relocate(lfs, file); + if (err) { + file->flags |= LFS_F_ERRED; + return err; + } + } + + file->pos += diff; + file->off += diff; + data += diff; + nsize -= diff; + + lfs_alloc_ack(lfs); + } + + file->flags &= ~LFS_F_ERRED; + return size; +} + +lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, + lfs_soff_t off, int whence) { + // write out everything beforehand, may be noop if rdonly + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + + // update pos + if (whence == LFS_SEEK_SET) { + file->pos = off; + } else if (whence == LFS_SEEK_CUR) { + if (off < 0 && (lfs_off_t)-off > file->pos) { + return LFS_ERR_INVAL; + } + + file->pos = file->pos + off; + } else if (whence == LFS_SEEK_END) { + if (off < 0 && (lfs_off_t)-off > file->size) { + return LFS_ERR_INVAL; + } + + file->pos = file->size + off; + } + + return file->pos; +} + +int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) { + if ((file->flags & 3) == LFS_O_RDONLY) { + return LFS_ERR_BADF; + } + + lfs_off_t oldsize = lfs_file_size(lfs, file); + if (size < oldsize) { + // need to flush since directly changing metadata + int err = lfs_file_flush(lfs, file); + if (err) { + return err; + } + + // lookup new head in ctz skip list + err = lfs_ctz_find(lfs, &file->cache, NULL, + file->head, file->size, + size, &file->head, &(lfs_off_t){0}); + if (err) { + return err; + } + + file->size = size; + file->flags |= LFS_F_DIRTY; + } else if (size > oldsize) { + lfs_off_t pos = file->pos; + + // flush+seek if not already at end + if (file->pos != oldsize) { + int err = lfs_file_seek(lfs, file, 0, LFS_SEEK_END); + if (err < 0) { + return err; + } + } + + // fill with zeros + while (file->pos < size) { + lfs_ssize_t res = lfs_file_write(lfs, file, &(uint8_t){0}, 1); + if (res < 0) { + return res; + } + } + + // restore pos + int err = lfs_file_seek(lfs, file, pos, LFS_SEEK_SET); + if (err < 0) { + return err; + } + } + + return 0; +} + +lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) { + (void)lfs; + return file->pos; +} + +int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) { + lfs_soff_t res = lfs_file_seek(lfs, file, 0, LFS_SEEK_SET); + if (res < 0) { + return res; + } + + return 0; +} + +lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) { + (void)lfs; + if (file->flags & LFS_F_WRITING) { + return lfs_max(file->pos, file->size); + } else { + return file->size; + } +} + + +/// General fs operations /// + +//----------------------------------------------------------------- +int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err) { + return err; + } + + memset(info, 0, sizeof(*info)); + info->type = entry.d.type; + if (info->type == LFS_TYPE_REG) { + info->size = entry.d.u.file.size; + } + + if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { + strcpy(info->name, "/"); + } else { + err = lfs_bd_read(lfs, cwd.pair[0], + entry.off + 4+entry.d.elen+entry.d.alen, + info->name, entry.d.nlen); + if (err) { + return err; + } + } + if (entry.d.alen > 0){ + err = lfs_dir_extract_attribute(lfs, &cwd, &entry, info); + } + return 0; +} + +int lfs_remove(lfs_t *lfs, const char *path) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t entry; + err = lfs_dir_find(lfs, &cwd, &entry, &path); + if (err) { + return err; + } + + lfs_dir_t dir; + if (entry.d.type == LFS_TYPE_DIR) { + // must be empty before removal, checking size + // without masking top bit checks for any case where + // dir is not empty + err = lfs_dir_fetch(lfs, &dir, entry.d.u.dir); + if (err) { + return err; + } else if (dir.d.size != sizeof(dir.d)+4) { + return LFS_ERR_NOTEMPTY; + } + } + + // remove the entry + err = lfs_dir_remove(lfs, &cwd, &entry); + if (err) { + return err; + } + + // if we were a directory, find pred, replace tail + if (entry.d.type == LFS_TYPE_DIR) { + int res = lfs_pred(lfs, dir.pair, &cwd); + if (res < 0) { + return res; + } + + LFS_ASSERT(res); // must have pred + cwd.d.tail[0] = dir.d.tail[0]; + cwd.d.tail[1] = dir.d.tail[1]; + + err = lfs_dir_commit(lfs, &cwd, NULL, 0); + if (err) { + return err; + } + } + + return 0; +} + +//-------------------------------------------------------------------- +int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { + // deorphan if we haven't yet, needed at most once after poweron + if (!lfs->deorphaned) { + int err = lfs_deorphan(lfs); + if (err) { + return err; + } + } + + // find old entry + lfs_dir_t oldcwd; + int err = lfs_dir_fetch(lfs, &oldcwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t oldentry; + err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath); + if (err) { + return err; + } + + // allocate new entry + lfs_dir_t newcwd; + err = lfs_dir_fetch(lfs, &newcwd, lfs->root); + if (err) { + return err; + } + + lfs_entry_t preventry; + err = lfs_dir_find(lfs, &newcwd, &preventry, &newpath); + if (err && (err != LFS_ERR_NOENT || strchr(newpath, '/') != NULL)) { + return err; + } + + bool prevexists = (err != LFS_ERR_NOENT); + bool samepair = (lfs_paircmp(oldcwd.pair, newcwd.pair) == 0); + + // must have same type + if (prevexists && preventry.d.type != oldentry.d.type) { + return LFS_ERR_ISDIR; + } + + lfs_dir_t dir; + if (prevexists && preventry.d.type == LFS_TYPE_DIR) { + // must be empty before removal, checking size + // without masking top bit checks for any case where + // dir is not empty + err = lfs_dir_fetch(lfs, &dir, preventry.d.u.dir); + if (err) { + return err; + } else if (dir.d.size != sizeof(dir.d)+4) { + return LFS_ERR_NOTEMPTY; + } + } + + // mark as moving + oldentry.d.type |= 0x80; + err = lfs_dir_update(lfs, &oldcwd, &oldentry, NULL, NULL); + if (err) { + return err; + } + + // update pair if newcwd == oldcwd + if (samepair) { + newcwd = oldcwd; + } + + // move to new location + uint8_t attribute[ATTRIBUTE_LEN]; + lfs_entry_t newentry = preventry; + newentry.d = oldentry.d; + newentry.d.type &= ~0x80; + newentry.d.nlen = strlen(newpath); + newentry.d.alen = lfs_dir_compute_attribute(attribute); + + if (prevexists) { + err = lfs_dir_update(lfs, &newcwd, &newentry, newpath, attribute); + if (err) { + return err; + } + } else { + err = lfs_dir_append(lfs, &newcwd, &newentry, newpath, attribute); + if (err) { + return err; + } + } + + // update pair if newcwd == oldcwd + if (samepair) { + oldcwd = newcwd; + } + + // remove old entry + err = lfs_dir_remove(lfs, &oldcwd, &oldentry); + if (err) { + return err; + } + + // if we were a directory, find pred, replace tail + if (prevexists && preventry.d.type == LFS_TYPE_DIR) { + int res = lfs_pred(lfs, dir.pair, &newcwd); + if (res < 0) { + return res; + } + + LFS_ASSERT(res); // must have pred + newcwd.d.tail[0] = dir.d.tail[0]; + newcwd.d.tail[1] = dir.d.tail[1]; + + err = lfs_dir_commit(lfs, &newcwd, NULL, 0); + if (err) { + return err; + } + } + + return 0; +} + + +/// Filesystem operations /// +static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { + lfs->cfg = cfg; + + // setup read cache + lfs->rcache.block = 0xffffffff; + if (lfs->cfg->read_buffer) { + lfs->rcache.buffer = lfs->cfg->read_buffer; + } else { + lfs->rcache.buffer = lfs_malloc(lfs->cfg->read_size); + if (!lfs->rcache.buffer) { + return LFS_ERR_NOMEM; + } + } + + // setup program cache + lfs->pcache.block = 0xffffffff; + if (lfs->cfg->prog_buffer) { + lfs->pcache.buffer = lfs->cfg->prog_buffer; + } else { + lfs->pcache.buffer = lfs_malloc(lfs->cfg->prog_size); + if (!lfs->pcache.buffer) { + return LFS_ERR_NOMEM; + } + } + + // setup lookahead, round down to nearest 32-bits + LFS_ASSERT(lfs->cfg->lookahead % 32 == 0); + LFS_ASSERT(lfs->cfg->lookahead > 0); + if (lfs->cfg->lookahead_buffer) { + lfs->free.buffer = lfs->cfg->lookahead_buffer; + } else { + lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8); + if (!lfs->free.buffer) { + return LFS_ERR_NOMEM; + } + } + + // check that program and read sizes are multiples of the block size + LFS_ASSERT(lfs->cfg->prog_size % lfs->cfg->read_size == 0); + LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->prog_size == 0); + + // check that the block size is large enough to fit ctz pointers + LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) + <= lfs->cfg->block_size); + + // setup default state + lfs->root[0] = 0xffffffff; + lfs->root[1] = 0xffffffff; + lfs->files = NULL; + lfs->dirs = NULL; + lfs->deorphaned = false; + + return 0; +} + +static int lfs_deinit(lfs_t *lfs) { + // free allocated memory + if (!lfs->cfg->read_buffer) { + lfs_free(lfs->rcache.buffer); + } + + if (!lfs->cfg->prog_buffer) { + lfs_free(lfs->pcache.buffer); + } + + if (!lfs->cfg->lookahead_buffer) { + lfs_free(lfs->free.buffer); + } + + return 0; +} + +int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { + int err = lfs_init(lfs, cfg); + if (err) { + return err; + } + + // create free lookahead + memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); + lfs->free.begin = 0; + lfs->free.size = lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count); + lfs->free.off = 0; + lfs_alloc_ack(lfs); + + // create superblock dir + lfs_dir_t superdir; + err = lfs_dir_alloc(lfs, &superdir); + if (err) { + return err; + } + + // write root directory + lfs_dir_t root; + err = lfs_dir_alloc(lfs, &root); + if (err) { + return err; + } + + err = lfs_dir_commit(lfs, &root, NULL, 0); + if (err) { + return err; + } + + lfs->root[0] = root.pair[0]; + lfs->root[1] = root.pair[1]; + + // write superblocks + lfs_superblock_t superblock = { + .off = sizeof(superdir.d), + .d.type = LFS_TYPE_SUPERBLOCK, + .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, + .d.nlen = sizeof(superblock.d.magic), + .d.version = LFS_DISK_VERSION, + .d.magic = {"littlefs"}, + .d.block_size = lfs->cfg->block_size, + .d.block_count = lfs->cfg->block_count, + .d.root = {lfs->root[0], lfs->root[1]}, + }; + superdir.d.tail[0] = root.pair[0]; + superdir.d.tail[1] = root.pair[1]; + superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4; + + // write both pairs to be safe + lfs_superblock_tole32(&superblock.d); + bool valid = false; + for (int i = 0; i < 2; i++) { + err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){ + {sizeof(superdir.d), sizeof(superblock.d), + &superblock.d, sizeof(superblock.d)} + }, 1); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + + valid = valid || !err; + } + + if (!valid) { + return LFS_ERR_CORRUPT; + } + + // sanity check that fetch works + err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1}); + if (err) { + return err; + } + + lfs_alloc_ack(lfs); + return lfs_deinit(lfs); +} + +//----------------------------- +void lfs_setup_free(lfs_t *lfs) +{ + // setup free lookahead + memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8); + lfs->free.begin = 0; + lfs->free.size = 0; + lfs->free.off = 0; + lfs_alloc_ack(lfs); +} + +//------------------------------------------------------- +int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { + int err = lfs_init(lfs, cfg); + if (err) { + return err; + } + + lfs_setup_free(lfs); + + // load superblock + lfs_dir_t dir; + lfs_superblock_t superblock; + err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); + if (err && err != LFS_ERR_CORRUPT) { + LFS_ERROR("Error fetching superblock at %d %d", 0, 1); + return err; + } + + if (!err) { + err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d), + &superblock.d, sizeof(superblock.d)); + lfs_superblock_fromle32(&superblock.d); + if (err) { + LFS_ERROR("Error reading superblock at %d %d", 0, 1); + return err; + } + + lfs->root[0] = superblock.d.root[0]; + lfs->root[1] = superblock.d.root[1]; + } + + if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) { + LFS_ERROR("Invalid superblock magic at %d %d", 0, 1); + return LFS_ERR_CORRUPT; + } + + uint16_t major_version = (0xffff & (superblock.d.version >> 16)); + uint16_t minor_version = (0xffff & (superblock.d.version >> 0)); + if ((major_version != LFS_DISK_VERSION_MAJOR || + minor_version != LFS_DISK_VERSION_MINOR)) { + LFS_ERROR("Invalid disk version %d.%d, expected %d.%d", major_version, minor_version, LFS_DISK_VERSION_MAJOR, LFS_DISK_VERSION_MINOR); + return LFS_ERR_INVAL; + } + + if (superblock.d.block_size != cfg->block_size) { + LFS_ERROR("Block size not matched [%u <> %u]", cfg->block_size, superblock.d.block_size); + return LFS_ERR_INVAL; + } + if (superblock.d.block_count != cfg->block_count) { + if (superblock.d.block_count < cfg->block_count) { + LFS_ERROR("Block count not matched [%u (configured) > %u (on disk)]", cfg->block_count, superblock.d.block_count); + return LFS_ERR_INVAL; + } + LFS_WARN("Block count not matched [%u (configured) <> %u (on disk)]", cfg->block_count, superblock.d.block_count); + // Adjust superblock block count + superblock.d.block_count = cfg->block_count; + // write both pairs to be safe + lfs_superblock_tole32(&superblock.d); + bool valid = false; + for (int i = 0; i < 2; i++) { + err = lfs_dir_commit(lfs, &dir, (struct lfs_region[]){ + {sizeof(dir.d), sizeof(superblock.d), + &superblock.d, sizeof(superblock.d)} + }, 1); + if (err && err != LFS_ERR_CORRUPT) { + return err; + } + + valid = valid || !err; + } + + if (!valid) { + return LFS_ERR_CORRUPT; + } + LFS_WARN("Block count adjusted to %u", cfg->block_count); + } + + return 0; +} + +int lfs_unmount(lfs_t *lfs) { + return lfs_deinit(lfs); +} + + +/// Littlefs specific operations /// +int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + // iterate over metadata pairs + lfs_dir_t dir; + lfs_entry_t entry; + lfs_block_t cwd[2] = {0, 1}; + + while (true) { + for (int i = 0; i < 2; i++) { + int err = cb(data, cwd[i]); + if (err) { + return err; + } + } + + int err = lfs_dir_fetch(lfs, &dir, cwd); + if (err) { + return err; + } + + // iterate over contents + while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { + err = lfs_bd_read(lfs, dir.pair[0], dir.off, + &entry.d, sizeof(entry.d)); + lfs_entry_fromle32(&entry.d); + if (err) { + return err; + } + + dir.off += lfs_entry_size(&entry); + if ((0x70 & entry.d.type) == (0x70 & LFS_TYPE_REG)) { + err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL, + entry.d.u.file.head, entry.d.u.file.size, cb, data); + if (err) { + return err; + } + } + } + + cwd[0] = dir.d.tail[0]; + cwd[1] = dir.d.tail[1]; + + if (lfs_pairisnull(cwd)) { + break; + } + } + + // iterate over any open files + for (lfs_file_t *f = lfs->files; f; f = f->next) { + if (f->flags & LFS_F_DIRTY) { + int err = lfs_ctz_traverse(lfs, &lfs->rcache, &f->cache, + f->head, f->size, cb, data); + if (err) { + return err; + } + } + + if (f->flags & LFS_F_WRITING) { + int err = lfs_ctz_traverse(lfs, &lfs->rcache, &f->cache, + f->block, f->pos, cb, data); + if (err) { + return err; + } + } + } + + return 0; +} + +static int lfs_pred(lfs_t *lfs, const lfs_block_t dir[2], lfs_dir_t *pdir) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + // iterate over all directory directory entries + int err = lfs_dir_fetch(lfs, pdir, (const lfs_block_t[2]){0, 1}); + if (err) { + return err; + } + + while (!lfs_pairisnull(pdir->d.tail)) { + if (lfs_paircmp(pdir->d.tail, dir) == 0) { + return true; + } + + err = lfs_dir_fetch(lfs, pdir, pdir->d.tail); + if (err) { + return err; + } + } + + return false; +} + +static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2], + lfs_dir_t *parent, lfs_entry_t *entry) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + parent->d.tail[0] = 0; + parent->d.tail[1] = 1; + + // iterate over all directory directory entries + while (!lfs_pairisnull(parent->d.tail)) { + int err = lfs_dir_fetch(lfs, parent, parent->d.tail); + if (err) { + return err; + } + + while (true) { + err = lfs_dir_next(lfs, parent, entry); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + if (err == LFS_ERR_NOENT) { + break; + } + + if (((0x70 & entry->d.type) == (0x70 & LFS_TYPE_DIR)) && + lfs_paircmp(entry->d.u.dir, dir) == 0) { + return true; + } + } + } + + return false; +} + +static int lfs_moved(lfs_t *lfs, const void *e) { + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + // skip superblock + lfs_dir_t cwd; + int err = lfs_dir_fetch(lfs, &cwd, (const lfs_block_t[2]){0, 1}); + if (err) { + return err; + } + + // iterate over all directory directory entries + lfs_entry_t entry; + while (!lfs_pairisnull(cwd.d.tail)) { + err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail); + if (err) { + return err; + } + + while (true) { + err = lfs_dir_next(lfs, &cwd, &entry); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + if (err == LFS_ERR_NOENT) { + break; + } + + if (!(0x80 & entry.d.type) && + memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) { + return true; + } + } + } + + return false; +} + +//----------------------------------------------------------------------------------------------- +static int lfs_relocate(lfs_t *lfs, const lfs_block_t oldpair[2], const lfs_block_t newpair[2]) { + // find parent + lfs_dir_t parent; + lfs_entry_t entry; + int res = lfs_parent(lfs, oldpair, &parent, &entry); + if (res < 0) { + return res; + } + + if (res) { + // update disk, this creates a desync + entry.d.u.dir[0] = newpair[0]; + entry.d.u.dir[1] = newpair[1]; + + int err = lfs_dir_update(lfs, &parent, &entry, NULL, NULL); + if (err) { + return err; + } + + // update internal root + if (lfs_paircmp(oldpair, lfs->root) == 0) { + LFS_DEBUG("Relocating root %d %d", newpair[0], newpair[1]); + lfs->root[0] = newpair[0]; + lfs->root[1] = newpair[1]; + } + + // clean up bad block, which should now be a desync + return lfs_deorphan(lfs); + } + + // find pred + res = lfs_pred(lfs, oldpair, &parent); + if (res < 0) { + return res; + } + + if (res) { + // just replace bad pair, no desync can occur + parent.d.tail[0] = newpair[0]; + parent.d.tail[1] = newpair[1]; + + return lfs_dir_commit(lfs, &parent, NULL, 0); + } + + // couldn't find dir, must be new + return 0; +} + +int lfs_deorphan(lfs_t *lfs) { + lfs->deorphaned = true; + + if (lfs_pairisnull(lfs->root)) { + return 0; + } + + lfs_dir_t pdir = {.d.size = 0x80000000}; + lfs_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1}; + + // iterate over all directory directory entries + while (!lfs_pairisnull(cwd.d.tail)) { + int err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail); + if (err) { + return err; + } + + // check head blocks for orphans + if (!(0x80000000 & pdir.d.size)) { + // check if we have a parent + lfs_dir_t parent; + lfs_entry_t entry; + int res = lfs_parent(lfs, pdir.d.tail, &parent, &entry); + if (res < 0) { + return res; + } + + if (!res) { + // we are an orphan + LFS_DEBUG("Found orphan %d %d", + pdir.d.tail[0], pdir.d.tail[1]); + + pdir.d.tail[0] = cwd.d.tail[0]; + pdir.d.tail[1] = cwd.d.tail[1]; + + err = lfs_dir_commit(lfs, &pdir, NULL, 0); + if (err) { + return err; + } + + break; + } + + if (!lfs_pairsync(entry.d.u.dir, pdir.d.tail)) { + // we have desynced + LFS_DEBUG("Found desync %d %d", + entry.d.u.dir[0], entry.d.u.dir[1]); + + pdir.d.tail[0] = entry.d.u.dir[0]; + pdir.d.tail[1] = entry.d.u.dir[1]; + + err = lfs_dir_commit(lfs, &pdir, NULL, 0); + if (err) { + return err; + } + + break; + } + } + + // check entries for moves + lfs_entry_t entry; + while (true) { + err = lfs_dir_next(lfs, &cwd, &entry); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + if (err == LFS_ERR_NOENT) { + break; + } + + // found moved entry + if (entry.d.type & 0x80) { + int moved = lfs_moved(lfs, &entry.d.u); + if (moved < 0) { + return moved; + } + + if (moved) { + LFS_DEBUG("Found move %d %d", + entry.d.u.dir[0], entry.d.u.dir[1]); + err = lfs_dir_remove(lfs, &cwd, &entry); + if (err) { + return err; + } + } else { + LFS_DEBUG("Found partial move %d %d", + entry.d.u.dir[0], entry.d.u.dir[1]); + entry.d.type &= ~0x80; + err = lfs_dir_update(lfs, &cwd, &entry, NULL, NULL); + if (err) { + return err; + } + } + } + } + + memcpy(&pdir, &cwd, sizeof(pdir)); + } + + return 0; +} + +// ==== Attributes support ============================== + +//------------------------------------------------------ +static uint8_t lfs_dir_compute_attribute(uint8_t *buf) { + time_t now = time(NULL); + buf[0] = LFS_ATTRIBUTE_TIME; + buf[1] = now & 0xFF; + buf[2] = (now >> 8) & 0xFF; + buf[3] = (now >> 16) & 0xFF; + buf[4] = (now >> 24) & 0xFF; + + //LFS_DEBUG("compute attribute: time = %ld", now); + return ATTRIBUTE_LEN; +} + +//----------------------------------------------------------------------------------------------------------- +static int lfs_dir_extract_attribute(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry, struct lfs_info *info) { + + uint8_t *attribute = lfs_malloc(entry->d.alen); + LFS_ASSERT(attribute); + if (attribute) { + int err = lfs_bd_read(lfs, dir->pair[0], + entry->off + 4 + entry->d.elen, + attribute, entry->d.alen); + if (err) { + lfs_free(attribute); + return err; + } + + // TODO search inside the attributes + if (entry->d.alen >= ATTRIBUTE_LEN) { + if (attribute[0] == LFS_ATTRIBUTE_TIME) { + info->time = + attribute[1] + attribute[2] * 256 + attribute[3] * 256 * 256 + attribute[4] * 256 * 256 * 256; + } + } + //LFS_DEBUG("extract attribute: alen = %u, time = %d", entry->d.alen, info->time); + lfs_free(attribute); + } + + return 0; +} + + diff --git a/MicroPython_BUILD/components/mklittlefs/littlefs/lfs.h b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs.h new file mode 100644 index 00000000..a743c9a2 --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs.h @@ -0,0 +1,491 @@ +/* + * The little filesystem + * + * Copyright (c) 2017 ARM Limited + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LFS_H +#define LFS_H + +#include +#include + + +/// Version info /// + +// Software library version +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS_VERSION 0x00010004 +#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16)) +#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0)) + +// Version of On-disk data structures +// Major (top-nibble), incremented on backwards incompatible changes +// Minor (bottom-nibble), incremented on feature additions +#define LFS_DISK_VERSION 0x00010002 +#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16)) +#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0)) + + +/// Definitions /// + +// Type definitions +typedef uint32_t lfs_size_t; +typedef uint32_t lfs_off_t; + +typedef int32_t lfs_ssize_t; +typedef int32_t lfs_soff_t; + +typedef uint32_t lfs_block_t; + +typedef uint32_t lfs_time_t; + +// Max name size in bytes +#ifndef LFS_NAME_MAX +#define LFS_NAME_MAX 255 +#endif + +// Possible error codes, these are negative to allow +// valid positive return values +enum lfs_error { + LFS_ERR_OK = 0, // No error + LFS_ERR_IO = -5, // Error during device operation + LFS_ERR_CORRUPT = -52, // Corrupted + LFS_ERR_NOENT = -2, // No directory entry + LFS_ERR_EXIST = -17, // Entry already exists + LFS_ERR_NOTDIR = -20, // Entry is not a dir + LFS_ERR_ISDIR = -21, // Entry is a dir + LFS_ERR_NOTEMPTY = -39, // Dir is not empty + LFS_ERR_BADF = -9, // Bad file number + LFS_ERR_INVAL = -22, // Invalid parameter + LFS_ERR_NOSPC = -28, // No space left on device + LFS_ERR_NOMEM = -12, // No more memory available +}; + +// File types +enum lfs_type { + LFS_TYPE_REG = 0x11, + LFS_TYPE_DIR = 0x22, + LFS_TYPE_SUPERBLOCK = 0x2e, +}; + +// Attribute types +enum lfs_attribute { + LFS_ATTRIBUTE_TIME = 0xC1, +}; + +// File open flags +enum lfs_open_flags { + // open flags + LFS_O_RDONLY = 1, // Open a file as read only + LFS_O_WRONLY = 2, // Open a file as write only + LFS_O_RDWR = 3, // Open a file as read and write + LFS_O_CREAT = 0x0100, // Create a file if it does not exist + LFS_O_EXCL = 0x0200, // Fail if a file already exists + LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size + LFS_O_APPEND = 0x0800, // Move to end of file on every write + + // internally used flags + LFS_F_DIRTY = 0x10000, // File does not match storage + LFS_F_WRITING = 0x20000, // File has been written since last flush + LFS_F_READING = 0x40000, // File has been read since last flush + LFS_F_ERRED = 0x80000, // An error occured during write +}; + +// File seek flags +enum lfs_whence_flags { + LFS_SEEK_SET = 0, // Seek relative to an absolute position + LFS_SEEK_CUR = 1, // Seek relative to the current file position + LFS_SEEK_END = 2, // Seek relative to the end of the file +}; + + +// Configuration provided during initialization of the littlefs +struct lfs_config { + // Opaque user provided context that can be used to pass + // information to the block device operations + void *context; + + // Read a region in a block. Negative error codes are propogated + // to the user. + int (*read)(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, void *buffer, lfs_size_t size); + + // Program a region in a block. The block must have previously + // been erased. Negative error codes are propogated to the user. + // May return LFS_ERR_CORRUPT if the block should be considered bad. + int (*prog)(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, const void *buffer, lfs_size_t size); + + // Erase a block. A block must be erased before being programmed. + // The state of an erased block is undefined. Negative error codes + // are propogated to the user. + // May return LFS_ERR_CORRUPT if the block should be considered bad. + int (*erase)(const struct lfs_config *c, lfs_block_t block); + + // Sync the state of the underlying block device. Negative error codes + // are propogated to the user. + int (*sync)(const struct lfs_config *c); + + // Minimum size of a block read. This determines the size of read buffers. + // This may be larger than the physical read size to improve performance + // by caching more of the block device. + lfs_size_t read_size; + + // Minimum size of a block program. This determines the size of program + // buffers. This may be larger than the physical program size to improve + // performance by caching more of the block device. + // Must be a multiple of the read size. + lfs_size_t prog_size; + + // Size of an erasable block. This does not impact ram consumption and + // may be larger than the physical erase size. However, this should be + // kept small as each file currently takes up an entire block. + // Must be a multiple of the program size. + lfs_size_t block_size; + + // Number of erasable blocks on the device. + lfs_size_t block_count; + + // Number of blocks to lookahead during block allocation. A larger + // lookahead reduces the number of passes required to allocate a block. + // The lookahead buffer requires only 1 bit per block so it can be quite + // large with little ram impact. Should be a multiple of 32. + lfs_size_t lookahead; + + // Optional, statically allocated read buffer. Must be read sized. + void *read_buffer; + + // Optional, statically allocated program buffer. Must be program sized. + void *prog_buffer; + + // Optional, statically allocated lookahead buffer. Must be 1 bit per + // lookahead block. + void *lookahead_buffer; + + // Optional, statically allocated buffer for files. Must be program sized. + // If enabled, only one file may be opened at a time. + void *file_buffer; +}; + + +// File info structure +struct lfs_info { + // Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR + uint8_t type; + + // Size of the file, only valid for REG files + lfs_size_t size; + + // Name of the file stored as a null-terminated string + char name[LFS_NAME_MAX+1]; + + lfs_time_t time; +}; + + +/// littlefs data structures /// +typedef struct lfs_entry { + lfs_off_t off; + + struct lfs_disk_entry { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + union { + struct { + lfs_block_t head; + lfs_size_t size; + } file; + lfs_block_t dir[2]; + } u; + } d; +} lfs_entry_t; + +typedef struct lfs_cache { + lfs_block_t block; + lfs_off_t off; + uint8_t *buffer; +} lfs_cache_t; + +typedef struct lfs_file { + struct lfs_file *next; + lfs_block_t pair[2]; + lfs_off_t poff; + + lfs_block_t head; + lfs_size_t size; + + uint32_t flags; + lfs_off_t pos; + lfs_block_t block; + lfs_off_t off; + lfs_cache_t cache; +} lfs_file_t; + +typedef struct lfs_dir { + struct lfs_dir *next; + lfs_block_t pair[2]; + lfs_off_t off; + + lfs_block_t head[2]; + lfs_off_t pos; + + struct lfs_disk_dir { + uint32_t rev; + lfs_size_t size; + lfs_block_t tail[2]; + } d; +} lfs_dir_t; + +typedef struct lfs_superblock { + lfs_off_t off; + + struct lfs_disk_superblock { + uint8_t type; + uint8_t elen; + uint8_t alen; + uint8_t nlen; + lfs_block_t root[2]; + uint32_t block_size; + uint32_t block_count; + uint32_t version; + char magic[8]; + } d; +} lfs_superblock_t; + +typedef struct lfs_free { + lfs_block_t begin; + lfs_block_t size; + lfs_block_t off; + lfs_block_t ack; + uint32_t *buffer; +} lfs_free_t; + +// The littlefs type +typedef struct lfs { + const struct lfs_config *cfg; + + lfs_block_t root[2]; + lfs_file_t *files; + lfs_dir_t *dirs; + + lfs_cache_t rcache; + lfs_cache_t pcache; + + lfs_free_t free; + bool deorphaned; +} lfs_t; + + +/// Filesystem functions /// + +// Format a block device with the littlefs +// +// Requires a littlefs object and config struct. This clobbers the littlefs +// object, and does not leave the filesystem mounted. +// +// Returns a negative error code on failure. +int lfs_format(lfs_t *lfs, const struct lfs_config *config); + +// Mounts a littlefs +// +// Requires a littlefs object and config struct. Multiple filesystems +// may be mounted simultaneously with multiple littlefs objects. Both +// lfs and config must be allocated while mounted. +// +// Returns a negative error code on failure. +int lfs_mount(lfs_t *lfs, const struct lfs_config *config); + +// Unmounts a littlefs +// +// Does nothing besides releasing any allocated resources. +// Returns a negative error code on failure. +int lfs_unmount(lfs_t *lfs); + +/// General operations /// + +// Removes a file or directory +// +// If removing a directory, the directory must be empty. +// Returns a negative error code on failure. +int lfs_remove(lfs_t *lfs, const char *path); + +// Rename or move a file or directory +// +// If the destination exists, it must match the source in type. +// If the destination is a directory, the directory must be empty. +// +// Note: If power loss occurs, it is possible that the file or directory +// will exist in both the oldpath and newpath simultaneously after the +// next mount. +// +// Returns a negative error code on failure. +int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath); + +// Find info about a file or directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a negative error code on failure. +int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info); + + +/// File operations /// + +// Open a file +// +// The mode that the file is opened in is determined +// by the flags, which are values from the enum lfs_open_flags +// that are bitwise-ored together. +// +// Returns a negative error code on failure. +int lfs_file_open(lfs_t *lfs, lfs_file_t *file, + const char *path, int flags); + +// Close a file +// +// Any pending writes are written out to storage as though +// sync had been called and releases any allocated resources. +// +// Returns a negative error code on failure. +int lfs_file_close(lfs_t *lfs, lfs_file_t *file); + +// Synchronize a file on storage +// +// Any pending writes are written out to storage. +// Returns a negative error code on failure. +int lfs_file_sync(lfs_t *lfs, lfs_file_t *file); + +// Read data from file +// +// Takes a buffer and size indicating where to store the read data. +// Returns the number of bytes read, or a negative error code on failure. +lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, + void *buffer, lfs_size_t size); + +// Write data to file +// +// Takes a buffer and size indicating the data to write. The file will not +// actually be updated on the storage until either sync or close is called. +// +// Returns the number of bytes written, or a negative error code on failure. +lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, + const void *buffer, lfs_size_t size); + +// Change the position of the file +// +// The change in position is determined by the offset and whence flag. +// Returns the old position of the file, or a negative error code on failure. +lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, + lfs_soff_t off, int whence); + +// Truncates the size of the file to the specified size +// +// Returns a negative error code on failure. +int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size); + +// Return the position of the file +// +// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR) +// Returns the position of the file, or a negative error code on failure. +lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file); + +// Change the position of the file to the beginning of the file +// +// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR) +// Returns a negative error code on failure. +int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file); + +// Return the size of the file +// +// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END) +// Returns the size of the file, or a negative error code on failure. +lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file); + + +/// Directory operations /// + +// Create a directory +// +// Returns a negative error code on failure. +int lfs_mkdir(lfs_t *lfs, const char *path); + +// Open a directory +// +// Once open a directory can be used with read to iterate over files. +// Returns a negative error code on failure. +int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path); + +// Close a directory +// +// Releases any allocated resources. +// Returns a negative error code on failure. +int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir); + +// Read an entry in the directory +// +// Fills out the info structure, based on the specified file or directory. +// Returns a negative error code on failure. +int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info); + +// Change the position of the directory +// +// The new off must be a value previous returned from tell and specifies +// an absolute offset in the directory seek. +// +// Returns a negative error code on failure. +int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off); + +// Return the position of the directory +// +// The returned offset is only meant to be consumed by seek and may not make +// sense, but does indicate the current position in the directory iteration. +// +// Returns the position of the directory, or a negative error code on failure. +lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir); + +// Change the position of the directory to the beginning of the directory +// +// Returns a negative error code on failure. +int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir); + + +/// Miscellaneous littlefs specific operations /// + +// Traverse through all blocks in use by the filesystem +// +// The provided callback will be called with each block address that is +// currently in use by the filesystem. This can be used to determine which +// blocks are in use or how much of the storage is available. +// +// Returns a negative error code on failure. +int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); + +// Prunes any recoverable errors that may have occured in the filesystem +// +// Not needed to be called by user unless an operation is interrupted +// but the filesystem is still mounted. This is already called on first +// allocation. +// +// Returns a negative error code on failure. +int lfs_deorphan(lfs_t *lfs); + + +void lfs_setup_free(lfs_t *lfs); +int lfs_alloc(lfs_t *lfs, lfs_block_t *block); + +#endif diff --git a/MicroPython_BUILD/components/mklittlefs/littlefs/lfs_util.c b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs_util.c new file mode 100644 index 00000000..3a2a351b --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs_util.c @@ -0,0 +1,42 @@ +/* + * lfs util functions + * + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "lfs_util.h" + +// Only compile if user does not provide custom config +#ifndef LFS_CONFIG + + +// Software CRC implementation with small lookup table +void lfs_crc(uint32_t *restrict crc, const void *buffer, size_t size) { + static const uint32_t rtable[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c, + }; + + const uint8_t *data = buffer; + + for (size_t i = 0; i < size; i++) { + *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf]; + *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf]; + } +} + + +#endif diff --git a/MicroPython_BUILD/components/mklittlefs/littlefs/lfs_util.h b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs_util.h new file mode 100644 index 00000000..f310f9a7 --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/littlefs/lfs_util.h @@ -0,0 +1,181 @@ +/* + * lfs utility functions + * + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LFS_UTIL_H +#define LFS_UTIL_H + +// Users can override lfs_util.h with their own configuration by defining +// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h). +// +// If LFS_CONFIG is used, none of the default utils will be emitted and must be +// provided by the config file. To start I would suggest copying lfs_util.h and +// modifying as needed. +#ifdef LFS_CONFIG +#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) +#define LFS_STRINGIZE2(x) #x +#include LFS_STRINGIZE(LFS_CONFIG) +#else + +// System includes +#include +#include +#include + +#ifndef LFS_NO_MALLOC +#include +#endif +#ifndef LFS_NO_ASSERT +#include +#endif +#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR) +#include +#endif + +// Macros, may be replaced by system specific wrappers. Arguments to these +// macros must not have side-effects as the macros can be removed for a smaller +// code footprint + +// Logging functions +#ifndef LFS_NO_DEBUG +#define LFS_DEBUG(fmt, ...) fprintf(stderr, "lfs debug: " fmt "\n", __VA_ARGS__) +#else +#define LFS_DEBUG(fmt, ...) +#endif + +#ifndef LFS_NO_WARN +#define LFS_WARN(fmt, ...) fprintf(stderr, "lfs warn: " fmt "\n", __VA_ARGS__) +#else +#define LFS_WARN(fmt, ...) +#endif + +#ifndef LFS_NO_ERROR +#define LFS_ERROR(fmt, ...) fprintf(stderr, "lfs error: " fmt "\n", __VA_ARGS__) +#else +#define LFS_ERROR(fmt, ...) +#endif + +// Runtime assertions +#ifndef LFS_NO_ASSERT +#define LFS_ASSERT(test) assert(test) +#else +#define LFS_ASSERT(test) +#endif + + +// Builtin functions, these may be replaced by more efficient +// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more +// expensive basic C implementation for debugging purposes + +// Min/max functions for unsigned 32-bit numbers +static inline uint32_t lfs_max(uint32_t a, uint32_t b) { + return (a > b) ? a : b; +} + +static inline uint32_t lfs_min(uint32_t a, uint32_t b) { + return (a < b) ? a : b; +} + +// Find the next smallest power of 2 less than or equal to a +static inline uint32_t lfs_npw2(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return 32 - __builtin_clz(a-1); +#else + uint32_t r = 0; + uint32_t s; + a -= 1; + s = (a > 0xffff) << 4; a >>= s; r |= s; + s = (a > 0xff ) << 3; a >>= s; r |= s; + s = (a > 0xf ) << 2; a >>= s; r |= s; + s = (a > 0x3 ) << 1; a >>= s; r |= s; + return (r | (a >> 1)) + 1; +#endif +} + +// Count the number of trailing binary zeros in a +// lfs_ctz(0) may be undefined +static inline uint32_t lfs_ctz(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__) + return __builtin_ctz(a); +#else + return lfs_npw2((a & -a) + 1) - 1; +#endif +} + +// Count the number of binary ones in a +static inline uint32_t lfs_popc(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return __builtin_popcount(a); +#else + a = a - ((a >> 1) & 0x55555555); + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); + return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; +#endif +} + +// Find the sequence comparison of a and b, this is the distance +// between a and b ignoring overflow +static inline int lfs_scmp(uint32_t a, uint32_t b) { + return (int)(unsigned)(a - b); +} + +// Convert from 32-bit little-endian to native order +static inline uint32_t lfs_fromle32(uint32_t a) { +#if !defined(LFS_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + return a; +#elif !defined(LFS_NO_INTRINSICS) && ( \ + (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + return __builtin_bswap32(a); +#else + return (((uint8_t*)&a)[0] << 0) | + (((uint8_t*)&a)[1] << 8) | + (((uint8_t*)&a)[2] << 16) | + (((uint8_t*)&a)[3] << 24); +#endif +} + +// Convert to 32-bit little-endian from native order +static inline uint32_t lfs_tole32(uint32_t a) { + return lfs_fromle32(a); +} + +// Calculate CRC-32 with polynomial = 0x04c11db7 +void lfs_crc(uint32_t *crc, const void *buffer, size_t size); + +// Allocate memory, only used if buffers are not provided to littlefs +static inline void *lfs_malloc(size_t size) { +#ifndef LFS_NO_MALLOC + return malloc(size); +#else + return NULL; +#endif +} + +// Deallocate memory, only used if buffers are not provided to littlefs +static inline void lfs_free(void *p) { +#ifndef LFS_NO_MALLOC + free(p); +#endif +} + + +#endif +#endif diff --git a/MicroPython_BUILD/components/mklittlefs/mklfs.c b/MicroPython_BUILD/components/mklittlefs/mklfs.c new file mode 100644 index 00000000..5ceb600a --- /dev/null +++ b/MicroPython_BUILD/components/mklittlefs/mklfs.c @@ -0,0 +1,400 @@ +/* + * Image creator for the littlefs + * + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * Copyright (c) 2018 LoBo (https://github.com/loboris) + * + * The MIT License (MIT) + * + * 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 "lfs.h" +#include "lfs_util.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "wear_levelling.h" + +static struct lfs_config config = {0}; +static lfs_t lfs; +static uint8_t *lfs_image = NULL; + +static uint32_t block_size = 0; +static uint32_t block_count = 0; +static uint32_t lookahead = 32; +static bool use_wl = false; +static char image_name[256] = {0}; +static char image_dir[256] = {0}; +static uint32_t fs_offset = 0; + +static uint32_t *erase_log = NULL; +static uint32_t *prog_log = NULL; +static uint32_t *read_log = NULL; + + +// === Image access functions === + +//------------------------------------------------------------------------------------------------------------- +int lfs_img_read(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) +{ + memcpy((uint8_t *)buffer, lfs_image + fs_offset + ((off_t)block * cfg->block_size) + (off_t)off, (size_t)size); + if (read_log) read_log[block]++; + return 0; +} + +//------------------------------------------------------------------------------------------------------------------- +int lfs_img_prog(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) +{ + memcpy(lfs_image + fs_offset + ((off_t)block * cfg->block_size) + (off_t)off, (uint8_t *)buffer, (size_t)size); + if (size != cfg->block_size) printf("SIZE=%d, BLOCK=%d, OFFSET=%d\r\n", size, block, off); + if (prog_log) prog_log[block]++; + return 0; +} + +//---------------------------------------------------------------- +int lfs_img_erase(const struct lfs_config *cfg, lfs_block_t block) +{ + memset(lfs_image + fs_offset + ((off_t)block * cfg->block_size), 0xFF, cfg->block_size); + if (erase_log) erase_log[block]++; + return 0; +} + +//-------------------------------------------- +int lfs_img_sync(const struct lfs_config *cfg) +{ + // do nothing + return 0; +} + +// === File functions =================== + +//--------------------------------------- +int addFile(char* name, const char* path) +{ + FILE* src = fopen(path, "rb"); + if (!src) { + printf("error: failed to open '%s' for reading\r\n", path); + return 1; + } + + lfs_file_t *file = (lfs_file_t *) malloc(sizeof(lfs_file_t)); + if (file == NULL) { + printf("error: failed to open lfs file '%s' for writting\r\n", name); + return 2; + } + + int lfs_flags = LFS_O_WRONLY | LFS_O_CREAT; + int err = lfs_file_open(&lfs, file, name, lfs_flags); + if (err < 0) + { + free(file); + return 3; + } + + // read file size + fseek(src, 0, SEEK_END); + size_t size = ftell(src); + fseek(src, 0, SEEK_SET); + + size_t left = size; + uint8_t data_byte; + while (left > 0){ + if (1 != fread(&data_byte, 1, 1, src)) { + printf("fread error!\r\n"); + + fclose(src); + lfs_file_close(&lfs, file); + free(file); + return 1; + } + lfs_ssize_t res = lfs_file_write(&lfs, file, &data_byte, 1); + if (res < 0) { + printf("SPIFFS_write error (%d)\r\n", res); + + fclose(src); + lfs_file_close(&lfs, file); + free(file); + return 1; + } + left -= 1; + } + + lfs_file_close(&lfs, file); + free(file); + + return 0; +} + +//-------------------- +int addDir(char* name) +{ + int err = lfs_mkdir(&lfs, name); + return err; +} + +//---------------------------------------------------- +int addFiles(const char* dirname, const char* subPath) +{ + DIR *dir; + struct dirent *ent; + bool error = false; + char dirPath[512] = {0}; + char dirpath[512] = {0}; + char newSubPath[512] = {0}; + char filepath[512] = {0}; + char fullpath[512] = {0}; + + sprintf(dirPath, "%s", dirname); + strcat(dirPath, subPath); + + // Open directory + if ((dir = opendir(dirPath)) != NULL) { + // Read files from directory. + while ((ent = readdir (dir)) != NULL) { + + // Ignore directory itself. + if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) { + continue; + } + + sprintf(fullpath, "%s", dirPath); + strcat(fullpath, ent->d_name); + struct stat path_stat; + stat(fullpath, &path_stat); + + if (!S_ISREG(path_stat.st_mode)) { + // Check if path is a directory. + if (S_ISDIR(path_stat.st_mode)) { + sprintf(dirpath, "%s", subPath); + strcat(dirpath, ent->d_name); + printf("%s [D]\r\n", dirpath); + int res = addDir(dirpath); + if (res != 0) { + printf("error adding directory (open)!\r\n"); + error = true; + break; + } + // Prepare new sub path. + sprintf(newSubPath, "%s", subPath); + strcat(newSubPath, ent->d_name); + strcat(newSubPath, "/"); + + if (addFiles(dirname, newSubPath) != 0) { + printf("Error for adding content from '%s' !\r\n", ent->d_name); + } + + continue; + } + else { + printf("skipping '%s'\r\n", ent->d_name); + continue; + } + } + + // File path with directory name as root folder. + sprintf(filepath, "%s", subPath); + strcat(filepath, ent->d_name); + printf("%s\r\n", filepath); + + // Add File to image. + if (addFile(filepath, fullpath) != 0) { + printf("error adding file!\r\n"); + error = true; + break; + } + } // end while + closedir(dir); + } + else { + printf("warning: can't read source directory\r\n"); + return 1; + } + + return (error) ? 1 : 0; +} + + +//---------------------------------------- +int lfs_img_create(struct lfs_config *cfg) +{ + lfs_image = malloc(cfg->block_size * cfg->block_count); + if (lfs_image == NULL) return -1; + + for (int i=0; iblock_count; i++) { + memset(lfs_image+(i*cfg->block_size), 0xFF, cfg->block_size); + } + + // setup function pointers + cfg->read = lfs_img_read; + cfg->prog = lfs_img_prog; + cfg->erase = lfs_img_erase; + cfg->sync = lfs_img_sync; + + return 0; +} + +//---------------------- +int lfs_img_format(void) +{ + int err = lfs_img_create(&config); + if (err) { + return err; + } + + err = lfs_format(&lfs, &config); + + return err; +} + +//------------------ +int save_image(void) +{ + FILE* img_file = fopen(image_name, "wb"); + if (!img_file) { + printf("error: failed to open '%s'\r\n", image_name); + return 1; + } + fwrite(lfs_image, 1, block_size * block_count, img_file); + fclose(img_file); + + return 0; +} + +//--------------------- +int lfs_img_mount(void) +{ + int err = 0; + + if (use_wl) fs_offset = 4096; + else fs_offset = 0; + + config.lookahead = lookahead; + config.block_count = block_count; + config.block_size = block_size; + config.prog_size = block_size; + config.read_size = block_size; + + err = lfs_img_create(&config); + if (err) { + printf("Error creating image (%d)\r\n", err); + return err; + } + + err = lfs_format(&lfs, &config); + if (err) { + printf("Error formating image (%d)\r\n", err); + return err; + } + + err = lfs_mount(&lfs, &config); + if (err) { + printf("Error mounting image (%d)\r\n", err); + return err; + } + return 0; +} + +//------------------------ +int lfs_create_image(void) +{ + int err = 0; + + err = lfs_img_mount(); + if (err) return err; + + printf("\r\nAdding files from image directory:\r\n"); + printf(" '%s'\r\n", image_dir); + printf("----------------------------------\r\n\r\n"); + addFiles(image_dir, "/"); + printf("\r\n"); + + err = lfs_unmount(&lfs); + if (err) { + printf("Error unmounting image (%d)\r\n", err); + } + + save_image(); + + return 0; +} + + +//=============================== +int main(int argc, char **argv) { + // parse options + int c; + char *cvalue = NULL; + char *ptr; + + printf("\r\n"); + while ( (c = getopt(argc, argv, "b:c:l:wT")) != -1) { + switch (c) { + case 'b': + cvalue = optarg; + block_size = (uint32_t)strtol(cvalue, &ptr, 10); + break; + case 'c': + cvalue = optarg; + block_count = (uint32_t)strtol(cvalue, &ptr, 10); + break; + case 'l': + cvalue = optarg; + lookahead = (uint32_t)strtol(cvalue, &ptr, 10); + break; + case 'w': + use_wl = true; + break; + case '?': + break; + default: + printf ("?? getopt returned character code 0%o ??\r\n", c); + } + } + + if (argc < 2) { + printf("Error: image directory and image name arguments are mandatory\r\n"); + printf("\r\n"); + return 1; + } + + sprintf(image_dir, "%s", argv[optind]); + sprintf(image_name, "%s", argv[optind+1]); + + printf("Creating LittleFS image\r\n"); + printf("=======================\r\n"); + printf("Image directory:\r\n '%s'\r\n", image_dir); + printf("Image name:\r\n '%s'\r\n", image_name); + printf("Block size=%u, Block count=%u, lookahead=%u, use wear leveling: %s\r\n", block_size, block_count, lookahead, use_wl ? "True" : "False"); + + int err = lfs_create_image(); + printf("=======================\r\n"); + printf("\r\n"); + + return err; +} diff --git a/MicroPython_BUILD/components/mkspiffs/include/sdkconfig.h b/MicroPython_BUILD/components/mkspiffs/include/sdkconfig.h index fac21dfa..5b70e3df 100644 --- a/MicroPython_BUILD/components/mkspiffs/include/sdkconfig.h +++ b/MicroPython_BUILD/components/mkspiffs/include/sdkconfig.h @@ -9,3 +9,4 @@ #define CONFIG_SPIFFS_GC_MAX_RUNS 10 #define CONFIG_SPIFFS_MAX_PARTITIONS 1 #define CONFIG_SPIFFS_OBJ_NAME_LEN 64 +#define CONFIG_SPIFFS_PAGE_SIZE 256 diff --git a/MicroPython_BUILD/components/quickmail/AUTHORS b/MicroPython_BUILD/components/quickmail/AUTHORS deleted file mode 100644 index 56a21ead..00000000 --- a/MicroPython_BUILD/components/quickmail/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Brecht Sanders - brechtsanders@users.sourceforge.net diff --git a/MicroPython_BUILD/components/quickmail/COPYING b/MicroPython_BUILD/components/quickmail/COPYING deleted file mode 100644 index 94a9ed02..00000000 --- a/MicroPython_BUILD/components/quickmail/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - 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/MicroPython_BUILD/components/quickmail/ChangeLog b/MicroPython_BUILD/components/quickmail/ChangeLog deleted file mode 100644 index 9239cfc2..00000000 --- a/MicroPython_BUILD/components/quickmail/ChangeLog +++ /dev/null @@ -1,249 +0,0 @@ -0.1.25 - -2016-10-31 Brecht Sanders - - * added "Content-Disposition: attachment; filename=" (thanks to David Singleton) - -0.1.24 - -2016-05-29 Brecht Sanders - - * fixed missing #include in smtpsocket.h - * added quickmail_cleanup() the fix memory leak when using cURL (thanks to Fulvio Senore) - -2016-05-25 Brecht Sanders - - * fixed date issue if locale is not English (thanks to Fulvio Senore) - -2016-05-19 Brecht Sanders - - * fixed daylight saving time issue on Windows (thanks to Fulvio Senore) - -0.1.23 - -2016-05-16 Brecht Sanders - - * move variable declaration to beginning of cose block for older C compilers - -2016-03-23 Brecht Sanders - - * removed -l from light command line application (without libcurl) - -0.1.22 - -2016-03-23 Brecht Sanders - - * added quickmail_send_secure() for SMTPS support (libcurl only) - -0.1.21 - -2015-12-11 Brecht Sanders - - * fixed base64 padding bug (reported by Wojtek Kunda) - * fixed missing end quote in body separator (reported by Wojtek Kunda) - * added multi-body support to command line application - -0.1.20 - -2015-10-08 Brecht Sanders - - * fixed some allocation code (reported by Carlos Tangerino) - -2015-05-09 Brecht Sanders - - * fixed configure.ac for MinGW static+shared build - -0.1.19 - -2015-04-29 Brecht Sanders - - * fixed curl error "VRFY command is disabled" (Andreas Baumann) - -0.1.18 - -2014-04-07 Brecht Sanders - - * fixed additional line break after Date header - -0.1.17 - -2013-11-10 Brecht Sanders - - * fixed Date header to show local time with proper UTC offset - -2013-11-05 Brecht Sanders - - * fixed line breaks in source files (UNIX EOL) - * show only the version of libcurl instead of all its components - -0.1.16 - -2013-10-21 Brecht Sanders - - * added code to catch failing malloc/realloc when out of memory - -0.1.15 - -2013-05-28 Brecht Sanders - - * API change: added mimetype parameter to the following functions - quickmail_list_attachment_callback_fn - quickmail_add_attachment_file - quickmail_add_attachment_memory - quickmail_add_attachment_custom - -2013-05-10 Brecht Sanders - - * fix automake to add -DNOCURL when compiling quickmaillight - * fix autoconf to allow compiling with per-target flags - -0.1.14 - -2013-05-03 Brecht Sanders - - * added header line for body: Content-Disposition: inline - -2013-04-16 Brecht Sanders - - * use angle brackets with CURLOPT_MAIL_FROM/CURLOPT_MAIL_RCPT - -2013-04-15 Brecht Sanders - - * added command line options -u username -w password - -0.1.13 - -2013-04-04 Brecht Sanders - - * added man page for application (quickmail.1) - -2013-03-16 Brecht Sanders - - * introduced dual licensing (GPL/commercial) and added License.txt - -2013-02-17 Brecht Sanders - - * fixed usage info in command line help (missing -m short help) - * added version information of libcurl library (and dependancies) - * undo previous change to use LF instead of CRLF, see RFC 2822 - -0.1.12 - -2013-02-16 Brecht Sanders - - * fixed a memory leak in quickmail_get_data when handling body data - * use LF instead of CRLF in headers (fixes a specific test case) - * quickmail program now accepts body from stdin if not supplied - * quickmail program now checks if at least 1 destination is supplied - -2013-02-13 Brecht Sanders - - * fixed bugs in custom body/attachment handling - * changes to support Microsoft Visual C as proposed by Troels K. - -2013-02-12 Brecht Sanders - - * changes to support Microsoft Visual C as proposed by Troels K. - -2012-11-24 Brecht Sanders - - * added -m command line parameter for MIME type of body - -0.1.11 - -2012-11-23 Brecht Sanders - - * fixed hang on remote SMTP disconnect if libcurl is not used - * quickmail application now returns nonzero exit code on error - * quickmail_set_body result is no longer const and caller must free() - * fixed missing Content-Type if no attachments - * added multipart/alternative support for multiple bodies - * added quickmail_add_body_file: add body from file - * added quickmail_add_body_memory: add body from memory - * added quickmail_add_body_custom: add body from custom source - * added quickmail_remove_body: remove body - * added quickmail_list_bodies: list bodies - -0.1.10 - -2012-11-13 Brecht Sanders - - * don't print to debuglog if it is NULL in smtpsocket.c - * include arpa/inet.h in smtpsocket.h for non-Windows systems - -0.1.9 - -2012-11-11 Brecht Sanders - - * quickmail application now returns nonzero exit code on error - * CURL_STATICLIB is defined when building static libquickmail.a - -0.1.8 - -2012-11-10 Brecht Sanders - - * now includes quickmail program to send mail from command line - * added quickmail_remove_attachment: remove attachment - * added quickmail_list_attachments: list attachments - * added quickmail_set_from: get from address - * added quickmail_get_subject: get subject - * quickmail_set_subject now sets the subject instead of from address - -0.1.7 - -2012-11-03 Brecht Sanders - - * added quickmail_initialize: initialize library - * added quickmail_add_attachment_memory: send attachment from memory - * added quickmail_add_attachment_custom: send custom data attachment - * added quickmail_add_header: add custom mail header - * fixed multiple To/Cc recipients are now joined in one header line - -0.1.6 - -2012-10-28 Brecht Sanders - - * fixes for building libquickmaillight on systems other than Windows - -0.1.5 - -2012-10-27 Brecht Sanders - - * new library libquickmaillight added with SMTP transport without libcurl - * added angle brackets around RCPT TO and MAIL FROM parameters - -0.1.4 - -2012-09-20 Brecht Sanders - - * fixed timezone issue by adding " +0000" to date header - -0.1.3 - -2012-09-20 Brecht Sanders - - * fixed missing ending quote in boundary header (reported by Mazin SW) - * fixed crash whith no attachments (reported by Mazin SW) - * fixed issue generating to stdio instead of file (reported by Mazin SW) - -0.1.2 - -2012-09-18 Brecht Sanders - - * removed header "Content-Description: The fixed length records" - -0.1.1 - -2012-08-03 Brecht Sanders - - * tested on Debian Linux - * added function quickmail_get_version() to get version number - * added Doxygen style comments to quickmail.h - -0.1.0 - -2012-08-02 Brecht Sanders - - * first release on SourceForge under GPL license - * depends on libcurl - * tested on Windows with MinGW and MinGW-64 compilers diff --git a/MicroPython_BUILD/components/quickmail/README b/MicroPython_BUILD/components/quickmail/README deleted file mode 100644 index 268291d2..00000000 --- a/MicroPython_BUILD/components/quickmail/README +++ /dev/null @@ -1,17 +0,0 @@ -Project name: - libquickmail -URL: - http://sourceforge.net/projects/libquickmail/ -Project discription: - C library intended to give C/C++ developers a quick and easy way - to send e-mail from their applications. - For the actual SMTP communication this library depends on libcurl. - There is also a light version available without libcurl dependancy. - The library can also be used to just create a multipart MIME - message body. - Features: - - multiple To/Cc/Bcc recipients - - multiple attachments without size limitation - - multiple bodies in alternative formats (e.g: text + HTML) - - SMTP authentication - - TLS encryption (via libcurl) diff --git a/MicroPython_BUILD/components/quickmail/component.mk b/MicroPython_BUILD/components/quickmail/component.mk deleted file mode 100644 index 0d8a2cf2..00000000 --- a/MicroPython_BUILD/components/quickmail/component.mk +++ /dev/null @@ -1,6 +0,0 @@ -# -# Component Makefile -# - -COMPONENT_SRCDIRS := . -COMPONENT_ADD_INCLUDEDIRS := . \ No newline at end of file diff --git a/MicroPython_BUILD/components/quickmail/quickmail.c b/MicroPython_BUILD/components/quickmail/quickmail.c deleted file mode 100644 index 3d45d79a..00000000 --- a/MicroPython_BUILD/components/quickmail/quickmail.c +++ /dev/null @@ -1,1020 +0,0 @@ -/* - This file is part of libquickmail. - - libquickmail 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. - - libquickmail 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 libquickmail. If not, see . - - Adapted for LUA-RTOS_ESP32 by Boris Lovosevic (loboris@gmail.com; https://github.com/loboris) -*/ - -#include "quickmail.h" -#include -#include -#include -#include -#include -#include -#include - -#include "py/mpthread.h" - -#define LIBQUICKMAIL_VERSION_MAJOR 0 -#define LIBQUICKMAIL_VERSION_MINOR 1 -#define LIBQUICKMAIL_VERSION_MICRO 25 - -#define VERSION_STRINGIZE_(major, minor, micro) #major"."#minor"."#micro -#define VERSION_STRINGIZE(major, minor, micro) VERSION_STRINGIZE_(major, minor, micro) - -#define LIBQUICKMAIL_VERSION VERSION_STRINGIZE(LIBQUICKMAIL_VERSION_MAJOR,LIBQUICKMAIL_VERSION_MINOR,LIBQUICKMAIL_VERSION_MICRO) - -#define NEWLINE "\r\n" -#define NEWLINELENGTH 2 -//#define NEWLINE "\n" -//#define NEWLINELENGTH 1 - -#define MIME_LINE_WIDTH 992 -#define BODY_BUFFER_SIZE 256 - -//definitions of the different stages of generating the message data -#define MAILPART_INITIALIZE 0 -#define MAILPART_HEADER 1 -#define MAILPART_BODY 2 -#define MAILPART_BODY_DONE 3 -#define MAILPART_ATTACHMENT 4 -#define MAILPART_END 5 -#define MAILPART_DONE 6 - -static const char* default_mime_type = "text/plain"; - -struct progress { - double lastruntime; - CURL *curl; -}; - -int quickmail_progress = 2; -int quickmail_verbose = 1; -int quickmail_timeout = 120; - -//////////////////////////////////////////////////////////////////////// - -#define DEBUG_ERROR(errmsg) -static const char* ERRMSG_MEMORY_ALLOCATION_ERROR = "Memory allocation error"; - -//////////////////////////////////////////////////////////////////////// - -char* randomize_zeros (char* data) -{ - //replace all 0s with random digits - char* p = data; - while (*p) { - if (*p == '0') - *p = '0' + rand() % 10; - p++; - } - return data; -} - -char* str_append (char** data, const char* newdata) -{ - //append a string to the end of an existing string - char* p; - int len = (*data ? strlen(*data) : 0); - if ((p = (char*)realloc(*data, len + strlen(newdata) + 1)) == NULL) { - free(p); - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return NULL; - } - *data = p; - strcpy(*data + len, newdata); - return *data; -} - -//////////////////////////////////////////////////////////////////////// - -struct email_info_struct { - int current; //must be zet to 0 - time_t timestamp; - char* from; - struct email_info_email_list_struct* to; - struct email_info_email_list_struct* cc; - struct email_info_email_list_struct* bcc; - char* subject; - char* header; - struct email_info_attachment_list_struct* bodylist; - struct email_info_attachment_list_struct* attachmentlist; - char* buf; - int buflen; - char* mime_boundary_body; - char* mime_boundary_part; - struct email_info_attachment_list_struct* current_attachment; - FILE* debuglog; - char dtable[64]; -}; - -//////////////////////////////////////////////////////////////////////// - -struct email_info_email_list_struct { - char* data; - struct email_info_email_list_struct* next; -}; - -void email_info_string_list_add (struct email_info_email_list_struct** list, const char* data) -{ - struct email_info_email_list_struct** p = list; - while (*p) - p = &(*p)->next; - if ((*p = (struct email_info_email_list_struct*)malloc(sizeof(struct email_info_email_list_struct))) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return; - } - (*p)->data = (data ? strdup(data) : NULL); - (*p)->next = NULL; -} - -void email_info_string_list_free (struct email_info_email_list_struct** list) -{ - struct email_info_email_list_struct* p = *list; - struct email_info_email_list_struct* current; - while (p) { - current = p; - p = current->next; - free(current->data); - free(current); - } - *list = NULL; -} - -char* email_info_string_list_concatenate (struct email_info_email_list_struct* list) -{ - char* result = NULL; - struct email_info_email_list_struct* listentry = list; - while (listentry) { - if (listentry->data && *listentry->data) { - if (result) - str_append(&result, "," NEWLINE "\t"); - str_append(&result, "<"); - str_append(&result, listentry->data); - str_append(&result, ">"); - } - listentry = listentry->next; - } - return result; -} - -//////////////////////////////////////////////////////////////////////// - -struct email_info_attachment_list_struct { - char* filename; - char* mimetype; - void* filedata; - void* handle; - quickmail_attachment_open_fn email_info_attachment_open; - quickmail_attachment_read_fn email_info_attachment_read; - quickmail_attachment_close_fn email_info_attachment_close; - quickmail_attachment_free_filedata_fn email_info_attachment_filedata_free; - struct email_info_attachment_list_struct* next; -}; - -struct email_info_attachment_list_struct* email_info_attachment_list_add (struct email_info_attachment_list_struct** list, const char* filename, const char* mimetype, void* filedata, quickmail_attachment_open_fn email_info_attachment_open, quickmail_attachment_read_fn email_info_attachment_read, quickmail_attachment_close_fn email_info_attachment_close, quickmail_attachment_free_filedata_fn email_info_attachment_filedata_free) -{ - struct email_info_attachment_list_struct** p = list; - while (*p) - p = &(*p)->next; - if ((*p = (struct email_info_attachment_list_struct*)malloc(sizeof(struct email_info_attachment_list_struct))) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return NULL; - } - (*p)->filename = strdup(filename ? filename : "UNNAMED"); - (*p)->mimetype = (mimetype ? strdup(mimetype) : NULL); - (*p)->filedata = filedata; - (*p)->handle = NULL; - (*p)->email_info_attachment_open = email_info_attachment_open; - (*p)->email_info_attachment_read = email_info_attachment_read; - (*p)->email_info_attachment_close = email_info_attachment_close; - (*p)->email_info_attachment_filedata_free = email_info_attachment_filedata_free; - (*p)->next = NULL; - return *p; -} - -void email_info_attachment_list_free_entry (struct email_info_attachment_list_struct* current) -{ - if (current->handle) { - if (current->email_info_attachment_close) - current->email_info_attachment_close(current->handle); - //else - // free(current->handle); - current->handle = NULL; - } - if (current->filedata) { - if (current->email_info_attachment_filedata_free) - current->email_info_attachment_filedata_free(current->filedata); - else - free(current->filedata); - } - if (current->mimetype) - free(current->mimetype); - free(current->filename); - free(current); -} - -void email_info_attachment_list_free (struct email_info_attachment_list_struct** list) -{ - struct email_info_attachment_list_struct* p = *list; - struct email_info_attachment_list_struct* current; - while (p) { - current = p; - p = current->next; - email_info_attachment_list_free_entry(current); - } - *list = NULL; -} - -int email_info_attachment_list_delete (struct email_info_attachment_list_struct** list, const char* filename) -{ - struct email_info_attachment_list_struct** p = list; - while (*p) { - if (strcmp((*p)->filename, filename) == 0) { - struct email_info_attachment_list_struct* current = *p; - *p = current->next; - email_info_attachment_list_free_entry(current); - return 0; - } - p = &(*p)->next; - } - return -1; -} - -void email_info_attachment_list_close_handles (struct email_info_attachment_list_struct* list) -{ - struct email_info_attachment_list_struct* p = list; - while (p) { - if (p->handle) { - if (p->email_info_attachment_close) - p->email_info_attachment_close(p->handle); - //else - // free(p->handle); - p->handle = NULL; - } - p = p->next; - } -} - -//dummy attachment functions - -void* email_info_attachment_open_dummy (void* filedata) -{ - return &email_info_attachment_open_dummy; -} - -size_t email_info_attachment_read_dummy (void* handle, void* buf, size_t len) -{ - return 0; -} - -struct email_info_attachment_list_struct* email_info_attachment_list_add_dummy (struct email_info_attachment_list_struct** list, const char* filename, const char* mimetype) -{ - return email_info_attachment_list_add(list, filename, mimetype, NULL, email_info_attachment_open_dummy, email_info_attachment_read_dummy, NULL, NULL); -} - -//file attachment functions - -void* email_info_attachment_open_file (void* filedata) -{ - return (void*)fopen((char*)filedata, "rb"); -} - -size_t email_info_attachment_read_file (void* handle, void* buf, size_t len) -{ - return fread(buf, 1, len, (FILE*)handle);; -} - -void email_info_attachment_close_file (void* handle) -{ - if (handle) - fclose((FILE*)handle); -} - -struct email_info_attachment_list_struct* email_info_attachment_list_add_file (struct email_info_attachment_list_struct** list, const char* path, const char* mimetype) -{ - //determine base filename - const char* basename = path + strlen(path); - while (basename != path) { - basename--; - if (*basename == '/') { - basename++; - break; - } - } - return email_info_attachment_list_add(list, basename, mimetype, (void*)strdup(path), email_info_attachment_open_file, email_info_attachment_read_file, email_info_attachment_close_file, NULL); -} - -//memory attachment functions - -struct email_info_attachment_memory_filedata_struct { - char* data; - size_t datalen; - int mustfree; -}; - -struct email_info_attachment_memory_handle_struct { - const char* data; - size_t datalen; - size_t pos; -}; - -void* email_info_attachment_open_memory (void* filedata) -{ - struct email_info_attachment_memory_filedata_struct* data; - struct email_info_attachment_memory_handle_struct* result; - data = ((struct email_info_attachment_memory_filedata_struct*)filedata); - if (!data->data) - return NULL; - if ((result = (struct email_info_attachment_memory_handle_struct*)malloc(sizeof(struct email_info_attachment_memory_handle_struct))) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return NULL; - } - result->data = data->data; - result->datalen = data->datalen; - result->pos = 0; - return result; -} - -size_t email_info_attachment_read_memory (void* handle, void* buf, size_t len) -{ - struct email_info_attachment_memory_handle_struct* h = (struct email_info_attachment_memory_handle_struct*)handle; - size_t n = (h->pos + len <= h->datalen ? len : h->datalen - h->pos); - memcpy(buf, h->data + h->pos, n); - h->pos += n; - return n; -} - -void email_info_attachment_close_memory (void* handle) -{ - if (handle) - free(handle); -} - -void email_info_attachment_filedata_free_memory (void* filedata) -{ - struct email_info_attachment_memory_filedata_struct* data = ((struct email_info_attachment_memory_filedata_struct*)filedata); - if (data) { - if (data->mustfree) - free(data->data); - free(data); - } -} - -struct email_info_attachment_list_struct* email_info_attachment_list_add_memory (struct email_info_attachment_list_struct** list, const char* filename, const char* mimetype, char* data, size_t datalen, int mustfree) -{ - struct email_info_attachment_memory_filedata_struct* filedata; - if ((filedata = (struct email_info_attachment_memory_filedata_struct*)malloc(sizeof(struct email_info_attachment_memory_filedata_struct))) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return NULL; - } - filedata->data = data; - filedata->datalen = datalen; - filedata->mustfree = mustfree; - return email_info_attachment_list_add(list, filename, mimetype, filedata, email_info_attachment_open_memory, email_info_attachment_read_memory, email_info_attachment_close_memory, email_info_attachment_filedata_free_memory); -} - -//////////////////////////////////////////////////////////////////////// - -const char* quickmail_get_version () -{ - return VERSION_STRINGIZE(LIBQUICKMAIL_VERSION_MAJOR, LIBQUICKMAIL_VERSION_MINOR, LIBQUICKMAIL_VERSION_MICRO); -} - -int quickmail_cleanup () -{ -#ifndef NOCURL - curl_global_cleanup(); -#endif - return 0; -} - -quickmail quickmail_create (const char* from, const char* subject) -{ - int i; - struct email_info_struct* mailobj; - if ((mailobj = (struct email_info_struct*)malloc(sizeof(struct email_info_struct))) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return NULL; - } - mailobj->current = 0; - mailobj->timestamp = time(NULL); - mailobj->from = (from ? strdup(from) : NULL); - mailobj->to = NULL; - mailobj->cc = NULL; - mailobj->bcc = NULL; - mailobj->subject = (subject ? strdup(subject) : NULL); - mailobj->header = NULL; - mailobj->bodylist = NULL; - mailobj->attachmentlist = NULL; - mailobj->buf = NULL; - mailobj->buflen = 0; - mailobj->mime_boundary_body = NULL; - mailobj->mime_boundary_part = NULL; - mailobj->current_attachment = NULL; - mailobj->debuglog = NULL; - for (i = 0; i < 26; i++) { - mailobj->dtable[i] = (char)('A' + i); - mailobj->dtable[26 + i] = (char)('a' + i); - } - for (i = 0; i < 10; i++) { - mailobj->dtable[52 + i] = (char)('0' + i); - } - mailobj->dtable[62] = '+'; - mailobj->dtable[63] = '/'; - srand(time(NULL)); - return mailobj; -} - -void quickmail_destroy (quickmail mailobj) -{ - free(mailobj->from); - email_info_string_list_free(&mailobj->to); - email_info_string_list_free(&mailobj->cc); - email_info_string_list_free(&mailobj->bcc); - free(mailobj->subject); - free(mailobj->header); - email_info_attachment_list_free(&mailobj->bodylist); - email_info_attachment_list_free(&mailobj->attachmentlist); - free(mailobj->buf); - free(mailobj->mime_boundary_body); - free(mailobj->mime_boundary_part); - free(mailobj); -} - -void quickmail_set_from (quickmail mailobj, const char* from) -{ - free(mailobj->from); - mailobj->from = strdup(from); -} - -const char* quickmail_get_from (quickmail mailobj) -{ - return mailobj->from; -} - -void quickmail_add_to (quickmail mailobj, const char* email) -{ - email_info_string_list_add(&mailobj->to, email); -} - -void quickmail_add_cc (quickmail mailobj, const char* email) -{ - email_info_string_list_add(&mailobj->cc, email); -} - -void quickmail_add_bcc (quickmail mailobj, const char* email) -{ - email_info_string_list_add(&mailobj->bcc, email); -} - -void quickmail_set_subject (quickmail mailobj, const char* subject) -{ - free(mailobj->subject); - mailobj->subject = (subject ? strdup(subject) : NULL); -} - -const char* quickmail_get_subject (quickmail mailobj) -{ - return mailobj->subject; -} - -void quickmail_add_header (quickmail mailobj, const char* headerline) -{ - str_append(&mailobj->header, headerline); - str_append(&mailobj->header, NEWLINE); -} - -void quickmail_set_body (quickmail mailobj, const char* body) -{ - email_info_attachment_list_free(&mailobj->bodylist); - if (body) - email_info_attachment_list_add_memory(&mailobj->bodylist, default_mime_type, default_mime_type, strdup(body), strlen(body), 1); -} - -char* quickmail_get_body (quickmail mailobj) -{ - size_t n; - char* p; - char* result = NULL; - size_t resultlen = 0; - if (mailobj->bodylist && (mailobj->bodylist->handle = mailobj->bodylist->email_info_attachment_open(mailobj->bodylist->filedata)) != NULL) { - do { - if ((p = (char*)realloc(result, resultlen + BODY_BUFFER_SIZE)) == NULL) { - free(result); - result = NULL; - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - break; - } - result = p; - if ((n = mailobj->bodylist->email_info_attachment_read(mailobj->bodylist->handle, result + resultlen, BODY_BUFFER_SIZE)) > 0) - resultlen += n; - } while (n > 0); - if (mailobj->bodylist->email_info_attachment_close) - mailobj->bodylist->email_info_attachment_close(mailobj->bodylist->handle); - //else - // free(mailobj->bodylist->handle); - mailobj->bodylist->handle = NULL; - } - return result; -} - -void quickmail_add_body_file (quickmail mailobj, const char* mimetype, const char* path) -{ - email_info_attachment_list_add(&mailobj->bodylist, NULL, (mimetype ? mimetype : default_mime_type), (void*)strdup(path), email_info_attachment_open_file, email_info_attachment_read_file, email_info_attachment_close_file, NULL); -} - -void quickmail_add_body_memory (quickmail mailobj, const char* mimetype, char* data, size_t datalen, int mustfree) -{ - email_info_attachment_list_add_memory(&mailobj->bodylist, NULL, (mimetype ? mimetype : default_mime_type), data, datalen, mustfree); -} - -void quickmail_add_body_custom (quickmail mailobj, const char* mimetype, char* data, quickmail_attachment_open_fn attachment_data_open, quickmail_attachment_read_fn attachment_data_read, quickmail_attachment_close_fn attachment_data_close, quickmail_attachment_free_filedata_fn attachment_data_filedata_free) -{ - email_info_attachment_list_add(&mailobj->bodylist, NULL, (mimetype ? mimetype : default_mime_type), data, (attachment_data_open ? attachment_data_open : email_info_attachment_open_dummy), (attachment_data_read ? attachment_data_read : email_info_attachment_read_dummy), attachment_data_close, attachment_data_filedata_free); -} - -int quickmail_remove_body (quickmail mailobj, const char* mimetype) -{ - return email_info_attachment_list_delete(&mailobj->bodylist, mimetype); -} - -void quickmail_list_bodies (quickmail mailobj, quickmail_list_attachment_callback_fn callback, void* callbackdata) -{ - struct email_info_attachment_list_struct* p = mailobj->bodylist; - while (p) { - callback(mailobj, p->filename, p->mimetype, p->email_info_attachment_open, p->email_info_attachment_read, p->email_info_attachment_close, callbackdata); - p = p->next; - } -} - -void quickmail_add_attachment_file (quickmail mailobj, const char* path, const char* mimetype) -{ - email_info_attachment_list_add_file(&mailobj->attachmentlist, path, mimetype); -} - -void quickmail_add_attachment_memory (quickmail mailobj, const char* filename, const char* mimetype, char* data, size_t datalen, int mustfree) -{ - email_info_attachment_list_add_memory(&mailobj->attachmentlist, filename, mimetype, data, datalen, mustfree); -} - -void quickmail_add_attachment_custom (quickmail mailobj, const char* filename, const char* mimetype, char* data, quickmail_attachment_open_fn attachment_data_open, quickmail_attachment_read_fn attachment_data_read, quickmail_attachment_close_fn attachment_data_close, quickmail_attachment_free_filedata_fn attachment_data_filedata_free) -{ - email_info_attachment_list_add(&mailobj->attachmentlist, filename, mimetype, data, (attachment_data_open ? attachment_data_open : email_info_attachment_open_dummy), (attachment_data_read ? attachment_data_read : email_info_attachment_read_dummy), attachment_data_close, attachment_data_filedata_free); -} - -int quickmail_remove_attachment (quickmail mailobj, const char* filename) -{ - return email_info_attachment_list_delete(&mailobj->attachmentlist, filename); -} - -void quickmail_list_attachments (quickmail mailobj, quickmail_list_attachment_callback_fn callback, void* callbackdata) -{ - struct email_info_attachment_list_struct* p = mailobj->attachmentlist; - while (p) { - callback(mailobj, p->filename, p->mimetype, p->email_info_attachment_open, p->email_info_attachment_read, p->email_info_attachment_close, callbackdata); - p = p->next; - } -} - -void quickmail_set_debug_log (quickmail mailobj, FILE* filehandle) -{ - mailobj->debuglog = filehandle; -} - -void quickmail_fsave (quickmail mailobj, FILE* filehandle) -{ - int i; - size_t n; - char buf[80]; - while ((n = quickmail_get_data(buf, sizeof(buf), 1, mailobj)) > 0) { - for (i = 0; i < n; i++) - fprintf(filehandle, "%c", buf[i]); - } -} - -size_t quickmail_get_data (void* ptr, size_t size, size_t nmemb, void* userp) -{ - struct email_info_struct* mailobj = (struct email_info_struct*)userp; - - //abort if no data is requested - if (size * nmemb == 0) - return 0; - - //initialize on first run - if (mailobj->current == MAILPART_INITIALIZE) { - free(mailobj->buf); - mailobj->buf = NULL; - mailobj->buflen = 0; - free(mailobj->mime_boundary_body); - mailobj->mime_boundary_body = NULL; - free(mailobj->mime_boundary_part); - mailobj->mime_boundary_part = NULL; - mailobj->current_attachment = mailobj->bodylist; - mailobj->current++; - } - - //process current part of mail if no partial data is pending - while (mailobj->buflen == 0) { - if (mailobj->buflen == 0 && mailobj->current == MAILPART_HEADER) { - char* s; - //generate header part - char** p = &mailobj->buf; - str_append(p, "User-Agent: libquickmail v" LIBQUICKMAIL_VERSION NEWLINE); - if (mailobj->timestamp != 0) { - char* oldlocale; - char timestamptext[32]; - //get original locale settings and switch to C locale (so date is in English) - if ((oldlocale = setlocale(LC_TIME, NULL)) != NULL) { - oldlocale = strdup(oldlocale); - setlocale(LC_TIME, "C"); - } - //format timestamp - if (strftime(timestamptext, sizeof(timestamptext), "%a, %d %b %Y %H:%M:%S %z", localtime(&mailobj->timestamp))) { - str_append(p, "Date: "); - str_append(p, timestamptext); - str_append(p, NEWLINE); - } - //restore original locale - if (oldlocale) { - setlocale(LC_TIME, oldlocale); - free(oldlocale); - } - } - if (mailobj->from && *mailobj->from) { - str_append(p, "From: <"); - str_append(p, mailobj->from); - str_append(p, ">" NEWLINE); - } - if ((s = email_info_string_list_concatenate(mailobj->to)) != NULL) { - str_append(p, "To: "); - str_append(p, s); - str_append(p, NEWLINE); - free(s); - } - if ((s = email_info_string_list_concatenate(mailobj->cc)) != NULL) { - str_append(p, "Cc: "); - str_append(p, s); - str_append(p, NEWLINE); - free(s); - } - if (mailobj->subject) { - str_append(p, "Subject: "); - str_append(p, mailobj->subject); - str_append(p, NEWLINE); - } - if (mailobj->header) { - str_append(p, mailobj->header); - } - if (mailobj->attachmentlist) { - str_append(p, "MIME-Version: 1.0" NEWLINE); - } - if (mailobj->attachmentlist) { - mailobj->mime_boundary_part = randomize_zeros(strdup("=PART=SEPARATOR=_0000_0000_0000_0000_0000_0000_=")); - str_append(p, "Content-Type: multipart/mixed; boundary=\""); - str_append(p, mailobj->mime_boundary_part); - str_append(p, "\"" NEWLINE NEWLINE "This is a multipart message in MIME format." NEWLINE NEWLINE "--"); - str_append(p, mailobj->mime_boundary_part); - str_append(p, NEWLINE); - } - if (mailobj->bodylist && mailobj->bodylist->next) { - mailobj->mime_boundary_body = randomize_zeros(strdup("=BODY=SEPARATOR=_0000_0000_0000_0000_0000_0000_=")); - str_append(p, "Content-Type: multipart/alternative; boundary=\""); - str_append(p, mailobj->mime_boundary_body); - str_append(p, "\"" NEWLINE); - } - mailobj->buflen = (mailobj->buf ? strlen(mailobj->buf) : 0); - mailobj->current++; - } - if (mailobj->buflen == 0 && mailobj->current == MAILPART_BODY) { - if (mailobj->current_attachment) { - if (!mailobj->current_attachment->handle) { - //open file with body data - while (mailobj->current_attachment) { - if ((mailobj->current_attachment->handle = mailobj->current_attachment->email_info_attachment_open(mailobj->current_attachment->filedata)) != NULL) { - break; - } - /////to do: notify/log the file could not be opened - mailobj->current_attachment = mailobj->current_attachment->next; - } - if (!mailobj->current_attachment) { - mailobj->current_attachment = mailobj->attachmentlist; - mailobj->current++; - } - //generate attachment header - if (mailobj->current_attachment && mailobj->current_attachment->handle) { - mailobj->buf = NULL; - if (mailobj->mime_boundary_body) { - mailobj->buf = str_append(&mailobj->buf, NEWLINE "--"); - mailobj->buf = str_append(&mailobj->buf, mailobj->mime_boundary_body); - mailobj->buf = str_append(&mailobj->buf, NEWLINE); - } - mailobj->buf = str_append(&mailobj->buf, "Content-Type: "); - mailobj->buf = str_append(&mailobj->buf, (mailobj->bodylist && mailobj->current_attachment->mimetype ? mailobj->current_attachment->mimetype : default_mime_type)); - mailobj->buf = str_append(&mailobj->buf, NEWLINE "Content-Transfer-Encoding: 8bit" NEWLINE "Content-Disposition: inline" NEWLINE NEWLINE); - mailobj->buflen = (mailobj->buf ? strlen(mailobj->buf) : 0); - } - } - if (mailobj->buflen == 0 && mailobj->current_attachment && mailobj->current_attachment->handle) { - //read body data - if ((mailobj->buf = malloc(BODY_BUFFER_SIZE)) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - } - if (mailobj->buf == NULL || (mailobj->buflen = mailobj->current_attachment->email_info_attachment_read(mailobj->current_attachment->handle, mailobj->buf, BODY_BUFFER_SIZE)) <= 0) { - //end of file - free(mailobj->buf); - mailobj->buflen = 0; - if (mailobj->current_attachment->email_info_attachment_close) - mailobj->current_attachment->email_info_attachment_close(mailobj->current_attachment->handle); - //else - // free(mailobj->current_attachment->handle); - mailobj->current_attachment->handle = NULL; - mailobj->current_attachment = mailobj->current_attachment->next; - } - } - } else { - mailobj->current_attachment = mailobj->attachmentlist; - mailobj->current++; - } - } - if (mailobj->buflen == 0 && mailobj->current == MAILPART_BODY_DONE) { - mailobj->buf = NULL; - if (mailobj->mime_boundary_body) { - mailobj->buf = str_append(&mailobj->buf, NEWLINE "--"); - mailobj->buf = str_append(&mailobj->buf, mailobj->mime_boundary_body); - mailobj->buf = str_append(&mailobj->buf, "--" NEWLINE); - mailobj->buflen = strlen(mailobj->buf); - free(mailobj->mime_boundary_body); - mailobj->mime_boundary_body = NULL; - } - mailobj->current++; - } - if (mailobj->buflen == 0 && mailobj->current == MAILPART_ATTACHMENT) { - if (mailobj->current_attachment) { - if (!mailobj->current_attachment->handle) { - //open file to attach - while (mailobj->current_attachment) { - if ((mailobj->current_attachment->handle = mailobj->current_attachment->email_info_attachment_open(mailobj->current_attachment->filedata)) != NULL) { - break; - } - mailobj->current_attachment = mailobj->current_attachment->next; - } - //generate attachment header - if (mailobj->current_attachment && mailobj->current_attachment->handle) { - mailobj->buf = NULL; - if (mailobj->mime_boundary_part) { - mailobj->buf = str_append(&mailobj->buf, NEWLINE "--"); - mailobj->buf = str_append(&mailobj->buf, mailobj->mime_boundary_part); - mailobj->buf = str_append(&mailobj->buf, NEWLINE); - } - mailobj->buf = str_append(&mailobj->buf, "Content-Type: "); - mailobj->buf = str_append(&mailobj->buf, (mailobj->current_attachment->mimetype ? mailobj->current_attachment->mimetype : "application/octet-stream")); - mailobj->buf = str_append(&mailobj->buf, "; Name=\""); - mailobj->buf = str_append(&mailobj->buf, (mailobj->current_attachment->filename ? mailobj->current_attachment->filename : "ATTACHMENT")); - mailobj->buf = str_append(&mailobj->buf, "\"" NEWLINE "Content-Disposition: attachment; filename=\""); - mailobj->buf = str_append(&mailobj->buf, (mailobj->current_attachment->filename ? mailobj->current_attachment->filename : "ATTACHMENT")); - mailobj->buf = str_append(&mailobj->buf, "\"" NEWLINE "Content-Transfer-Encoding: base64" NEWLINE NEWLINE); - mailobj->buflen = strlen(mailobj->buf); - } - } else { - //generate next line of attachment data - size_t n = 0; - int mimelinepos = 0; - unsigned char igroup[3] = {0, 0, 0}; - unsigned char ogroup[4]; - mailobj->buflen = 0; - if ((mailobj->buf = (char*)malloc(MIME_LINE_WIDTH + NEWLINELENGTH + 1)) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - n = 0; - } else { - while (mimelinepos < MIME_LINE_WIDTH && (n = mailobj->current_attachment->email_info_attachment_read(mailobj->current_attachment->handle, igroup, 3)) > 0) { - //code data to base64 - ogroup[0] = mailobj->dtable[igroup[0] >> 2]; - ogroup[1] = mailobj->dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; - ogroup[2] = mailobj->dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; - ogroup[3] = mailobj->dtable[igroup[2] & 0x3F]; - //padd with "=" characters if less than 3 characters were read - if (n < 3) { - ogroup[3] = '='; - if (n < 2) - ogroup[2] = '='; - } - memcpy(mailobj->buf + mimelinepos, ogroup, 4); - mailobj->buflen += 4; - mimelinepos += 4; - } - if (mimelinepos > 0) { - memcpy(mailobj->buf + mimelinepos, NEWLINE, NEWLINELENGTH); - mailobj->buflen += NEWLINELENGTH; - } - } - if (n <= 0) { - //end of file - if (mailobj->current_attachment->email_info_attachment_close) - mailobj->current_attachment->email_info_attachment_close(mailobj->current_attachment->handle); - else - free(mailobj->current_attachment->handle); - mailobj->current_attachment->handle = NULL; - mailobj->current_attachment = mailobj->current_attachment->next; - } - } - } else { - mailobj->current++; - } - } - if (mailobj->buflen == 0 && mailobj->current == MAILPART_END) { - mailobj->buf = NULL; - mailobj->buflen = 0; - if (mailobj->mime_boundary_part) { - mailobj->buf = str_append(&mailobj->buf, NEWLINE "--"); - mailobj->buf = str_append(&mailobj->buf, mailobj->mime_boundary_part); - mailobj->buf = str_append(&mailobj->buf, "--" NEWLINE); - mailobj->buflen = strlen(mailobj->buf); - free(mailobj->mime_boundary_part); - mailobj->mime_boundary_part = NULL; - } - //mailobj->buf = str_append(&mailobj->buf, NEWLINE "." NEWLINE); - //mailobj->buflen = strlen(mailobj->buf); - mailobj->current++; - } - if (mailobj->buflen == 0 && mailobj->current == MAILPART_DONE) { - break; - } - } - - //flush pending data if any - if (mailobj->buflen > 0) { - int len = (mailobj->buflen > size * nmemb ? size * nmemb : mailobj->buflen); - memcpy(ptr, mailobj->buf, len); - if (len < mailobj->buflen) { - mailobj->buf = memmove(mailobj->buf, mailobj->buf + len, mailobj->buflen - len); - mailobj->buflen -= len; - } else { - free(mailobj->buf); - mailobj->buf = NULL; - mailobj->buflen = 0; - } - return len; - } - - //if (mailobj->current != MAILPART_DONE) - // ;//this should never be reached - mailobj->current = 0; - return 0; -} - -#ifndef NOCURL -char* add_angle_brackets (const char* data) -{ - size_t datalen = strlen(data); - char* result; - if ((result = (char*)malloc(datalen + 3)) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return NULL; - } - result[0] = '<'; - memcpy(result + 1, data, datalen); - result[datalen + 1] = '>'; - result[datalen + 2] = 0; - return result; -} -#endif - -static int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { - struct progress *myp = (struct progress *)p; - CURL *curl = myp->curl; - double curtime = 0; - - curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime); - - /* under certain circumstances it may be desirable for certain functionality - to only run every N seconds, in order to do this the transaction time can - be used */ - if ((quickmail_verbose) && ((curtime - myp->lastruntime) >= quickmail_progress)) { - if (myp->lastruntime == 0) printf("\r\n"); - myp->lastruntime = curtime; - printf("TIME: %0.1f UP: %" CURL_FORMAT_CURL_OFF_T"\r", curtime, ulnow); - } - return 0; -} - -const char* quickmail_protocol_send (quickmail mailobj, const char* smtpserver, unsigned int smtpport, int protocol, const char* username, const char* password) -{ - //libcurl based sending - CURL *curl; - CURLcode result = CURLE_FAILED_INIT; - struct progress prog; - - if ((curl = curl_easy_init()) != NULL) { - prog.lastruntime = 0; - prog.curl = curl; - struct curl_slist *recipients = NULL; - struct email_info_email_list_struct* listentry; - //set destination URL - char* addr; - size_t len = strlen(smtpserver) + 14; - if ((addr = (char*)malloc(len)) == NULL) { - DEBUG_ERROR(ERRMSG_MEMORY_ALLOCATION_ERROR) - return ERRMSG_MEMORY_ALLOCATION_ERROR; - } - snprintf(addr, len, "%s://%s:%u", (protocol == QUICKMAIL_PROT_SMTPS ? "smtps" : "smtp"), smtpserver, smtpport); - curl_easy_setopt(curl, CURLOPT_URL, addr); - free(addr); - //try Transport Layer Security (TLS), but continue anyway if it fails - curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY); - //don't fail if the TLS/SSL a certificate could not be verified - //alternative: add the issuer certificate (or the host certificate if - //the certificate is self-signed) to the set of certificates that are - //known to libcurl using CURLOPT_CAINFO and/or CURLOPT_CAPATH - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - //set authentication credentials if provided - if (username && *username) - curl_easy_setopt(curl, CURLOPT_USERNAME, username); - if (password) - curl_easy_setopt(curl, CURLOPT_PASSWORD, password); - //set from value for envelope reverse-path - if (mailobj->from && *mailobj->from) { - addr = add_angle_brackets(mailobj->from); - curl_easy_setopt(curl, CURLOPT_MAIL_FROM, addr); - free(addr); - } - //set recipients - listentry = mailobj->to; - while (listentry) { - if (listentry->data && *listentry->data) { - addr = add_angle_brackets(listentry->data); - recipients = curl_slist_append(recipients, addr); - free(addr); - } - listentry = listentry->next; - } - listentry = mailobj->cc; - while (listentry) { - if (listentry->data && *listentry->data) { - addr = add_angle_brackets(listentry->data); - recipients = curl_slist_append(recipients, addr); - free(addr); - } - listentry = listentry->next; - } - listentry = mailobj->bcc; - while (listentry) { - if (listentry->data && *listentry->data) { - addr = add_angle_brackets(listentry->data); - recipients = curl_slist_append(recipients, addr); - free(addr); - } - listentry = listentry->next; - } - curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); - //set callback function for getting message body - curl_easy_setopt(curl, CURLOPT_READFUNCTION, quickmail_get_data); - curl_easy_setopt(curl, CURLOPT_READDATA, mailobj); - curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); //set CURLOPT_UPLOAD to 1 to not use VRFY and other unneeded commands - //enable debugging if requested - if (mailobj->debuglog) { - curl_easy_setopt(curl, CURLOPT_VERBOSE, quickmail_verbose); - curl_easy_setopt(curl, CURLOPT_STDERR, mailobj->debuglog); - } - curl_easy_setopt(curl, CURLOPT_TIMEOUT, quickmail_timeout); - curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo); - // pass the struct pointer into the xferinfo function, note that this is an alias to CURLOPT_PROGRESSDATA - curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog); - if (quickmail_progress) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1L); - - //send the message - MP_THREAD_GIL_EXIT(); - result = curl_easy_perform(curl); - MP_THREAD_GIL_ENTER(); - - if (quickmail_verbose) printf("\r\n"); - //free the list of recipients and clean up - curl_slist_free_all(recipients); - curl_easy_cleanup(curl); - } - return (result == CURLE_OK ? NULL : curl_easy_strerror(result)); -} - -const char* quickmail_send (quickmail mailobj, const char* smtpserver, unsigned int smtpport, const char* username, const char* password) -{ - return quickmail_protocol_send(mailobj, smtpserver, smtpport, QUICKMAIL_PROT_SMTP, username, password); -} -const char* quickmail_send_secure (quickmail mailobj, const char* smtpserver, unsigned int smtpport, const char* username, const char* password) -{ - return quickmail_protocol_send(mailobj, smtpserver, smtpport, QUICKMAIL_PROT_SMTPS, username, password); -} diff --git a/MicroPython_BUILD/components/quickmail/quickmail.h b/MicroPython_BUILD/components/quickmail/quickmail.h deleted file mode 100644 index 4a729bd5..00000000 --- a/MicroPython_BUILD/components/quickmail/quickmail.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - This file is part of libquickmail. - - libquickmail 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. - - libquickmail 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 libquickmail. If not, see . - - Adapted for LUA-RTOS_ESP32 by Boris Lovosevic (loboris@gmail.com; https://github.com/loboris) -*/ - -/*! \file quickmail.h - * \brief header file for libquickmail - * \author Brecht Sanders - * \date 2012-2016 - * \copyright GPL - */ - -#ifndef __INCLUDED_QUICKMAIL_H -#define __INCLUDED_QUICKMAIL_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define QUICKMAIL_PROT_SMTP 1 -#define QUICKMAIL_PROT_SMTPS 2 - - -/*! \brief quickmail object type */ -typedef struct email_info_struct* quickmail; - - - -/*! \brief type of pointer to function for opening attachment data - * \param filedata custom data as passed to quickmail_add_body_custom/quickmail_add_attachment_custom - * \return data structure to be used in calls to quickmail_attachment_read_fn and quickmail_attachment_close_fn functions - * \sa quickmail_add_body_custom() - * \sa quickmail_add_attachment_custom() - */ -typedef void* (*quickmail_attachment_open_fn)(void* filedata); - -/*! \brief type of pointer to function for reading attachment data - * \param handle data structure obtained via the corresponding quickmail_attachment_open_fn function - * \param buf buffer for receiving data - * \param len size in bytes of buffer for receiving data - * \return number of bytes read (zero on end of file) - * \sa quickmail_add_body_custom() - * \sa quickmail_add_attachment_custom() - */ -typedef size_t (*quickmail_attachment_read_fn)(void* handle, void* buf, size_t len); - -/*! \brief type of pointer to function for closing attachment data - * \param handle data structure obtained via the corresponding quickmail_attachment_open_fn function - * \sa quickmail_add_body_custom() - * \sa quickmail_add_attachment_custom() - */ -typedef void (*quickmail_attachment_close_fn)(void* handle); - -/*! \brief type of pointer to function for cleaning up custom data in quickmail_destroy - * \param filedata custom data as passed to quickmail_add_body_custom/quickmail_add_attachment_custom - * \sa quickmail_add_body_custom() - * \sa quickmail_add_attachment_custom() - */ -typedef void (*quickmail_attachment_free_filedata_fn)(void* filedata); - -/*! \brief type of pointer to function for cleaning up custom data in quickmail_destroy - * \param mailobj quickmail object - * \param filename attachment filename (same value as mimetype for mail body) - * \param mimetype MIME type - * \param attachment_data_open function for opening attachment data - * \param attachment_data_read function for reading attachment data - * \param attachment_data_close function for closing attachment data (optional, free() will be used if NULL) - * \param callbackdata custom data passed to quickmail_list_attachments - * \sa quickmail_list_bodies() - * \sa quickmail_list_attachments() - */ -typedef void (*quickmail_list_attachment_callback_fn)(quickmail mailobj, const char* filename, const char* mimetype, quickmail_attachment_open_fn email_info_attachment_open, quickmail_attachment_read_fn email_info_attachment_read, quickmail_attachment_close_fn email_info_attachment_close, void* callbackdata); - - - -/*! \brief get version quickmail library - * \return library version - */ -const char* quickmail_get_version (); - -/*! \brief clean up quickmail library, call once at the end of the main thread of the application - * \return zero on success - */ -int quickmail_cleanup (); - -/*! \brief create a new quickmail object - * \param from sender e-mail address - * \param subject e-mail subject - * \return quickmail object or NULL on error - */ -quickmail quickmail_create (const char* from, const char* subject); - -/*! \brief clean up a quickmail object - * \param mailobj quickmail object - */ -void quickmail_destroy (quickmail mailobj); - -/*! \brief set the sender (from) e-mail address of a quickmail object - * \param mailobj quickmail object - * \param from sender e-mail address - */ -void quickmail_set_from (quickmail mailobj, const char* from); - -/*! \brief get the sender (from) e-mail address of a quickmail object - * \param mailobj quickmail object - * \return sender e-mail address - */ -const char* quickmail_get_from (quickmail mailobj); - -/*! \brief add a recipient (to) e-mail address to a quickmail object - * \param mailobj quickmail object - * \param e-mail recipient e-mail address - */ -void quickmail_add_to (quickmail mailobj, const char* email); - -/*! \brief add a carbon copy recipient (cc) e-mail address to a quickmail object - * \param mailobj quickmail object - * \param e-mail recipient e-mail address - */ -void quickmail_add_cc (quickmail mailobj, const char* email); - -/*! \brief add a blind carbon copy recipient (bcc) e-mail address to a quickmail object - * \param mailobj quickmail object - * \param e-mail recipient e-mail address - */ -void quickmail_add_bcc (quickmail mailobj, const char* email); - -/*! \brief set the subject of a quickmail object - * \param mailobj quickmail object - * \param subject e-mail subject - */ -void quickmail_set_subject (quickmail mailobj, const char* subject); - -/*! \brief set the subject of a quickmail object - * \param mailobj quickmail object - * \return e-mail subject - */ -const char* quickmail_get_subject (quickmail mailobj); - -/*! \brief add an e-mail header to a quickmail object - * \param mailobj quickmail object - * \param headerline header line to add - */ -void quickmail_add_header (quickmail mailobj, const char* headerline); - -/*! \brief set the body of a quickmail object - * \param mailobj quickmail object - * \param body e-mail body - */ -void quickmail_set_body (quickmail mailobj, const char* body); - -/*! \brief set the body of a quickmail object - * any existing bodies will be removed and a single plain text body will be added - * \param mailobj quickmail object - * \return e-mail body or NULL on error (caller must free result) - */ -char* quickmail_get_body (quickmail mailobj); - -/*! \brief add a body file to a quickmail object (deprecated) - * \param mailobj quickmail object - * \param mimetype MIME type (text/plain will be used if set to NULL) - * \param path path of file with body data - */ -void quickmail_add_body_file (quickmail mailobj, const char* mimetype, const char* path); - -/*! \brief add a body from memory to a quickmail object - * \param mailobj quickmail object - * \param mimetype MIME type (text/plain will be used if set to NULL) - * \param data body content - * \param datalen size of data in bytes - * \param mustfree non-zero if data must be freed by quickmail_destroy - */ -void quickmail_add_body_memory (quickmail mailobj, const char* mimetype, char* data, size_t datalen, int mustfree); - -/*! \brief add a body with custom read functions to a quickmail object - * \param mailobj quickmail object - * \param mimetype MIME type (text/plain will be used if set to NULL) - * \param data custom data passed to attachment_data_open and attachment_data_filedata_free functions - * \param attachment_data_open function for opening attachment data - * \param attachment_data_read function for reading attachment data - * \param attachment_data_close function for closing attachment data (optional, free() will be used if NULL) - * \param attachment_data_filedata_free function for cleaning up custom data in quickmail_destroy (optional, free() will be used if NULL) - */ -void quickmail_add_body_custom (quickmail mailobj, const char* mimetype, char* data, quickmail_attachment_open_fn attachment_data_open, quickmail_attachment_read_fn attachment_data_read, quickmail_attachment_close_fn attachment_data_close, quickmail_attachment_free_filedata_fn attachment_data_filedata_free); - -/*! \brief remove body from quickmail object - * \param mailobj quickmail object - * \param mimetype MIME type (text/plain will be used if set to NULL) - * \return zero on success - */ -int quickmail_remove_body (quickmail mailobj, const char* mimetype); - -/*! \brief list bodies by calling a callback function for each body - * \param mailobj quickmail object - * \param callback function to call for each attachment - * \param callbackdata custom data to pass to the callback function - * \sa quickmail_list_attachment_callback_fn - */ -void quickmail_list_bodies (quickmail mailobj, quickmail_list_attachment_callback_fn callback, void* callbackdata); - -/*! \brief add a file attachment to a quickmail object - * \param mailobj quickmail object - * \param path path of file to attach - * \param mimetype MIME type of file to attach (application/octet-stream will be used if set to NULL) - */ -void quickmail_add_attachment_file (quickmail mailobj, const char* path, const char* mimetype); - -/*! \brief add an attachment from memory to a quickmail object - * \param mailobj quickmail object - * \param filename name of file to attach (must not include full path) - * \param mimetype MIME type of file to attach (set to NULL for default binary file) - * \param data data content - * \param datalen size of data in bytes - * \param mustfree non-zero if data must be freed by quickmail_destroy - */ -void quickmail_add_attachment_memory (quickmail mailobj, const char* filename, const char* mimetype, char* data, size_t datalen, int mustfree); - -/*! \brief add an attachment with custom read functions to a quickmail object - * \param mailobj quickmail object - * \param filename name of file to attach (must not include full path) - * \param mimetype MIME type of file to attach (set to NULL for default binary file) - * \param data custom data passed to attachment_data_open and attachment_data_filedata_free functions - * \param attachment_data_open function for opening attachment data - * \param attachment_data_read function for reading attachment data - * \param attachment_data_close function for closing attachment data (optional, free() will be used if NULL) - * \param attachment_data_filedata_free function for cleaning up custom data in quickmail_destroy (optional, free() will be used if NULL) - */ -void quickmail_add_attachment_custom (quickmail mailobj, const char* filename, const char* mimetype, char* data, quickmail_attachment_open_fn attachment_data_open, quickmail_attachment_read_fn attachment_data_read, quickmail_attachment_close_fn attachment_data_close, quickmail_attachment_free_filedata_fn attachment_data_filedata_free); - -/*! \brief remove attachment from quickmail object - * \param mailobj quickmail object - * \param filename name of file to attach (must not include full path) - * \return zero on success - */ -int quickmail_remove_attachment (quickmail mailobj, const char* filename); - -/*! \brief list attachments by calling a callback function for each attachment - * \param mailobj quickmail object - * \param callback function to call for each attachment - * \param callbackdata custom data to pass to the callback function - * \sa quickmail_list_attachment_callback_fn - */ -void quickmail_list_attachments (quickmail mailobj, quickmail_list_attachment_callback_fn callback, void* callbackdata); - -/*! \brief set the debug logging destination of a quickmail object - * \param mailobj quickmail object - * \param filehandle file handle of logging destination (or NULL for no logging) - */ -void quickmail_set_debug_log (quickmail mailobj, FILE* filehandle); - -/*! \brief save the generated e-mail to a file - * \param mailobj quickmail object - * \param filehandle file handle to write the e-mail contents to - */ -void quickmail_fsave (quickmail mailobj, FILE* filehandle); - -/*! \brief read data the next data from the e-mail contents (can be used as CURLOPT_READFUNCTION callback function) - * \param buffer buffer to copy data to (bust be able to hold size * nmemb bytes) - * \param size record size - * \param nmemb number of records to copy to \p buffer - * \param mailobj quickmail object - * \return number of bytes copied to \p buffer or 0 if at end - */ -size_t quickmail_get_data (void* buffer, size_t size, size_t nmemb, void* mailobj); - -/*! \brief send the e-mail via SMTP or SMTPS - * \param mailobj quickmail object - * \param smtpserver IP address or hostname of SMTP/SMTPS server - * \param smtpport SMTP/SMTPS port number (normally this is 25) - * \param prptocol protocol type (SMTP or SMTPS) - * \param username username to use for authentication (or NULL if not needed) - * \param password password to use for authentication (or NULL if not needed) - * \return NULL on success or error message on error - */ -const char* quickmail_protocol_send (quickmail mailobj, const char* smtpserver, unsigned int smtpport, int protocol, const char* username, const char* password); - -/*! \brief send the e-mail via SMTP - * \param mailobj quickmail object - * \param smtpserver IP address or hostname of SMTP server - * \param smtpport SMTP port number (normally this is 25) - * \param username username to use for authentication (or NULL if not needed) - * \param password password to use for authentication (or NULL if not needed) - * \return NULL on success or error message on error - */ -const char* quickmail_send (quickmail mailobj, const char* smtpserver, unsigned int smtpport, const char* username, const char* password); - -/*! \brief send the e-mail via SMTPS - * \param mailobj quickmail object - * \param smtpserver IP address or hostname of SMTPS server - * \param smtpport SMTPS port number (normally this is 465) - * \param username username to use for authentication (or NULL if not needed) - * \param password password to use for authentication (or NULL if not needed) - * \return NULL on success or error message on error - */ -const char* quickmail_send_secure (quickmail mailobj, const char* smtpserver, unsigned int smtpport, const char* username, const char* password); - -int quickmail_progress; -int quickmail_verbose; -int quickmail_timeout; - -#ifdef __cplusplus -} -#endif - -#endif //__INCLUDED_QUICKMAIL_H diff --git a/MicroPython_BUILD/firmware/.gitignore b/MicroPython_BUILD/firmware/.gitignore new file mode 100644 index 00000000..9ab087fc --- /dev/null +++ b/MicroPython_BUILD/firmware/.gitignore @@ -0,0 +1,2 @@ + +MicroPython_LoBo_Firmwares.zip diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip index 527f705a..a8143045 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip index a00a0f96..ec4b6741 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_all.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip index 067b4214..e65fc265 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_ota.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip index 09628ee6..9da7e206 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip index 87fb3da3..83970ac2 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all_bt.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all_bt.zip new file mode 100644 index 00000000..ec585d18 Binary files /dev/null and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_all_bt.zip differ diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip index 06e4cc24..d6c0506e 100644 Binary files a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip and b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip differ diff --git a/MicroPython_BUILD/firmware/README.md b/MicroPython_BUILD/firmware/README.md index e9096004..c9e00cf8 100644 --- a/MicroPython_BUILD/firmware/README.md +++ b/MicroPython_BUILD/firmware/README.md @@ -19,8 +19,16 @@ Available firmwares: All firmwares are configured with 1 MB SPIFFS file system.
Telnet server, FTP server, mDNS and Mqtt are enabled. -To flash, use **esptool.py**. +To flash, use **esptool.py**.
+If you don't have it installed, install it using `pip`:
+`pip install esptool` or `pip3 install esptool` -You can use the `flash.sh` script, run it in its directory. +You can use the `flash.sh` script to flash the firmware:
-**Edit the** `flash.sh` **and set the correct usb port for your board.** +Change you working directory to the selected firmware directory (the one containing **MicroPython.bin**) and run: + +``` +../flash.sh -p -b +``` + +`-p` & `-b` options are optional, default port is `/dev/ttyUSB0`, default baud rate is `460800`. diff --git a/MicroPython_BUILD/firmware/README.txt b/MicroPython_BUILD/firmware/README.txt new file mode 100644 index 00000000..940fa4bf --- /dev/null +++ b/MicroPython_BUILD/firmware/README.txt @@ -0,0 +1,39 @@ + +=== Prebuilt firmwares === + + +Default configuration is used. + +Available firmwares: + +------------------------------------------------------------------------------------------------------- +Directory Description +------------------------------------------------------------------------------------------------------- +esp32 MicroPython, single partition layout, 4MB Flash +esp32_ota MicroPython, dual partition layout, OTA enabled, 4MB Flash +esp32_psram MicroPython, single partition layout, 4MB Flash & 4MB SPIRAM +esp32_psram_ota MicroPython, dual partition layout, OTA enabled, 4MB Flash & 4MB SPIRAM +esp32_all MicroPython, single partition layout, 4MB Flash, ALL modules included +esp32_psram_all MicroPython, single partition layout, 4MB Flash & 4MB SPIRAM, ALL modules included +------------------------------------------------------------------------------------------------------- + + +All firmwares are configured with 1 MB SPIFFS file system.
+Telnet server, FTP server, mDNS and Mqtt are enabled. + +To flash, use 'esptool.py'. +If you don't have it installed, install it using `pip`: + +pip install esptool +or +pip3 install esptool + + +You can use the 'flash.sh' script to flash the firmware: + +Change you working directory to the selected firmware directory (the one containing 'MicroPython.bin') and run: + +../flash.sh -p -b + + +-p & -b options are optional, default port is /dev/ttyUSB0, default baud rate is 460800. diff --git a/MicroPython_BUILD/firmware/esp32/MicroPython.bin b/MicroPython_BUILD/firmware/esp32/MicroPython.bin index be4c9568..cf80bb50 100644 Binary files a/MicroPython_BUILD/firmware/esp32/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin index 762dfdce..d98b9dcb 100644 Binary files a/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32/firmware.bin b/MicroPython_BUILD/firmware/esp32/firmware.bin new file mode 100644 index 00000000..25305976 Binary files /dev/null and b/MicroPython_BUILD/firmware/esp32/firmware.bin differ diff --git a/MicroPython_BUILD/firmware/esp32/flash.sh b/MicroPython_BUILD/firmware/esp32/flash.sh deleted file mode 100755 index 39e917a4..00000000 --- a/MicroPython_BUILD/firmware/esp32/flash.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0xf000 phy_init_data.bin 0x10000 MicroPython.bin 0x8000 partitions_mpy.bin diff --git a/MicroPython_BUILD/firmware/esp32/makeimg.py b/MicroPython_BUILD/firmware/esp32/makeimg.py new file mode 100644 index 00000000..e6303836 --- /dev/null +++ b/MicroPython_BUILD/firmware/esp32/makeimg.py @@ -0,0 +1,28 @@ +import sys + +OFFSET_BOOTLOADER = 0x1000 +OFFSET_PARTITIONS = 0x8000 +OFFSET_PHY_INIT_DATA = 0xf000 +OFFSET_APPLICATION = 0x10000 + +files_in = [ + ('bootloader', OFFSET_BOOTLOADER, 'bootloader/bootloader.bin'), + ('partitions', OFFSET_PARTITIONS, 'partitions_mpy.bin'), + ('phy_init_data', OFFSET_PHY_INIT_DATA, 'phy_init_data.bin'), + ('application', OFFSET_APPLICATION, 'MicroPython.bin'), +] +# file_out = sys.argv[1] +file_out = 'firmware.bin' + +cur_offset = OFFSET_BOOTLOADER +with open(file_out, 'wb') as fout: + for name, offset, file_in in files_in: + assert offset >= cur_offset + fout.write(b'\xff' * (offset - cur_offset)) + cur_offset = offset + with open(file_in, 'rb') as fin: + data = fin.read() + fout.write(data) + cur_offset += len(data) + print('%-12s% 8d' % (name, len(data))) + print('%-12s% 8d' % ('total', cur_offset)) diff --git a/MicroPython_BUILD/firmware/esp32/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32/partitions_mpy.bin index 0f2a28ed..6b11b17e 100644 Binary files a/MicroPython_BUILD/firmware/esp32/partitions_mpy.bin and b/MicroPython_BUILD/firmware/esp32/partitions_mpy.bin differ diff --git a/MicroPython_BUILD/firmware/esp32/partitions_mpy.csv b/MicroPython_BUILD/firmware/esp32/partitions_mpy.csv index 32598216..ba0b1167 100644 --- a/MicroPython_BUILD/firmware/esp32/partitions_mpy.csv +++ b/MicroPython_BUILD/firmware/esp32/partitions_mpy.csv @@ -1,9 +1,9 @@ # ------------------------------------------------------- -# - Partition layout generaded by BUILD.sh script - +# - Partition layout generated by BUILD.sh script - # ------------------------------------------------------- # Name, Type, SubType, Offset, Size, Flags # ------------------------------------------------------- nvs, data, nvs, 0x9000, 24K, phy_init, data, phy, 0xf000, 4K, -MicroPython, app, factory, 0x10000, 1344K, -internalfs, data, spiffs, , 1024K, +MicroPython, app, factory, 0x10000, 1408K, +internalfs, data, spiffs, , 2624K, diff --git a/MicroPython_BUILD/firmware/esp32/sdkconfig b/MicroPython_BUILD/firmware/esp32/sdkconfig index f3c57030..1a32e9df 100644 --- a/MicroPython_BUILD/firmware/esp32/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32/sdkconfig @@ -20,7 +20,10 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= CONFIG_LOG_BOOTLOADER_LEVEL=3 -CONFIG_BOOTLOADER_VDDSDIO_BOOST=y +CONFIG_BOOTLOADER_SPI_WP_PIN=7 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= # # Security features @@ -40,16 +43,16 @@ CONFIG_ESPTOOLPY_BAUD_OTHER= CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 CONFIG_ESPTOOLPY_BAUD=921600 CONFIG_ESPTOOLPY_COMPRESSED=y -CONFIG_FLASHMODE_QIO= +CONFIG_FLASHMODE_QIO=y CONFIG_FLASHMODE_QOUT= -CONFIG_FLASHMODE_DIO=y +CONFIG_FLASHMODE_DIO= CONFIG_FLASHMODE_DOUT= CONFIG_ESPTOOLPY_FLASHMODE="dio" -CONFIG_ESPTOOLPY_FLASHFREQ_80M= -CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHFREQ_40M= CONFIG_ESPTOOLPY_FLASHFREQ_26M= CONFIG_ESPTOOLPY_FLASHFREQ_20M= -CONFIG_ESPTOOLPY_FLASHFREQ="40m" +CONFIG_ESPTOOLPY_FLASHFREQ="80m" CONFIG_ESPTOOLPY_FLASHSIZE_1MB= CONFIG_ESPTOOLPY_FLASHSIZE_2MB= CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y @@ -76,88 +79,82 @@ CONFIG_MONITOR_BAUD=115200 # # MicroPython # -CONFIG_MICROPY_HW_BOARD_NAME="ESP32 board" +CONFIG_MICROPY_HW_BOARD_NAME="M5Stack" CONFIG_MICROPY_HW_MCU_NAME="ESP32" CONFIG_MICROPY_TIMEZONE="GMT0BST" CONFIG_MICROPY_USE_OTA= +CONFIG_BOOT_SET_LED=-1 # # System settings # -CONFIG_MICRO_PY_LOG_LEVEL=2 +CONFIG_MICRO_PY_LOG_LEVEL=3 CONFIG_MICRO_PY_LOG_LEVEL0= CONFIG_MICRO_PY_LOG_LEVEL1= -CONFIG_MICRO_PY_LOG_LEVEL2=y -CONFIG_MICRO_PY_LOG_LEVEL3= +CONFIG_MICRO_PY_LOG_LEVEL2= +CONFIG_MICRO_PY_LOG_LEVEL3=y CONFIG_MICRO_PY_LOG_LEVEL4= CONFIG_MICRO_PY_LOG_LEVEL5= +CONFIG_MICROPY_USE_TASK_WDT= +CONFIG_MICROPY_USE_UNICODE=y +CONFIG_MICROPY_ENABLE_FINALISER=y +CONFIG_MICROPY_GC_COLLECT_RETVAL= +CONFIG_MICROPY_GC_SET_THRESHOLD=y +CONFIG_MICROPY_GC_THRESHOLD_VALUE=80 +CONFIG_MICROPY_SCHEDULER_DEPTH=8 +CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR=32 CONFIG_MICROPY_RX_BUFFER_SIZE=1080 -CONFIG_MICROPY_USE_TASK_WDT=y -CONFIG_MICROPY_USE_BOTH_CORES= +CONFIG_MICROPY_USE_BOTH_CORES=y CONFIG_MICROPY_TASK_PRIORITY=5 -CONFIG_MICROPY_STACK_SIZE=20 +CONFIG_MICROPY_STACK_SIZE=15 CONFIG_MICROPY_HEAP_SIZE=80 -CONFIG_MICROPY_THREAD_MAX_THREADS=4 -CONFIG_MICROPY_THREAD_STACK_SIZE=4 -CONFIG_MICROPY_USE_TELNET=y +CONFIG_MICROPY_THREAD_MAX_THREADS=3 +CONFIG_MICROPY_THREAD_STACK_SIZE=6 +CONFIG_MICROPY_USE_TELNET= CONFIG_MICROPY_USE_WEBSERVER= -CONFIG_MICROPY_USE_FTPSERVER=y - -# -# FTP Server Configuration -# -CONFIG_FTPSERVER_LOG_LEVEL=1 -CONFIG_FTPSERVER_LOG_LEVEL0= -CONFIG_FTPSERVER_LOG_LEVEL1=y -CONFIG_FTPSERVER_LOG_LEVEL2= -CONFIG_FTPSERVER_LOG_LEVEL3= -CONFIG_FTPSERVER_LOG_LEVEL4= -CONFIG_MICROPY_FTPSERVER_TIMEOUT=300 -CONFIG_MICROPY_FTPSERVER_BUFFER_SIZE=1024 +CONFIG_MICROPY_USE_FTPSERVER= # # Modules # -CONFIG_MICROPY_PY_FRAMEBUF=y -CONFIG_MICROPY_PY_USE_BTREE= -CONFIG_MICROPY_USE_WEBSOCKETS= +CONFIG_MICROPY_PY_FRAMEBUF= +CONFIG_MICROPY_PY_USE_BTREE=y +CONFIG_MICROPY_USE_WEBSOCKETS=y CONFIG_MICROPY_USE_DISPLAY=y +CONFIG_MICROPY_USE_TFT=y +CONFIG_MICROPY_USE_EPD= CONFIG_MICROPY_USE_EVE= CONFIG_MICROPY_USE_GSM= +CONFIG_MICROPY_USE_GPS= CONFIG_MICROPY_USE_ETHERNET= -CONFIG_MICROPY_USE_MDNS=y +CONFIG_MICROPY_USE_MDNS= +CONFIG_MICROPY_USE_REQUESTS= CONFIG_MICROPY_USE_CURL= CONFIG_MICROPY_USE_SSH= -CONFIG_MICROPY_USE_MQTT=y - -# -# MQTT Configuration -# -CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_PRIORITY=5 -CONFIG_MQTT_BUFFER_SIZE_BYTE=256 -CONFIG_MQTT_MAX_PAYLOAD_SIZE=2048 -CONFIG_MQTT_LOG_LEVEL=1 -CONFIG_MQTT_LOG_LEVEL0= -CONFIG_MQTT_LOG_LEVEL1=y -CONFIG_MQTT_LOG_LEVEL2= -CONFIG_MQTT_LOG_LEVEL3= -CONFIG_MQTT_LOG_LEVEL4= +CONFIG_MICROPY_USE_MQTT= # # File systems # -CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=6 -CONFIG_MICROPY_USE_SPIFFS=y +CONFIG_MICROPY_FILESYSTEM_TYPE=0 +CONFIG_MICROPY_FS_TYPE0=y +CONFIG_MICROPY_FS_TYPE1= +CONFIG_MICROPY_FS_TYPE2= +CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=4 CONFIG_MICROPY_SDMMC_SHOW_INFO=y # # SD Card configuration # -CONFIG_SDCARD_MODE=3 -CONFIG_SDCARD_MODE1= +CONFIG_SDCARD_MODE=1 +CONFIG_SDCARD_MODE1=y CONFIG_SDCARD_MODE2= -CONFIG_SDCARD_MODE3=y +CONFIG_SDCARD_MODE3= +CONFIG_SDMMC_ALLOW_SPI_HIGHSPEED=y +CONFIG_SDCARD_CLK=18 +CONFIG_SDCARD_MOSI=23 +CONFIG_SDCARD_MISO=19 +CONFIG_SDCARD_CS=4 # # Partition Table @@ -166,11 +163,8 @@ CONFIG_PARTITION_TABLE_SINGLE_APP= CONFIG_PARTITION_TABLE_TWO_OTA= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_mpy.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 -CONFIG_PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET=0xf000 CONFIG_PARTITION_TABLE_FILENAME="partitions_mpy.csv" -CONFIG_APP_OFFSET=0x10000 -CONFIG_PHY_DATA_OFFSET=0xf000 +CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # @@ -187,6 +181,7 @@ CONFIG_STACK_CHECK_NORM= CONFIG_STACK_CHECK_STRONG= CONFIG_STACK_CHECK_ALL= CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= # # Component config @@ -199,10 +194,6 @@ CONFIG_ESP32_APPTRACE_DEST_TRAX= CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_ENABLE= CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y - -# -# FreeRTOS SystemView Tracing -# CONFIG_AWS_IOT_SDK= # @@ -212,6 +203,22 @@ CONFIG_BT_ENABLED= CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BT_RESERVE_DRAM=0 +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI master configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y + # # ESP32-specific # @@ -219,7 +226,6 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_MEMMAP_SMP=y CONFIG_SPIRAM_SUPPORT= CONFIG_MEMMAP_TRACEMEM= CONFIG_MEMMAP_TRACEMEM_TWOBANKS= @@ -233,7 +239,7 @@ CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2048 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 CONFIG_MAIN_TASK_STACK_SIZE=3584 CONFIG_IPC_TASK_STACK_SIZE=1024 CONFIG_TIMER_TASK_STACK_SIZE=3584 @@ -256,6 +262,7 @@ CONFIG_ESP32_PANIC_PRINT_REBOOT= CONFIG_ESP32_PANIC_SILENT_REBOOT= CONFIG_ESP32_PANIC_GDBSTUB= CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y CONFIG_INT_WDT=y CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_INT_WDT_CHECK_CPU1=y @@ -290,21 +297,25 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE= CONFIG_NO_BLOBS= CONFIG_ESP_TIMER_PROFILING= CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # # Wi-Fi # CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 -CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER= +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED= CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= # # PHY @@ -326,6 +337,11 @@ CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y CONFIG_ADC_CAL_LUT_ENABLE=y +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + # # Ethernet # @@ -364,6 +380,9 @@ CONFIG_FATFS_LFN_NONE= CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_STACK= CONFIG_FATFS_MAX_LFN=127 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_API_ENCODING_UTF_16= +CONFIG_FATFS_API_ENCODING_UTF_8= CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE= @@ -385,7 +404,7 @@ CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=4 CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= CONFIG_FREERTOS_ASSERT_DISABLE= -CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 CONFIG_FREERTOS_ISR_STACKSIZE=4096 CONFIG_FREERTOS_LEGACY_HOOKS= CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 @@ -417,11 +436,11 @@ CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y # CONFIG_LOG_DEFAULT_LEVEL_NONE= CONFIG_LOG_DEFAULT_LEVEL_ERROR= -CONFIG_LOG_DEFAULT_LEVEL_WARN= +CONFIG_LOG_DEFAULT_LEVEL_WARN=y CONFIG_LOG_DEFAULT_LEVEL_INFO= -CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG= CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= -CONFIG_LOG_DEFAULT_LEVEL=4 +CONFIG_LOG_DEFAULT_LEVEL=2 CONFIG_LOG_COLORS=y # @@ -430,6 +449,7 @@ CONFIG_LOG_COLORS=y CONFIG_L2_TO_L3_COPY= CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 +CONFIG_USE_ONLY_LWIP_SELECT= CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y CONFIG_LWIP_SO_RCVBUF= @@ -463,6 +483,7 @@ CONFIG_TCP_SND_BUF_DEFAULT=5744 CONFIG_TCP_WND_DEFAULT=5744 CONFIG_TCP_RECVMBOX_SIZE=6 CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= CONFIG_TCP_OVERSIZE_MSS=y CONFIG_TCP_OVERSIZE_QUARTER_MSS= CONFIG_TCP_OVERSIZE_DISABLE= @@ -494,7 +515,7 @@ CONFIG_LWIP_MAX_RAW_PCBS=16 # # mbedTLS # -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=8192 CONFIG_MBEDTLS_DEBUG= CONFIG_MBEDTLS_HARDWARE_AES=y CONFIG_MBEDTLS_HARDWARE_MPI= @@ -628,6 +649,11 @@ CONFIG_SPIFFS_TEST_VISUALISATION= # CONFIG_IP_LOST_TIMER_INTERVAL=120 +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y + # # Wear Levelling # diff --git a/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin index ca6f0c6b..bdfbcac3 100644 Binary files a/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin index d51b4cd2..1af8d951 100644 Binary files a/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_all/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_all/flash.sh b/MicroPython_BUILD/firmware/esp32_all/flash.sh deleted file mode 100755 index 39e917a4..00000000 --- a/MicroPython_BUILD/firmware/esp32_all/flash.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0xf000 phy_init_data.bin 0x10000 MicroPython.bin 0x8000 partitions_mpy.bin diff --git a/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.bin index f37f3bfa..869be0be 100644 Binary files a/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.bin and b/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.csv b/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.csv new file mode 100644 index 00000000..dbeb22e8 --- /dev/null +++ b/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.csv @@ -0,0 +1,9 @@ +# ------------------------------------------------------- +# - Partition layout generated by BUILD.sh script - +# ------------------------------------------------------- +# Name, Type, SubType, Offset, Size, Flags +# ------------------------------------------------------- +nvs, data, nvs, 0x9000, 24K, +phy_init, data, phy, 0xf000, 4K, +MicroPython, app, factory, 0x10000, 1984K, +internalfs, data, spiffs, , 1024K, diff --git a/MicroPython_BUILD/firmware/esp32_all/sdkconfig b/MicroPython_BUILD/firmware/esp32_all/sdkconfig index 7d0197ff..dc3b2ef5 100644 --- a/MicroPython_BUILD/firmware/esp32_all/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_all/sdkconfig @@ -20,7 +20,10 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= CONFIG_LOG_BOOTLOADER_LEVEL=3 -CONFIG_BOOTLOADER_VDDSDIO_BOOST=y +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= # # Security features @@ -80,6 +83,7 @@ CONFIG_MICROPY_HW_BOARD_NAME="ESP32 board" CONFIG_MICROPY_HW_MCU_NAME="ESP32" CONFIG_MICROPY_TIMEZONE="GMT0BST" CONFIG_MICROPY_USE_OTA= +CONFIG_BOOT_SET_LED=-1 # # System settings @@ -91,8 +95,16 @@ CONFIG_MICRO_PY_LOG_LEVEL2=y CONFIG_MICRO_PY_LOG_LEVEL3= CONFIG_MICRO_PY_LOG_LEVEL4= CONFIG_MICRO_PY_LOG_LEVEL5= -CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_TASK_WDT=y +CONFIG_MICROPY_TASK_WDT_PANIC= +CONFIG_MICROPY_USE_UNICODE=y +CONFIG_MICROPY_ENABLE_FINALISER=y +CONFIG_MICROPY_GC_COLLECT_RETVAL= +CONFIG_MICROPY_GC_SET_THRESHOLD=y +CONFIG_MICROPY_GC_THRESHOLD_VALUE=90 +CONFIG_MICROPY_SCHEDULER_DEPTH=8 +CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR=32 +CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_BOTH_CORES= CONFIG_MICROPY_TASK_PRIORITY=5 CONFIG_MICROPY_STACK_SIZE=20 @@ -122,14 +134,19 @@ CONFIG_MICROPY_PY_FRAMEBUF=y CONFIG_MICROPY_PY_USE_BTREE=y CONFIG_MICROPY_USE_WEBSOCKETS=y CONFIG_MICROPY_USE_DISPLAY=y +CONFIG_MICROPY_USE_TFT=y +CONFIG_MICROPY_USE_EPD= CONFIG_MICROPY_USE_EVE= CONFIG_MICROPY_USE_GSM=y +CONFIG_MICROPY_USE_GPS=y +CONFIG_MICROPY_GPS_SERVICE_STACK=3072 CONFIG_MICROPY_USE_ETHERNET= CONFIG_MICROPY_USE_MDNS=y +CONFIG_MICROPY_USE_REQUESTS=y CONFIG_MICROPY_USE_CURL=y +CONFIG_MICROPY_CURL_MAX_WRITE_SIZE=8192 CONFIG_MICROPY_USE_CURL_TLS=y CONFIG_MICROPY_USE_CURLFTP=y -CONFIG_MICROPY_USE_MAIL=y CONFIG_MICROPY_USE_SSH=y CONFIG_MICROPY_USE_MQTT=y @@ -137,9 +154,10 @@ CONFIG_MICROPY_USE_MQTT=y # MQTT Configuration # CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_PRIORITY=5 -CONFIG_MQTT_BUFFER_SIZE_BYTE=256 -CONFIG_MQTT_MAX_PAYLOAD_SIZE=2048 +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= CONFIG_MQTT_LOG_LEVEL=1 CONFIG_MQTT_LOG_LEVEL0= CONFIG_MQTT_LOG_LEVEL1=y @@ -150,8 +168,11 @@ CONFIG_MQTT_LOG_LEVEL4= # # File systems # +CONFIG_MICROPY_FILESYSTEM_TYPE=0 +CONFIG_MICROPY_FS_TYPE0=y +CONFIG_MICROPY_FS_TYPE1= +CONFIG_MICROPY_FS_TYPE2= CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=6 -CONFIG_MICROPY_USE_SPIFFS=y CONFIG_MICROPY_SDMMC_SHOW_INFO=y # @@ -161,6 +182,7 @@ CONFIG_SDCARD_MODE=3 CONFIG_SDCARD_MODE1= CONFIG_SDCARD_MODE2= CONFIG_SDCARD_MODE3=y +CONFIG_SDMMC_ALLOW_SPI_HIGHSPEED= # # Partition Table @@ -169,11 +191,8 @@ CONFIG_PARTITION_TABLE_SINGLE_APP= CONFIG_PARTITION_TABLE_TWO_OTA= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_mpy.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 -CONFIG_PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET=0xf000 CONFIG_PARTITION_TABLE_FILENAME="partitions_mpy.csv" -CONFIG_APP_OFFSET=0x10000 -CONFIG_PHY_DATA_OFFSET=0xf000 +CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # @@ -190,6 +209,7 @@ CONFIG_STACK_CHECK_NORM= CONFIG_STACK_CHECK_STRONG= CONFIG_STACK_CHECK_ALL= CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= # # Component config @@ -202,10 +222,6 @@ CONFIG_ESP32_APPTRACE_DEST_TRAX= CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_ENABLE= CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y - -# -# FreeRTOS SystemView Tracing -# CONFIG_AWS_IOT_SDK= # @@ -215,6 +231,22 @@ CONFIG_BT_ENABLED= CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BT_RESERVE_DRAM=0 +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI master configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y + # # ESP32-specific # @@ -222,7 +254,6 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_MEMMAP_SMP=y CONFIG_SPIRAM_SUPPORT= CONFIG_MEMMAP_TRACEMEM= CONFIG_MEMMAP_TRACEMEM_TWOBANKS= @@ -259,6 +290,7 @@ CONFIG_ESP32_PANIC_PRINT_REBOOT= CONFIG_ESP32_PANIC_SILENT_REBOOT= CONFIG_ESP32_PANIC_GDBSTUB= CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y CONFIG_INT_WDT=y CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_INT_WDT_CHECK_CPU1=y @@ -293,6 +325,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE= CONFIG_NO_BLOBS= CONFIG_ESP_TIMER_PROFILING= CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # # Wi-Fi @@ -303,11 +336,14 @@ CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED= CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= # # PHY @@ -329,6 +365,11 @@ CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y CONFIG_ADC_CAL_LUT_ENABLE=y +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + # # Ethernet # @@ -367,6 +408,9 @@ CONFIG_FATFS_LFN_NONE= CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_STACK= CONFIG_FATFS_MAX_LFN=127 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_API_ENCODING_UTF_16= +CONFIG_FATFS_API_ENCODING_UTF_8= CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE= @@ -433,6 +477,7 @@ CONFIG_LOG_COLORS=y CONFIG_L2_TO_L3_COPY= CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 +CONFIG_USE_ONLY_LWIP_SELECT= CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y CONFIG_LWIP_SO_RCVBUF= @@ -466,6 +511,7 @@ CONFIG_TCP_SND_BUF_DEFAULT=5744 CONFIG_TCP_WND_DEFAULT=5744 CONFIG_TCP_RECVMBOX_SIZE=6 CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= CONFIG_TCP_OVERSIZE_MSS=y CONFIG_TCP_OVERSIZE_QUARTER_MSS= CONFIG_TCP_OVERSIZE_DISABLE= @@ -497,7 +543,7 @@ CONFIG_LWIP_MAX_RAW_PCBS=16 # # mbedTLS # -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=8192 CONFIG_MBEDTLS_DEBUG= CONFIG_MBEDTLS_HARDWARE_AES=y CONFIG_MBEDTLS_HARDWARE_MPI= @@ -631,6 +677,11 @@ CONFIG_SPIFFS_TEST_VISUALISATION= # CONFIG_IP_LOST_TIMER_INTERVAL=120 +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y + # # Wear Levelling # diff --git a/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin index 3075bfdf..8d7e5eb2 100644 Binary files a/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin index a30c9432..0174f5f0 100644 Binary files a/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_ota/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_ota/flash.sh b/MicroPython_BUILD/firmware/esp32_ota/flash.sh deleted file mode 100755 index 39e917a4..00000000 --- a/MicroPython_BUILD/firmware/esp32_ota/flash.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0xf000 phy_init_data.bin 0x10000 MicroPython.bin 0x8000 partitions_mpy.bin diff --git a/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.bin index 92f62ab8..a953fef3 100644 Binary files a/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.bin and b/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.csv b/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.csv index 48e0d8d5..c88305b4 100644 --- a/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.csv +++ b/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.csv @@ -1,11 +1,11 @@ # ------------------------------------------------------- -# - Partition layout generaded by BUILD.sh script - +# - Partition layout generated by BUILD.sh script - # ------------------------------------------------------- # Name, Type, SubType, Offset, Size, Flags # ------------------------------------------------------- nvs, data, nvs, 0x9000, 16K, otadata, data, ota, 0xd000, 8K, phy_init, data, phy, 0xf000, 4K, -MicroPython_1, app, ota_0, 0x10000, 1344K, -MicroPython_2, app, ota_1, , 1344K, -internalfs, data, spiffs, , 1024K, +MicroPython_1, app, ota_0, 0x10000, 1536K, +MicroPython_2, app, ota_1, , 1536K, +internalfs, data, spiffs, , 960K, diff --git a/MicroPython_BUILD/firmware/esp32_ota/sdkconfig b/MicroPython_BUILD/firmware/esp32_ota/sdkconfig index 108b67c8..a6066aef 100644 --- a/MicroPython_BUILD/firmware/esp32_ota/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_ota/sdkconfig @@ -20,7 +20,10 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= CONFIG_LOG_BOOTLOADER_LEVEL=3 -CONFIG_BOOTLOADER_VDDSDIO_BOOST=y +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= # # Security features @@ -81,6 +84,7 @@ CONFIG_MICROPY_HW_MCU_NAME="ESP32" CONFIG_MICROPY_TIMEZONE="GMT0BST" CONFIG_MICROPY_USE_OTA=y CONFIG_GPIO_INPUT_FORCE_FACTORY= +CONFIG_BOOT_SET_LED=-1 # # System settings @@ -92,8 +96,16 @@ CONFIG_MICRO_PY_LOG_LEVEL2=y CONFIG_MICRO_PY_LOG_LEVEL3= CONFIG_MICRO_PY_LOG_LEVEL4= CONFIG_MICRO_PY_LOG_LEVEL5= -CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_TASK_WDT=y +CONFIG_MICROPY_TASK_WDT_PANIC= +CONFIG_MICROPY_USE_UNICODE=y +CONFIG_MICROPY_ENABLE_FINALISER=y +CONFIG_MICROPY_GC_COLLECT_RETVAL= +CONFIG_MICROPY_GC_SET_THRESHOLD=y +CONFIG_MICROPY_GC_THRESHOLD_VALUE=90 +CONFIG_MICROPY_SCHEDULER_DEPTH=8 +CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR=32 +CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_BOTH_CORES= CONFIG_MICROPY_TASK_PRIORITY=5 CONFIG_MICROPY_STACK_SIZE=20 @@ -123,10 +135,15 @@ CONFIG_MICROPY_PY_FRAMEBUF=y CONFIG_MICROPY_PY_USE_BTREE= CONFIG_MICROPY_USE_WEBSOCKETS= CONFIG_MICROPY_USE_DISPLAY=y +CONFIG_MICROPY_USE_TFT=y +CONFIG_MICROPY_USE_EPD= CONFIG_MICROPY_USE_EVE= CONFIG_MICROPY_USE_GSM= +CONFIG_MICROPY_USE_GPS=y +CONFIG_MICROPY_GPS_SERVICE_STACK=3072 CONFIG_MICROPY_USE_ETHERNET= CONFIG_MICROPY_USE_MDNS=y +CONFIG_MICROPY_USE_REQUESTS=y CONFIG_MICROPY_USE_CURL= CONFIG_MICROPY_USE_SSH= CONFIG_MICROPY_USE_MQTT=y @@ -135,9 +152,10 @@ CONFIG_MICROPY_USE_MQTT=y # MQTT Configuration # CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_PRIORITY=5 -CONFIG_MQTT_BUFFER_SIZE_BYTE=256 -CONFIG_MQTT_MAX_PAYLOAD_SIZE=2048 +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= CONFIG_MQTT_LOG_LEVEL=1 CONFIG_MQTT_LOG_LEVEL0= CONFIG_MQTT_LOG_LEVEL1=y @@ -148,8 +166,11 @@ CONFIG_MQTT_LOG_LEVEL4= # # File systems # +CONFIG_MICROPY_FILESYSTEM_TYPE=0 +CONFIG_MICROPY_FS_TYPE0=y +CONFIG_MICROPY_FS_TYPE1= +CONFIG_MICROPY_FS_TYPE2= CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=6 -CONFIG_MICROPY_USE_SPIFFS=y CONFIG_MICROPY_SDMMC_SHOW_INFO=y # @@ -159,6 +180,7 @@ CONFIG_SDCARD_MODE=3 CONFIG_SDCARD_MODE1= CONFIG_SDCARD_MODE2= CONFIG_SDCARD_MODE3=y +CONFIG_SDMMC_ALLOW_SPI_HIGHSPEED= # # Partition Table @@ -167,11 +189,8 @@ CONFIG_PARTITION_TABLE_SINGLE_APP= CONFIG_PARTITION_TABLE_TWO_OTA= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_mpy.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 -CONFIG_PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET=0xf000 CONFIG_PARTITION_TABLE_FILENAME="partitions_mpy.csv" -CONFIG_APP_OFFSET=0x10000 -CONFIG_PHY_DATA_OFFSET=0xf000 +CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # @@ -188,6 +207,7 @@ CONFIG_STACK_CHECK_NORM= CONFIG_STACK_CHECK_STRONG= CONFIG_STACK_CHECK_ALL= CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= # # Component config @@ -200,10 +220,6 @@ CONFIG_ESP32_APPTRACE_DEST_TRAX= CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_ENABLE= CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y - -# -# FreeRTOS SystemView Tracing -# CONFIG_AWS_IOT_SDK= # @@ -213,6 +229,22 @@ CONFIG_BT_ENABLED= CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BT_RESERVE_DRAM=0 +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI master configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y + # # ESP32-specific # @@ -220,7 +252,6 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_MEMMAP_SMP=y CONFIG_SPIRAM_SUPPORT= CONFIG_MEMMAP_TRACEMEM= CONFIG_MEMMAP_TRACEMEM_TWOBANKS= @@ -257,6 +288,7 @@ CONFIG_ESP32_PANIC_PRINT_REBOOT= CONFIG_ESP32_PANIC_SILENT_REBOOT= CONFIG_ESP32_PANIC_GDBSTUB= CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y CONFIG_INT_WDT=y CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_INT_WDT_CHECK_CPU1=y @@ -291,6 +323,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE= CONFIG_NO_BLOBS= CONFIG_ESP_TIMER_PROFILING= CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # # Wi-Fi @@ -301,11 +334,14 @@ CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED= CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= # # PHY @@ -327,6 +363,11 @@ CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y CONFIG_ADC_CAL_LUT_ENABLE=y +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + # # Ethernet # @@ -365,6 +406,9 @@ CONFIG_FATFS_LFN_NONE= CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_STACK= CONFIG_FATFS_MAX_LFN=127 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_API_ENCODING_UTF_16= +CONFIG_FATFS_API_ENCODING_UTF_8= CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE= @@ -431,6 +475,7 @@ CONFIG_LOG_COLORS=y CONFIG_L2_TO_L3_COPY= CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 +CONFIG_USE_ONLY_LWIP_SELECT= CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y CONFIG_LWIP_SO_RCVBUF= @@ -464,6 +509,7 @@ CONFIG_TCP_SND_BUF_DEFAULT=5744 CONFIG_TCP_WND_DEFAULT=5744 CONFIG_TCP_RECVMBOX_SIZE=6 CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= CONFIG_TCP_OVERSIZE_MSS=y CONFIG_TCP_OVERSIZE_QUARTER_MSS= CONFIG_TCP_OVERSIZE_DISABLE= @@ -495,7 +541,7 @@ CONFIG_LWIP_MAX_RAW_PCBS=16 # # mbedTLS # -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=8192 CONFIG_MBEDTLS_DEBUG= CONFIG_MBEDTLS_HARDWARE_AES=y CONFIG_MBEDTLS_HARDWARE_MPI= @@ -629,6 +675,11 @@ CONFIG_SPIFFS_TEST_VISUALISATION= # CONFIG_IP_LOST_TIMER_INTERVAL=120 +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y + # # Wear Levelling # diff --git a/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin index 3f6e1b5e..fa5a7d6f 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin index 4544dfb2..350d9067 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram/flash.sh b/MicroPython_BUILD/firmware/esp32_psram/flash.sh deleted file mode 100755 index 39e917a4..00000000 --- a/MicroPython_BUILD/firmware/esp32_psram/flash.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0xf000 phy_init_data.bin 0x10000 MicroPython.bin 0x8000 partitions_mpy.bin diff --git a/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.bin index 4d9423a1..53fe8f10 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.bin and b/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.csv b/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.csv index d27de0f2..064fc95b 100644 --- a/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.csv +++ b/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.csv @@ -1,9 +1,9 @@ # ------------------------------------------------------- -# - Partition layout generaded by BUILD.sh script - +# - Partition layout generated by BUILD.sh script - # ------------------------------------------------------- # Name, Type, SubType, Offset, Size, Flags # ------------------------------------------------------- nvs, data, nvs, 0x9000, 24K, phy_init, data, phy, 0xf000, 4K, -MicroPython, app, factory, 0x10000, 1472K, +MicroPython, app, factory, 0x10000, 1664K, internalfs, data, spiffs, , 1024K, diff --git a/MicroPython_BUILD/firmware/esp32_psram/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram/sdkconfig index 4942e39f..267c650e 100644 --- a/MicroPython_BUILD/firmware/esp32_psram/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_psram/sdkconfig @@ -20,7 +20,10 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= CONFIG_LOG_BOOTLOADER_LEVEL=3 -CONFIG_BOOTLOADER_VDDSDIO_BOOST=y +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= # # Security features @@ -80,6 +83,7 @@ CONFIG_MICROPY_HW_BOARD_NAME="ESP32 board" CONFIG_MICROPY_HW_MCU_NAME="ESP32" CONFIG_MICROPY_TIMEZONE="GMT0BST" CONFIG_MICROPY_USE_OTA= +CONFIG_BOOT_SET_LED=-1 # # System settings @@ -91,8 +95,16 @@ CONFIG_MICRO_PY_LOG_LEVEL2=y CONFIG_MICRO_PY_LOG_LEVEL3= CONFIG_MICRO_PY_LOG_LEVEL4= CONFIG_MICRO_PY_LOG_LEVEL5= -CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_TASK_WDT=y +CONFIG_MICROPY_TASK_WDT_PANIC= +CONFIG_MICROPY_USE_UNICODE=y +CONFIG_MICROPY_ENABLE_FINALISER=y +CONFIG_MICROPY_GC_COLLECT_RETVAL= +CONFIG_MICROPY_GC_SET_THRESHOLD=y +CONFIG_MICROPY_GC_THRESHOLD_VALUE=90 +CONFIG_MICROPY_SCHEDULER_DEPTH=8 +CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR=32 +CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_BOTH_CORES= CONFIG_MICROPY_TASK_PRIORITY=5 CONFIG_MICROPY_STACK_SIZE=20 @@ -122,10 +134,15 @@ CONFIG_MICROPY_PY_FRAMEBUF=y CONFIG_MICROPY_PY_USE_BTREE= CONFIG_MICROPY_USE_WEBSOCKETS= CONFIG_MICROPY_USE_DISPLAY=y +CONFIG_MICROPY_USE_TFT=y +CONFIG_MICROPY_USE_EPD= CONFIG_MICROPY_USE_EVE= CONFIG_MICROPY_USE_GSM= +CONFIG_MICROPY_USE_GPS=y +CONFIG_MICROPY_GPS_SERVICE_STACK=3072 CONFIG_MICROPY_USE_ETHERNET= CONFIG_MICROPY_USE_MDNS=y +CONFIG_MICROPY_USE_REQUESTS=y CONFIG_MICROPY_USE_CURL= CONFIG_MICROPY_USE_SSH= CONFIG_MICROPY_USE_MQTT=y @@ -134,9 +151,10 @@ CONFIG_MICROPY_USE_MQTT=y # MQTT Configuration # CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_PRIORITY=5 -CONFIG_MQTT_BUFFER_SIZE_BYTE=256 -CONFIG_MQTT_MAX_PAYLOAD_SIZE=2048 +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= CONFIG_MQTT_LOG_LEVEL=1 CONFIG_MQTT_LOG_LEVEL0= CONFIG_MQTT_LOG_LEVEL1=y @@ -147,8 +165,11 @@ CONFIG_MQTT_LOG_LEVEL4= # # File systems # +CONFIG_MICROPY_FILESYSTEM_TYPE=0 +CONFIG_MICROPY_FS_TYPE0=y +CONFIG_MICROPY_FS_TYPE1= +CONFIG_MICROPY_FS_TYPE2= CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=6 -CONFIG_MICROPY_USE_SPIFFS=y CONFIG_MICROPY_SDMMC_SHOW_INFO=y # @@ -158,6 +179,7 @@ CONFIG_SDCARD_MODE=3 CONFIG_SDCARD_MODE1= CONFIG_SDCARD_MODE2= CONFIG_SDCARD_MODE3=y +CONFIG_SDMMC_ALLOW_SPI_HIGHSPEED= # # Partition Table @@ -166,11 +188,8 @@ CONFIG_PARTITION_TABLE_SINGLE_APP= CONFIG_PARTITION_TABLE_TWO_OTA= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_mpy.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 -CONFIG_PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET=0xf000 CONFIG_PARTITION_TABLE_FILENAME="partitions_mpy.csv" -CONFIG_APP_OFFSET=0x10000 -CONFIG_PHY_DATA_OFFSET=0xf000 +CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # @@ -187,6 +206,7 @@ CONFIG_STACK_CHECK_NORM= CONFIG_STACK_CHECK_STRONG= CONFIG_STACK_CHECK_ALL= CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= # # Component config @@ -199,10 +219,6 @@ CONFIG_ESP32_APPTRACE_DEST_TRAX= CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_ENABLE= CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y - -# -# FreeRTOS SystemView Tracing -# CONFIG_AWS_IOT_SDK= # @@ -212,6 +228,22 @@ CONFIG_BT_ENABLED= CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BT_RESERVE_DRAM=0 +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI master configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y + # # ESP32-specific # @@ -219,26 +251,22 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_MEMMAP_SMP=y CONFIG_SPIRAM_SUPPORT=y # # SPI RAM config # CONFIG_SPIRAM_BOOT_INIT=y -CONFIG_SPIRAM_IGNORE_NOTFOUND= +CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_USE_MEMMAP= -CONFIG_SPIRAM_USE_CAPS_ALLOC= -CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC= CONFIG_SPIRAM_TYPE_ESPPSRAM32=y CONFIG_SPIRAM_SIZE=4194304 CONFIG_SPIRAM_SPEED_40M=y CONFIG_SPIRAM_MEMTEST=y CONFIG_SPIRAM_CACHE_WORKAROUND=y -CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 -CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST= -CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY= +CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=y CONFIG_MEMMAP_TRACEMEM= CONFIG_MEMMAP_TRACEMEM_TWOBANKS= CONFIG_ESP32_TRAX= @@ -274,6 +302,7 @@ CONFIG_ESP32_PANIC_PRINT_REBOOT= CONFIG_ESP32_PANIC_SILENT_REBOOT= CONFIG_ESP32_PANIC_GDBSTUB= CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y CONFIG_INT_WDT=y CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_INT_WDT_CHECK_CPU1=y @@ -308,6 +337,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE= CONFIG_NO_BLOBS= CONFIG_ESP_TIMER_PROFILING= CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # # Wi-Fi @@ -315,13 +345,17 @@ CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER= CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED= CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= # # PHY @@ -343,6 +377,11 @@ CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y CONFIG_ADC_CAL_LUT_ENABLE=y +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + # # Ethernet # @@ -381,6 +420,9 @@ CONFIG_FATFS_LFN_NONE= CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_STACK= CONFIG_FATFS_MAX_LFN=127 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_API_ENCODING_UTF_16= +CONFIG_FATFS_API_ENCODING_UTF_8= CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE= @@ -447,6 +489,7 @@ CONFIG_LOG_COLORS=y CONFIG_L2_TO_L3_COPY= CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 +CONFIG_USE_ONLY_LWIP_SELECT= CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y CONFIG_LWIP_SO_RCVBUF= @@ -480,6 +523,7 @@ CONFIG_TCP_SND_BUF_DEFAULT=5744 CONFIG_TCP_WND_DEFAULT=5744 CONFIG_TCP_RECVMBOX_SIZE=6 CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= CONFIG_TCP_OVERSIZE_MSS=y CONFIG_TCP_OVERSIZE_QUARTER_MSS= CONFIG_TCP_OVERSIZE_DISABLE= @@ -645,6 +689,11 @@ CONFIG_SPIFFS_TEST_VISUALISATION= # CONFIG_IP_LOST_TIMER_INTERVAL=120 +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y + # # Wear Levelling # diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin index 30c1184d..be3084df 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin index 6f30b9b3..bba409a8 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram_all/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/flash.sh b/MicroPython_BUILD/firmware/esp32_psram_all/flash.sh deleted file mode 100755 index 39e917a4..00000000 --- a/MicroPython_BUILD/firmware/esp32_psram_all/flash.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0xf000 phy_init_data.bin 0x10000 MicroPython.bin 0x8000 partitions_mpy.bin diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.bin index 7c7197a9..ad8e58c6 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.bin and b/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.csv b/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.csv index 44b67dd3..0cc861d7 100644 --- a/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.csv +++ b/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.csv @@ -1,9 +1,9 @@ # ------------------------------------------------------- -# - Partition layout generaded by BUILD.sh script - +# - Partition layout generated by BUILD.sh script - # ------------------------------------------------------- # Name, Type, SubType, Offset, Size, Flags # ------------------------------------------------------- nvs, data, nvs, 0x9000, 24K, phy_init, data, phy, 0xf000, 4K, -MicroPython, app, factory, 0x10000, 1920K, +MicroPython, app, factory, 0x10000, 2176K, internalfs, data, spiffs, , 1024K, diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig index c2895511..9d8aff34 100644 --- a/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig @@ -20,7 +20,10 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= CONFIG_LOG_BOOTLOADER_LEVEL=3 -CONFIG_BOOTLOADER_VDDSDIO_BOOST=y +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= # # Security features @@ -80,6 +83,7 @@ CONFIG_MICROPY_HW_BOARD_NAME="ESP32 board" CONFIG_MICROPY_HW_MCU_NAME="ESP32" CONFIG_MICROPY_TIMEZONE="GMT0BST" CONFIG_MICROPY_USE_OTA= +CONFIG_BOOT_SET_LED=-1 # # System settings @@ -91,8 +95,16 @@ CONFIG_MICRO_PY_LOG_LEVEL2=y CONFIG_MICRO_PY_LOG_LEVEL3= CONFIG_MICRO_PY_LOG_LEVEL4= CONFIG_MICRO_PY_LOG_LEVEL5= -CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_TASK_WDT=y +CONFIG_MICROPY_TASK_WDT_PANIC= +CONFIG_MICROPY_USE_UNICODE=y +CONFIG_MICROPY_ENABLE_FINALISER=y +CONFIG_MICROPY_GC_COLLECT_RETVAL= +CONFIG_MICROPY_GC_SET_THRESHOLD=y +CONFIG_MICROPY_GC_THRESHOLD_VALUE=90 +CONFIG_MICROPY_SCHEDULER_DEPTH=8 +CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR=32 +CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_BOTH_CORES= CONFIG_MICROPY_TASK_PRIORITY=5 CONFIG_MICROPY_STACK_SIZE=20 @@ -122,14 +134,19 @@ CONFIG_MICROPY_PY_FRAMEBUF=y CONFIG_MICROPY_PY_USE_BTREE=y CONFIG_MICROPY_USE_WEBSOCKETS=y CONFIG_MICROPY_USE_DISPLAY=y +CONFIG_MICROPY_USE_TFT=y +CONFIG_MICROPY_USE_EPD= CONFIG_MICROPY_USE_EVE= CONFIG_MICROPY_USE_GSM=y +CONFIG_MICROPY_USE_GPS=y +CONFIG_MICROPY_GPS_SERVICE_STACK=3072 CONFIG_MICROPY_USE_ETHERNET= CONFIG_MICROPY_USE_MDNS=y +CONFIG_MICROPY_USE_REQUESTS=y CONFIG_MICROPY_USE_CURL=y +CONFIG_MICROPY_CURL_MAX_WRITE_SIZE=8192 CONFIG_MICROPY_USE_CURL_TLS=y CONFIG_MICROPY_USE_CURLFTP=y -CONFIG_MICROPY_USE_MAIL=y CONFIG_MICROPY_USE_SSH=y CONFIG_MICROPY_USE_MQTT=y @@ -137,9 +154,10 @@ CONFIG_MICROPY_USE_MQTT=y # MQTT Configuration # CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_PRIORITY=5 -CONFIG_MQTT_BUFFER_SIZE_BYTE=256 -CONFIG_MQTT_MAX_PAYLOAD_SIZE=2048 +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= CONFIG_MQTT_LOG_LEVEL=1 CONFIG_MQTT_LOG_LEVEL0= CONFIG_MQTT_LOG_LEVEL1=y @@ -150,8 +168,11 @@ CONFIG_MQTT_LOG_LEVEL4= # # File systems # +CONFIG_MICROPY_FILESYSTEM_TYPE=0 +CONFIG_MICROPY_FS_TYPE0=y +CONFIG_MICROPY_FS_TYPE1= +CONFIG_MICROPY_FS_TYPE2= CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=6 -CONFIG_MICROPY_USE_SPIFFS=y CONFIG_MICROPY_SDMMC_SHOW_INFO=y # @@ -161,6 +182,7 @@ CONFIG_SDCARD_MODE=3 CONFIG_SDCARD_MODE1= CONFIG_SDCARD_MODE2= CONFIG_SDCARD_MODE3=y +CONFIG_SDMMC_ALLOW_SPI_HIGHSPEED= # # Partition Table @@ -169,11 +191,8 @@ CONFIG_PARTITION_TABLE_SINGLE_APP= CONFIG_PARTITION_TABLE_TWO_OTA= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_mpy.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 -CONFIG_PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET=0xf000 CONFIG_PARTITION_TABLE_FILENAME="partitions_mpy.csv" -CONFIG_APP_OFFSET=0x10000 -CONFIG_PHY_DATA_OFFSET=0xf000 +CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # @@ -190,6 +209,7 @@ CONFIG_STACK_CHECK_NORM= CONFIG_STACK_CHECK_STRONG= CONFIG_STACK_CHECK_ALL= CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= # # Component config @@ -202,10 +222,6 @@ CONFIG_ESP32_APPTRACE_DEST_TRAX= CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_ENABLE= CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y - -# -# FreeRTOS SystemView Tracing -# CONFIG_AWS_IOT_SDK= # @@ -215,6 +231,22 @@ CONFIG_BT_ENABLED= CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BT_RESERVE_DRAM=0 +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI master configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y + # # ESP32-specific # @@ -222,26 +254,22 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_MEMMAP_SMP=y CONFIG_SPIRAM_SUPPORT=y # # SPI RAM config # CONFIG_SPIRAM_BOOT_INIT=y -CONFIG_SPIRAM_IGNORE_NOTFOUND= +CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_USE_MEMMAP= -CONFIG_SPIRAM_USE_CAPS_ALLOC= -CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC= CONFIG_SPIRAM_TYPE_ESPPSRAM32=y CONFIG_SPIRAM_SIZE=4194304 CONFIG_SPIRAM_SPEED_40M=y CONFIG_SPIRAM_MEMTEST=y CONFIG_SPIRAM_CACHE_WORKAROUND=y -CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 -CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST= -CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY= +CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=y CONFIG_MEMMAP_TRACEMEM= CONFIG_MEMMAP_TRACEMEM_TWOBANKS= CONFIG_ESP32_TRAX= @@ -277,6 +305,7 @@ CONFIG_ESP32_PANIC_PRINT_REBOOT= CONFIG_ESP32_PANIC_SILENT_REBOOT= CONFIG_ESP32_PANIC_GDBSTUB= CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y CONFIG_INT_WDT=y CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_INT_WDT_CHECK_CPU1=y @@ -311,6 +340,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE= CONFIG_NO_BLOBS= CONFIG_ESP_TIMER_PROFILING= CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # # Wi-Fi @@ -318,13 +348,17 @@ CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER= CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED= CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= # # PHY @@ -346,6 +380,11 @@ CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y CONFIG_ADC_CAL_LUT_ENABLE=y +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + # # Ethernet # @@ -384,6 +423,9 @@ CONFIG_FATFS_LFN_NONE= CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_STACK= CONFIG_FATFS_MAX_LFN=127 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_API_ENCODING_UTF_16= +CONFIG_FATFS_API_ENCODING_UTF_8= CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE= @@ -450,6 +492,7 @@ CONFIG_LOG_COLORS=y CONFIG_L2_TO_L3_COPY= CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 +CONFIG_USE_ONLY_LWIP_SELECT= CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y CONFIG_LWIP_SO_RCVBUF= @@ -483,6 +526,7 @@ CONFIG_TCP_SND_BUF_DEFAULT=5744 CONFIG_TCP_WND_DEFAULT=5744 CONFIG_TCP_RECVMBOX_SIZE=6 CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= CONFIG_TCP_OVERSIZE_MSS=y CONFIG_TCP_OVERSIZE_QUARTER_MSS= CONFIG_TCP_OVERSIZE_DISABLE= @@ -648,6 +692,11 @@ CONFIG_SPIFFS_TEST_VISUALISATION= # CONFIG_IP_LOST_TIMER_INTERVAL=120 +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y + # # Wear Levelling # diff --git a/MicroPython_BUILD/firmware/esp32_psram_all_bt/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_all_bt/MicroPython.bin new file mode 100644 index 00000000..006d49de Binary files /dev/null and b/MicroPython_BUILD/firmware/esp32_psram_all_bt/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all_bt/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram_all_bt/bootloader/bootloader.bin new file mode 100644 index 00000000..5c2c755f Binary files /dev/null and b/MicroPython_BUILD/firmware/esp32_psram_all_bt/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all_bt/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_psram_all_bt/partitions_mpy.bin new file mode 100644 index 00000000..5498387c Binary files /dev/null and b/MicroPython_BUILD/firmware/esp32_psram_all_bt/partitions_mpy.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all_bt/partitions_mpy.csv b/MicroPython_BUILD/firmware/esp32_psram_all_bt/partitions_mpy.csv new file mode 100644 index 00000000..6ec8e5c2 --- /dev/null +++ b/MicroPython_BUILD/firmware/esp32_psram_all_bt/partitions_mpy.csv @@ -0,0 +1,9 @@ +# ------------------------------------------------------- +# - Partition layout generated by BUILD.sh script - +# ------------------------------------------------------- +# Name, Type, SubType, Offset, Size, Flags +# ------------------------------------------------------- +nvs, data, nvs, 0x9000, 24K, +phy_init, data, phy, 0xf000, 4K, +MicroPython, app, factory, 0x10000, 2304K, +internalfs, data, spiffs, , 1024K, diff --git a/MicroPython_BUILD/firmware/esp32_psram_all_bt/phy_init_data.bin b/MicroPython_BUILD/firmware/esp32_psram_all_bt/phy_init_data.bin new file mode 100644 index 00000000..434b5292 Binary files /dev/null and b/MicroPython_BUILD/firmware/esp32_psram_all_bt/phy_init_data.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_all_bt/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram_all_bt/sdkconfig new file mode 100644 index 00000000..6fc2ca7b --- /dev/null +++ b/MicroPython_BUILD/firmware/esp32_psram_all_bt/sdkconfig @@ -0,0 +1,746 @@ +# +# Automatically generated file; DO NOT EDIT. +# Espressif IoT Development Framework Configuration +# + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_PYTHON="python" +CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y + +# +# Bootloader config +# +CONFIG_LOG_BOOTLOADER_LEVEL_NONE= +CONFIG_LOG_BOOTLOADER_LEVEL_ERROR= +CONFIG_LOG_BOOTLOADER_LEVEL_WARN= +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= +CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= +CONFIG_LOG_BOOTLOADER_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= + +# +# Security features +# +CONFIG_SECURE_BOOT_ENABLED= +CONFIG_FLASH_ENCRYPTION_ENABLED= + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0" +CONFIG_ESPTOOLPY_BAUD_115200B= +CONFIG_ESPTOOLPY_BAUD_230400B= +CONFIG_ESPTOOLPY_BAUD_921600B=y +CONFIG_ESPTOOLPY_BAUD_2MB= +CONFIG_ESPTOOLPY_BAUD_OTHER= +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_FLASHMODE_QIO= +CONFIG_FLASHMODE_QOUT= +CONFIG_FLASHMODE_DIO=y +CONFIG_FLASHMODE_DOUT= +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M= +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_ESPTOOLPY_FLASHFREQ_26M= +CONFIG_ESPTOOLPY_FLASHFREQ_20M= +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +CONFIG_ESPTOOLPY_FLASHSIZE_1MB= +CONFIG_ESPTOOLPY_FLASHSIZE_2MB= +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_8MB= +CONFIG_ESPTOOLPY_FLASHSIZE_16MB= +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +CONFIG_ESPTOOLPY_BEFORE_NORESET= +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET= +CONFIG_ESPTOOLPY_AFTER_NORESET=y +CONFIG_ESPTOOLPY_AFTER="no_reset" +CONFIG_MONITOR_BAUD_9600B= +CONFIG_MONITOR_BAUD_57600B= +CONFIG_MONITOR_BAUD_115200B=y +CONFIG_MONITOR_BAUD_230400B= +CONFIG_MONITOR_BAUD_921600B= +CONFIG_MONITOR_BAUD_2MB= +CONFIG_MONITOR_BAUD_OTHER= +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 + +# +# MicroPython +# +CONFIG_MICROPY_HW_BOARD_NAME="ESP32&psRAM board" +CONFIG_MICROPY_HW_MCU_NAME="ESP32" +CONFIG_MICROPY_TIMEZONE="GMT0BST" +CONFIG_MICROPY_USE_OTA= +CONFIG_BOOT_SET_LED=-1 + +# +# System settings +# +CONFIG_MICRO_PY_LOG_LEVEL=2 +CONFIG_MICRO_PY_LOG_LEVEL0= +CONFIG_MICRO_PY_LOG_LEVEL1= +CONFIG_MICRO_PY_LOG_LEVEL2=y +CONFIG_MICRO_PY_LOG_LEVEL3= +CONFIG_MICRO_PY_LOG_LEVEL4= +CONFIG_MICRO_PY_LOG_LEVEL5= +CONFIG_MICROPY_USE_TASK_WDT=y +CONFIG_MICROPY_TASK_WDT_PANIC= +CONFIG_MICROPY_USE_UNICODE=y +CONFIG_MICROPY_ENABLE_FINALISER=y +CONFIG_MICROPY_GC_COLLECT_RETVAL= +CONFIG_MICROPY_GC_SET_THRESHOLD=y +CONFIG_MICROPY_GC_THRESHOLD_VALUE=90 +CONFIG_MICROPY_SCHEDULER_DEPTH=8 +CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR=32 +CONFIG_MICROPY_RX_BUFFER_SIZE=1080 +CONFIG_MICROPY_USE_BOTH_CORES= +CONFIG_MICROPY_TASK_PRIORITY=5 +CONFIG_MICROPY_STACK_SIZE=20 +CONFIG_MICROPY_HEAP_SIZE=3072 +CONFIG_MICROPY_THREAD_MAX_THREADS=4 +CONFIG_MICROPY_THREAD_STACK_SIZE=4 +CONFIG_MICROPY_USE_TELNET=y +CONFIG_MICROPY_USE_WEBSERVER= +CONFIG_MICROPY_USE_FTPSERVER=y + +# +# FTP Server Configuration +# +CONFIG_FTPSERVER_LOG_LEVEL=1 +CONFIG_FTPSERVER_LOG_LEVEL0= +CONFIG_FTPSERVER_LOG_LEVEL1=y +CONFIG_FTPSERVER_LOG_LEVEL2= +CONFIG_FTPSERVER_LOG_LEVEL3= +CONFIG_FTPSERVER_LOG_LEVEL4= +CONFIG_MICROPY_FTPSERVER_TIMEOUT=300 +CONFIG_MICROPY_FTPSERVER_BUFFER_SIZE=1024 + +# +# Modules +# +CONFIG_MICROPY_PY_FRAMEBUF=y +CONFIG_MICROPY_PY_USE_BTREE=y +CONFIG_MICROPY_USE_WEBSOCKETS=y +CONFIG_MICROPY_USE_DISPLAY=y +CONFIG_MICROPY_USE_TFT=y +CONFIG_MICROPY_USE_EPD= +CONFIG_MICROPY_USE_EVE= +CONFIG_MICROPY_USE_GSM=y +CONFIG_MICROPY_USE_GPS=y +CONFIG_MICROPY_GPS_SERVICE_STACK=3072 +CONFIG_MICROPY_USE_ETHERNET= +CONFIG_MICROPY_USE_BLUETOOTH= +CONFIG_MICROPY_USE_RFCOMM=y +CONFIG_MICROPY_USE_MDNS=y +CONFIG_MICROPY_USE_REQUESTS=y +CONFIG_MICROPY_USE_CURL=y +CONFIG_MICROPY_CURL_MAX_WRITE_SIZE=8192 +CONFIG_MICROPY_USE_CURL_TLS=y +CONFIG_MICROPY_USE_CURLFTP=y +CONFIG_MICROPY_USE_SSH=y +CONFIG_MICROPY_USE_MQTT=y + +# +# MQTT Configuration +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= +CONFIG_MQTT_LOG_LEVEL=1 +CONFIG_MQTT_LOG_LEVEL0= +CONFIG_MQTT_LOG_LEVEL1=y +CONFIG_MQTT_LOG_LEVEL2= +CONFIG_MQTT_LOG_LEVEL3= +CONFIG_MQTT_LOG_LEVEL4= + +# +# File systems +# +CONFIG_MICROPY_FILESYSTEM_TYPE=0 +CONFIG_MICROPY_FS_TYPE0=y +CONFIG_MICROPY_FS_TYPE1= +CONFIG_MICROPY_FS_TYPE2= +CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=6 +CONFIG_MICROPY_SDMMC_SHOW_INFO=y + +# +# SD Card configuration +# +CONFIG_SDCARD_MODE=3 +CONFIG_SDCARD_MODE1= +CONFIG_SDCARD_MODE2= +CONFIG_SDCARD_MODE3=y +CONFIG_SDMMC_ALLOW_SPI_HIGHSPEED= + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP= +CONFIG_PARTITION_TABLE_TWO_OTA= +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_mpy.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_mpy.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y + +# +# Compiler options +# +CONFIG_OPTIMIZATION_LEVEL_DEBUG= +CONFIG_OPTIMIZATION_LEVEL_RELEASE=y +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +CONFIG_OPTIMIZATION_ASSERTIONS_SILENT= +CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED= +CONFIG_CXX_EXCEPTIONS= +CONFIG_STACK_CHECK_NONE=y +CONFIG_STACK_CHECK_NORM= +CONFIG_STACK_CHECK_STRONG= +CONFIG_STACK_CHECK_ALL= +CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= + +# +# Component config +# + +# +# Application Level Tracing +# +CONFIG_ESP32_APPTRACE_DEST_TRAX= +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_ENABLE= +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_AWS_IOT_SDK= + +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y +CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= + +# +# MODEM SLEEP Options +# +CONFIG_BTDM_CONTROLLER_MODEM_SLEEP= +CONFIG_BLUEDROID_ENABLED=y +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +CONFIG_BLUEDROID_PINNED_TO_CORE_1= +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTC_TASK_STACK_SIZE=3072 +CONFIG_BLUEDROID_MEM_DEBUG= +CONFIG_CLASSIC_BT_ENABLED=y +CONFIG_A2DP_ENABLE= +CONFIG_BT_SPP_ENABLED=y +CONFIG_HFP_ENABLE= +CONFIG_GATTS_ENABLE=y +CONFIG_GATTC_ENABLE=y +CONFIG_GATTC_CACHE_NVS_FLASH= +CONFIG_BLE_SMP_ENABLE= +CONFIG_BT_STACK_NO_LOG=y +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y +CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK= +CONFIG_BLE_SCAN_DUPLICATE=y +CONFIG_DUPLICATE_SCAN_CACHE_SIZE=20 +CONFIG_BLE_MESH_SCAN_DUPLICATE_EN= +CONFIG_SMP_ENABLE=y +CONFIG_BT_RESERVE_DRAM=0x10000 + +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI master configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y + +# +# ESP32-specific +# +CONFIG_ESP32_DEFAULT_CPU_FREQ_80= +CONFIG_ESP32_DEFAULT_CPU_FREQ_160= +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SPIRAM_SUPPORT=y + +# +# SPI RAM config +# +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MEMMAP= +CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC= +CONFIG_SPIRAM_TYPE_ESPPSRAM32=y +CONFIG_SPIRAM_SIZE=4194304 +CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_CACHE_WORKAROUND=y +CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=y +CONFIG_MEMMAP_TRACEMEM= +CONFIG_MEMMAP_TRACEMEM_TWOBANKS= +CONFIG_ESP32_TRAX= +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH= +CONFIG_ESP32_ENABLE_COREDUMP_TO_UART= +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_ESP32_ENABLE_COREDUMP= +CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF= +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_LF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +CONFIG_NEWLIB_NANO_FORMAT= +CONFIG_CONSOLE_UART_DEFAULT=y +CONFIG_CONSOLE_UART_CUSTOM= +CONFIG_CONSOLE_UART_NONE= +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ULP_COPROC_ENABLED= +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_PANIC_PRINT_HALT=y +CONFIG_ESP32_PANIC_PRINT_REBOOT= +CONFIG_ESP32_PANIC_SILENT_REBOOT= +CONFIG_ESP32_PANIC_GDBSTUB= +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_TASK_WDT_PANIC= +CONFIG_TASK_WDT_TIMEOUT_S=15 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +CONFIG_BROWNOUT_DET_LVL_SEL_1= +CONFIG_BROWNOUT_DET_LVL_SEL_2= +CONFIG_BROWNOUT_DET_LVL_SEL_3= +CONFIG_BROWNOUT_DET_LVL_SEL_4= +CONFIG_BROWNOUT_DET_LVL_SEL_5= +CONFIG_BROWNOUT_DET_LVL_SEL_6= +CONFIG_BROWNOUT_DET_LVL_SEL_7= +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC= +CONFIG_ESP32_TIME_SYSCALL_USE_FRC1= +CONFIG_ESP32_TIME_SYSCALL_USE_NONE= +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL= +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40= +CONFIG_ESP32_XTAL_FREQ_26= +CONFIG_ESP32_XTAL_FREQ_AUTO=y +CONFIG_ESP32_XTAL_FREQ=0 +CONFIG_DISABLE_BASIC_ROM_CONSOLE= +CONFIG_ESP_TIMER_PROFILING= +CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y + +# +# Wi-Fi +# +CONFIG_SW_COEXIST_ENABLE=y +CONFIG_SW_COEXIST_PREFERENCE_WIFI= +CONFIG_SW_COEXIST_PREFERENCE_BT= +CONFIG_SW_COEXIST_PREFERENCE_BALANCE=y +CONFIG_SW_COEXIST_PREFERENCE_VALUE=2 +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER= +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED= +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION=y +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 + +# +# Power Management +# +CONFIG_PM_ENABLE= + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + +# +# Ethernet +# +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE= +CONFIG_EMAC_TASK_PRIORITY=20 + +# +# FAT Filesystem support +# +CONFIG_FATFS_CODEPAGE_DYNAMIC= +CONFIG_FATFS_CODEPAGE_437=y +CONFIG_FATFS_CODEPAGE_720= +CONFIG_FATFS_CODEPAGE_737= +CONFIG_FATFS_CODEPAGE_771= +CONFIG_FATFS_CODEPAGE_775= +CONFIG_FATFS_CODEPAGE_850= +CONFIG_FATFS_CODEPAGE_852= +CONFIG_FATFS_CODEPAGE_855= +CONFIG_FATFS_CODEPAGE_857= +CONFIG_FATFS_CODEPAGE_860= +CONFIG_FATFS_CODEPAGE_861= +CONFIG_FATFS_CODEPAGE_862= +CONFIG_FATFS_CODEPAGE_863= +CONFIG_FATFS_CODEPAGE_864= +CONFIG_FATFS_CODEPAGE_865= +CONFIG_FATFS_CODEPAGE_866= +CONFIG_FATFS_CODEPAGE_869= +CONFIG_FATFS_CODEPAGE_932= +CONFIG_FATFS_CODEPAGE_936= +CONFIG_FATFS_CODEPAGE_949= +CONFIG_FATFS_CODEPAGE_950= +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE= +CONFIG_FATFS_LFN_HEAP=y +CONFIG_FATFS_LFN_STACK= +CONFIG_FATFS_MAX_LFN=127 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_API_ENCODING_UTF_16= +CONFIG_FATFS_API_ENCODING_UTF_8= +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE= + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_CORETIMER_0=y +CONFIG_FREERTOS_CORETIMER_1= +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK= +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=4 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= +CONFIG_FREERTOS_ASSERT_DISABLE= +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_ISR_STACKSIZE=4096 +CONFIG_FREERTOS_LEGACY_HOOKS= +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_SUPPORT_STATIC_ALLOCATION=y +CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK=y +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_USE_TRACE_FACILITY= +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS= +CONFIG_FREERTOS_DEBUG_INTERNALS= + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +CONFIG_HEAP_POISONING_LIGHT= +CONFIG_HEAP_POISONING_COMPREHENSIVE= +CONFIG_HEAP_TRACING= + +# +# libsodium +# +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y + +# +# Log output +# +CONFIG_LOG_DEFAULT_LEVEL_NONE= +CONFIG_LOG_DEFAULT_LEVEL_ERROR= +CONFIG_LOG_DEFAULT_LEVEL_WARN= +CONFIG_LOG_DEFAULT_LEVEL_INFO= +CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y +CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= +CONFIG_LOG_DEFAULT_LEVEL=4 +CONFIG_LOG_COLORS=y + +# +# LWIP +# +CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= +CONFIG_LWIP_MAX_SOCKETS=8 +CONFIG_USE_ONLY_LWIP_SELECT=y +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +CONFIG_LWIP_SO_RCVBUF= +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_IP_FRAG= +CONFIG_LWIP_IP_REASSEMBLY= +CONFIG_LWIP_STATS= +CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_AUTOIP= +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= +CONFIG_TCP_OVERSIZE_MSS=y +CONFIG_TCP_OVERSIZE_QUARTER_MSS= +CONFIG_TCP_OVERSIZE_DISABLE= + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=4096 +CONFIG_PPP_SUPPORT=y +CONFIG_PPP_PAP_SUPPORT=y +CONFIG_PPP_CHAP_SUPPORT= +CONFIG_PPP_MSCHAP_SUPPORT= +CONFIG_PPP_MPPE_SUPPORT= +CONFIG_PPP_DEBUG_ON= + +# +# ICMP +# +CONFIG_LWIP_MULTICAST_PING= +CONFIG_LWIP_BROADCAST_PING= + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 + +# +# mbedTLS +# +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_DEBUG= +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI= +CONFIG_MBEDTLS_HARDWARE_SHA= +CONFIG_MBEDTLS_HAVE_TIME=y +CONFIG_MBEDTLS_HAVE_TIME_DATE= +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +CONFIG_MBEDTLS_TLS_SERVER_ONLY= +CONFIG_MBEDTLS_TLS_CLIENT_ONLY= +CONFIG_MBEDTLS_TLS_DISABLED= +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +CONFIG_MBEDTLS_PSK_MODES= +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_SSL3= +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS= +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +CONFIG_MBEDTLS_CAMELLIA_C= +CONFIG_MBEDTLS_DES_C= +CONFIG_MBEDTLS_RC4_DISABLED=y +CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= +CONFIG_MBEDTLS_RC4_ENABLED= +CONFIG_MBEDTLS_BLOWFISH_C= +CONFIG_MBEDTLS_XTEA_C= +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +CONFIG_MBEDTLS_RIPEMD160_C= + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y + +# +# OpenSSL +# +CONFIG_OPENSSL_DEBUG= +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +CONFIG_OPENSSL_ASSERT_EXIT= + +# +# PThreads +# +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 + +# +# SPI Flash driver +# +CONFIG_SPI_FLASH_VERIFY_WRITE= +CONFIG_SPI_FLASH_ENABLE_COUNTERS= +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS= +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED= + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=1 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +CONFIG_SPIFFS_CACHE_STATS= +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +CONFIG_SPIFFS_GC_STATS= +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=64 +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=5 +CONFIG_SPIFFS_USE_MTIME=y +CONFIG_SPIFFS_USE_DIR=y + +# +# Debug Configuration +# +CONFIG_SPIFFS_DBG= +CONFIG_SPIFFS_API_DBG= +CONFIG_SPIFFS_GC_DBG= +CONFIG_SPIFFS_CACHE_DBG= +CONFIG_SPIFFS_CHECK_DBG= +CONFIG_SPIFFS_TEST_VISUALISATION= + +# +# tcpip adapter +# +CONFIG_IP_LOST_TIMER_INTERVAL=120 + +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y + +# +# Wear Levelling +# +CONFIG_WL_SECTOR_SIZE_512=y +CONFIG_WL_SECTOR_SIZE_4096= +CONFIG_WL_SECTOR_SIZE=512 +CONFIG_WL_SECTOR_MODE_PERF= +CONFIG_WL_SECTOR_MODE_SAFE=y +CONFIG_WL_SECTOR_MODE=1 diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin index bd69c1b0..f3044374 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin and b/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin index cea4be6b..f99af120 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin and b/MicroPython_BUILD/firmware/esp32_psram_ota/bootloader/bootloader.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/flash.sh b/MicroPython_BUILD/firmware/esp32_psram_ota/flash.sh deleted file mode 100755 index 39e917a4..00000000 --- a/MicroPython_BUILD/firmware/esp32_psram_ota/flash.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0xf000 phy_init_data.bin 0x10000 MicroPython.bin 0x8000 partitions_mpy.bin diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.bin index 5db33c33..3a5f8d2b 100644 Binary files a/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.bin and b/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.bin differ diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.csv b/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.csv index d6784316..3e066a66 100644 --- a/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.csv +++ b/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.csv @@ -1,11 +1,11 @@ # ------------------------------------------------------- -# - Partition layout generaded by BUILD.sh script - +# - Partition layout generated by BUILD.sh script - # ------------------------------------------------------- # Name, Type, SubType, Offset, Size, Flags # ------------------------------------------------------- nvs, data, nvs, 0x9000, 16K, otadata, data, ota, 0xd000, 8K, phy_init, data, phy, 0xf000, 4K, -MicroPython_1, app, ota_0, 0x10000, 1472K, -MicroPython_2, app, ota_1, , 1472K, -internalfs, data, spiffs, , 1024K, +MicroPython_1, app, ota_0, 0x10000, 1728K, +MicroPython_2, app, ota_1, , 1728K, +internalfs, data, spiffs, , 576K, diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig index 42fbd457..6c05f63e 100644 --- a/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig @@ -20,7 +20,10 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= CONFIG_LOG_BOOTLOADER_LEVEL=3 -CONFIG_BOOTLOADER_VDDSDIO_BOOST=y +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= # # Security features @@ -81,6 +84,7 @@ CONFIG_MICROPY_HW_MCU_NAME="ESP32" CONFIG_MICROPY_TIMEZONE="GMT0BST" CONFIG_MICROPY_USE_OTA=y CONFIG_GPIO_INPUT_FORCE_FACTORY= +CONFIG_BOOT_SET_LED=-1 # # System settings @@ -92,8 +96,16 @@ CONFIG_MICRO_PY_LOG_LEVEL2=y CONFIG_MICRO_PY_LOG_LEVEL3= CONFIG_MICRO_PY_LOG_LEVEL4= CONFIG_MICRO_PY_LOG_LEVEL5= -CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_TASK_WDT=y +CONFIG_MICROPY_TASK_WDT_PANIC= +CONFIG_MICROPY_USE_UNICODE=y +CONFIG_MICROPY_ENABLE_FINALISER=y +CONFIG_MICROPY_GC_COLLECT_RETVAL= +CONFIG_MICROPY_GC_SET_THRESHOLD=y +CONFIG_MICROPY_GC_THRESHOLD_VALUE=90 +CONFIG_MICROPY_SCHEDULER_DEPTH=8 +CONFIG_MICROPY_PY_THREAD_GIL_VM_DIVISOR=32 +CONFIG_MICROPY_RX_BUFFER_SIZE=1080 CONFIG_MICROPY_USE_BOTH_CORES= CONFIG_MICROPY_TASK_PRIORITY=5 CONFIG_MICROPY_STACK_SIZE=20 @@ -123,10 +135,15 @@ CONFIG_MICROPY_PY_FRAMEBUF=y CONFIG_MICROPY_PY_USE_BTREE= CONFIG_MICROPY_USE_WEBSOCKETS= CONFIG_MICROPY_USE_DISPLAY=y +CONFIG_MICROPY_USE_TFT=y +CONFIG_MICROPY_USE_EPD= CONFIG_MICROPY_USE_EVE= CONFIG_MICROPY_USE_GSM= +CONFIG_MICROPY_USE_GPS=y +CONFIG_MICROPY_GPS_SERVICE_STACK=3072 CONFIG_MICROPY_USE_ETHERNET= CONFIG_MICROPY_USE_MDNS=y +CONFIG_MICROPY_USE_REQUESTS=y CONFIG_MICROPY_USE_CURL= CONFIG_MICROPY_USE_SSH= CONFIG_MICROPY_USE_MQTT=y @@ -135,9 +152,10 @@ CONFIG_MICROPY_USE_MQTT=y # MQTT Configuration # CONFIG_MQTT_PROTOCOL_311=y -CONFIG_MQTT_PRIORITY=5 -CONFIG_MQTT_BUFFER_SIZE_BYTE=256 -CONFIG_MQTT_MAX_PAYLOAD_SIZE=2048 +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= CONFIG_MQTT_LOG_LEVEL=1 CONFIG_MQTT_LOG_LEVEL0= CONFIG_MQTT_LOG_LEVEL1=y @@ -148,8 +166,11 @@ CONFIG_MQTT_LOG_LEVEL4= # # File systems # +CONFIG_MICROPY_FILESYSTEM_TYPE=0 +CONFIG_MICROPY_FS_TYPE0=y +CONFIG_MICROPY_FS_TYPE1= +CONFIG_MICROPY_FS_TYPE2= CONFIG_MICROPY_FATFS_MAX_OPEN_FILES=6 -CONFIG_MICROPY_USE_SPIFFS=y CONFIG_MICROPY_SDMMC_SHOW_INFO=y # @@ -159,6 +180,7 @@ CONFIG_SDCARD_MODE=3 CONFIG_SDCARD_MODE1= CONFIG_SDCARD_MODE2= CONFIG_SDCARD_MODE3=y +CONFIG_SDMMC_ALLOW_SPI_HIGHSPEED= # # Partition Table @@ -167,11 +189,8 @@ CONFIG_PARTITION_TABLE_SINGLE_APP= CONFIG_PARTITION_TABLE_TWO_OTA= CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_mpy.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 -CONFIG_PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET=0xf000 CONFIG_PARTITION_TABLE_FILENAME="partitions_mpy.csv" -CONFIG_APP_OFFSET=0x10000 -CONFIG_PHY_DATA_OFFSET=0xf000 +CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # @@ -188,6 +207,7 @@ CONFIG_STACK_CHECK_NORM= CONFIG_STACK_CHECK_STRONG= CONFIG_STACK_CHECK_ALL= CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= # # Component config @@ -200,10 +220,6 @@ CONFIG_ESP32_APPTRACE_DEST_TRAX= CONFIG_ESP32_APPTRACE_DEST_NONE=y CONFIG_ESP32_APPTRACE_ENABLE= CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y - -# -# FreeRTOS SystemView Tracing -# CONFIG_AWS_IOT_SDK= # @@ -213,6 +229,22 @@ CONFIG_BT_ENABLED= CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BT_RESERVE_DRAM=0 +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI master configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y + # # ESP32-specific # @@ -220,26 +252,22 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80= CONFIG_ESP32_DEFAULT_CPU_FREQ_160= CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 -CONFIG_MEMMAP_SMP=y CONFIG_SPIRAM_SUPPORT=y # # SPI RAM config # CONFIG_SPIRAM_BOOT_INIT=y -CONFIG_SPIRAM_IGNORE_NOTFOUND= +CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_USE_MEMMAP= -CONFIG_SPIRAM_USE_CAPS_ALLOC= -CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC= CONFIG_SPIRAM_TYPE_ESPPSRAM32=y CONFIG_SPIRAM_SIZE=4194304 CONFIG_SPIRAM_SPEED_40M=y CONFIG_SPIRAM_MEMTEST=y CONFIG_SPIRAM_CACHE_WORKAROUND=y -CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 -CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST= -CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768 -CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY= +CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=y CONFIG_MEMMAP_TRACEMEM= CONFIG_MEMMAP_TRACEMEM_TWOBANKS= CONFIG_ESP32_TRAX= @@ -275,6 +303,7 @@ CONFIG_ESP32_PANIC_PRINT_REBOOT= CONFIG_ESP32_PANIC_SILENT_REBOOT= CONFIG_ESP32_PANIC_GDBSTUB= CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y CONFIG_INT_WDT=y CONFIG_INT_WDT_TIMEOUT_MS=300 CONFIG_INT_WDT_CHECK_CPU1=y @@ -309,6 +338,7 @@ CONFIG_DISABLE_BASIC_ROM_CONSOLE= CONFIG_NO_BLOBS= CONFIG_ESP_TIMER_PROFILING= CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # # Wi-Fi @@ -316,13 +346,17 @@ CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER= CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0 CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED= CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= # # PHY @@ -344,6 +378,11 @@ CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y CONFIG_ADC_CAL_LUT_ENABLE=y +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + # # Ethernet # @@ -382,6 +421,9 @@ CONFIG_FATFS_LFN_NONE= CONFIG_FATFS_LFN_HEAP=y CONFIG_FATFS_LFN_STACK= CONFIG_FATFS_MAX_LFN=127 +CONFIG_FATFS_API_ENCODING_ANSI_OEM=y +CONFIG_FATFS_API_ENCODING_UTF_16= +CONFIG_FATFS_API_ENCODING_UTF_8= CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE= @@ -448,6 +490,7 @@ CONFIG_LOG_COLORS=y CONFIG_L2_TO_L3_COPY= CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 +CONFIG_USE_ONLY_LWIP_SELECT= CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y CONFIG_LWIP_SO_RCVBUF= @@ -481,6 +524,7 @@ CONFIG_TCP_SND_BUF_DEFAULT=5744 CONFIG_TCP_WND_DEFAULT=5744 CONFIG_TCP_RECVMBOX_SIZE=6 CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= CONFIG_TCP_OVERSIZE_MSS=y CONFIG_TCP_OVERSIZE_QUARTER_MSS= CONFIG_TCP_OVERSIZE_DISABLE= @@ -646,6 +690,11 @@ CONFIG_SPIFFS_TEST_VISUALISATION= # CONFIG_IP_LOST_TIMER_INTERVAL=120 +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y + # # Wear Levelling # diff --git a/MicroPython_BUILD/firmware/flash.sh b/MicroPython_BUILD/firmware/flash.sh new file mode 100755 index 00000000..4411120f --- /dev/null +++ b/MicroPython_BUILD/firmware/flash.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +FLASH_COMPORT="/dev/ttyUSB0" +FLASH_BDRATE="460800" + +get_arguments() { + POSITIONAL_ARGS=() + local key="$1" + J_OPTION="" + + while [[ $# -gt 0 ]] + do + local key="$1" + case $key in + -p|--port) + FLASH_COMPORT="$2" + shift # past argument + shift # past value + ;; + -b|--bdrate) + FLASH_BDRATE="$2" + shift # past argument + shift # past value + ;; + *) # unknown option + local opt="$1" + if [ "${opt:0:2}" == "-j" ]; then + J_OPTION=${opt} + else + POSITIONAL_ARGS+=("$1") # save it in an array for later + fi + shift # past argument + ;; + esac + done + #set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters +} + +get_arguments "$@" + +esptool.py --chip esp32 --port ${FLASH_COMPORT} --baud ${FLASH_BDRATE} --before default_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader/bootloader.bin 0xf000 phy_init_data.bin 0x10000 MicroPython.bin 0x8000 partitions_mpy.bin diff --git a/MicroPython_BUILD/sdkconfig.defaults b/MicroPython_BUILD/sdkconfig.defaults index d7871b63..c55ec86f 100644 --- a/MicroPython_BUILD/sdkconfig.defaults +++ b/MicroPython_BUILD/sdkconfig.defaults @@ -35,6 +35,22 @@ CONFIG_ESP32_PANIC_PRINT_HALT=y CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION=y CONFIG_TASK_WDT_TIMEOUT_S=15 +# +# SPI RAM config +# +CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MEMMAP= +CONFIG_SPIRAM_USE_CAPS_ALLOC=y +CONFIG_SPIRAM_USE_MALLOC= +CONFIG_SPIRAM_TYPE_ESPPSRAM32=y +CONFIG_SPIRAM_SIZE=4194304 +CONFIG_SPIRAM_SPEED_40M=y +CONFIG_SPIRAM_SPEED_80M= +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_CACHE_WORKAROUND=y +CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=y + # # Log output # @@ -77,6 +93,11 @@ CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16 +# +# mbedTLS +# +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=8192 + # # FatFS # diff --git a/MicroPython_BUILD/updates.txt b/MicroPython_BUILD/updates.txt new file mode 100644 index 00000000..be27870d --- /dev/null +++ b/MicroPython_BUILD/updates.txt @@ -0,0 +1,279 @@ +=== 2018-09-04 === +Updated 'machine.DAC' module + added 'write_buffer()' method + which can be used to reproduce data collected with 'machine.ADC.collect' + +Updated 'machine.ADC' module + improved 'collect()' method, max frequency increased to 18000 Hz + +------------------------------------------------------------------------------- + +=== 2018-09-04 === +Updated 'EVE' module to build correctly for both FT80x and FT81x + +------------------------------------------------------------------------------- + +=== 2018-09-03 === +Fixed build errors if EVE module was selected without TFT module enabled + +Updated 'Curl' module + Adder custom request argument to 'getmail' method + +Updated frozen modules 'microWebSrv' and 'microWebSocket' + Removed unneede import of 'websocket' module + +------------------------------------------------------------------------------- + +=== 2018-09-01 === +Fixed wrong method name in 'requests' module + +------------------------------------------------------------------------------- + +=== 2018-09-01 === + +Fixed bug in Ftp server preenting directory listing + +Updated 'ota' module + update over network now uses 'esp_http_client' componnent + update with SSL (https) is now possible + server certificate (with https) can be used to verify the firmware origin + +Updated 'gsm' module + added option to allow connection when in roaming + added method 'isconfig()' to get the IP, netmask and gateway + some small improvements + +Updated 'requests' module + added method 'certificate()' to set the server certificate from file (when using https) + added method 'debug()' to enable/disable logging + some cleaning and improvements + +Updated 'machine.DHT' module + fixed bug: When a DTH22 sensor is used, the results were always truncated after the decimal place + +Updated 'machine.Pin' module + improved irq handling + +------------------------------------------------------------------------------- + +=== 2018-08-26 === + +Updated 'ethernet' module + updated all modules using network to work on any network interface, including ethernet + ftpserver and telnet server now also works over ethernet + +Updated 'uos.sdconfig()' + SPI host can be selected if SDCard mode is SPI + +Updated 'Curl' module + added 'getmail' method + added option to set maximum write buffer size, lower size can make it more usable on boards without psRAM + tab character (0x09) is now accepted in response body + +Updated 'machine' module + fixed bug in 'deepsleep' method, deepslep for all timeout values now works as expected + +Updated 'DAC' module + fixed bug in 'waveform' method, the 'duration' argument now works for waveform types + +Updated 'machine.Pin' module + fixed bug in handling the 'debounce' argument + +Added 'requests' module implemented in C, based on 'esp_http_client' componnent + get, post, head, put, patch methods + +Refactored 'display' module + added full support for FTDI EVE chips (FT8xx) + prepared for implementation of e-paper displays support + +Updated sdcard support + +Updated esp-idf to version v3.1-rc1-53509c7b + +------------------------------------------------------------------------------- + +=== 2018-06-27 === + +Removed option to run REPL in separate thread + the option was introduced to resolve some issues + which was fixed later, so it is not needed anymore + +Refactored I2C slave support + much improved i2c slave operation + +Added 'machine.RFCOMM' module + support for Bluetooth classic SPP profile + functionality equivalent to that of the UART module + Works only on boards with external SPI_RAM + +Added 'highspeed' option when configuring SDCard in SPI mode + +Updated 'machine' module + fixed bug in 'machine.stdin_disable()' function + added 'machine.WDT()' function + +Updated 'machine.ADC' module + arg name '8bit' changed to 'byte' in read_timed() function + +Updated 'network' module + station's rssi is reported in 'status('stations')' function + +Updated 'curl' module + fixed param parsing in curl.post() function + +Updated 'mdns' module + fixed param parsing in addService() function + +'esp-idf' updated + date: 2018-06-27 + version: v3.1-beta1-14-g698d3baf + hash: 698d3bafa51a06a89605c6a15f89df514efa21f8 + +Other minor updates, improvements and bug fixes + +------------------------------------------------------------------------------- + +=== 2018-06-04 === + +Refactored 'machine.Pin' module + better interrupt handling, debouncing added + +Refactored 'machine.ADC' module + new functions added + background data collecting and timed read to array or file + +Refactored 'machine.DAC' module + new functions added + timed write from array or file + waveform generator + playing wav files + +Updated 'machine' module + fixed reading internal temperature sensor + added reading internal Vdd (experimental) + +Updated 'display' module + added 'readScreen()' function + +Updated 'neopixel' module + fixed issue when neopixel is configured on multiple pins + +Refactored 'utimeq' module + new sort method for time item, ascending and descending sort available + new functions added: + len() returns tuple of current queue length and allocated length + dump([True]) is provided which prints the detailed que information. + peek(idx, res) is provided, which peeks the queue item form the index idx + peektime([idx]) accepts optional argument to peek the time value from queue at index idx. + time values in a range of int64_t are accepted and properly sorted. Floats can be accepted as time value and are rounded to int64_t + overflow on time value never occurs as the time range is more then 290000 years with micro seconds value. + +Menuconfig: + added option to enable/disable automatic garbage collection on boot + added option to set automatic garbage collection threshold + + +'esp-idf' updated + date: 2018-05-19 + version: v3.1-dev-1101-g1f7b41e2 + hash: 1f7b41e206646417adc572da928175d33c986bd3 + +Other minor updates, improvements and bug fixes + +------------------------------------------------------------------------------- + +=== 2018-05-15 === + +Updated MicroPython core + +Some improvements in garbage collector + +Added MicroPython system options in 'menuconfig' + +Updated some frozen modules + upip, urequests, logging + +------------------------------------------------------------------------------- + +=== 2018-05-15 === + +Updated 'uart' module + fixed critical bug which could cause crash after gc collect + added 'deinit' function + +Updated 'gc' module + improved garbage collection, especially when multiple threads are running + added 'collectif' function which conditionally performs + garbage collection if the used heap is above the given values + optional argument can now be used with 'gc.collect()' and 'gc.collectif()' + which enables printing gc some gc information + 'gc.threshold()' value must be > 20K + 'gc.threshold()' accepts additional argument which can set the gc debug level + +Updated '_thread' module, some improvements + +Some new MicroPython system options added to menuconfig + +Temporary solution for esp-idf bug: + cannot set the QIO mode on some Flash chips + +------------------------------------------------------------------------------- + +=== 2018-05-10 === + +'esp-idf' updated + date: 2018-05-08 + version: v3.1-dev-961-ga2556229 + hash: a2556229aa6f55b16b171e3325ee9ab1943e8552 + +Added support for runtime detection of SPIRAM + firmwares built with SPIRAM support can now run on boards without SPIRAM + +Added 'GPS' module + collecting gps data from separate FreeRTOS task is supported + +Added built-in finction 'float_precision' + precision of floats can be now set at run time + +Added new method of initializing the 'array' objects + size of the array object can be specified, uses much less heap space + +Updated 'mqtt' module + uses new espmqtt library, new features and some bug fixes + mqtt over websockets is now supported + +Updated 'sys' module + added function 'espidf_info()', returns information about used esp-idf + +Updated 'gc' module + added function 'collectif()', conditional collect + +Updated 'upip' module + 'pypy' URL updated + +Updated 'utimeq' module + fixed bugs in getting/setting time values + +Updated 'display' module + added 'text_x()' and 'text_y()' + +Fixed bug when 'mp_hal_ticks_base' was not updated afer soft resets + +Updated 'network' module + ap_if.status('clients') now returns client's mac address and IP address + +Updated 'uart' module + changes needed for 'gps' module, more reliable + +Updated 'sockets' module + from latest official MicroPython + +Updated 'rtc' module + fixed bug in setting time zone in 'ntp_sync()' function + +Using or not UNICODE can now be configured from 'menuconfig' + +Updated 'BUILD.sh' + added options to select the comm port and/or baud rate + +Many bug fixes, stability improvements, ... diff --git a/README.md b/README.md index 8be15c63..6a11a85e 100644 --- a/README.md +++ b/README.md @@ -1,265 +1,597 @@ -# MicroPython for ESP32 +# M5Stack Micropython Base [Lobo MicroPython](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/) -# with support for 4MB of psRAM +## Getting Start -
+- See LoBo MicroPython [WiKi](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki) -> This repository can be used to build MicroPython for ESP32 boards/modules with **psRAM** as well as for ESP32 boards/modules **without psRAM.**

-> *Building on* **Linux**, **MacOS** *and* **Windows** (including **Linux Subsystem on Windows 10**) *is supported*.

-> MicroPython works great on ESP32, but the most serious issue is still (as on most other MicroPython boards) limited amount of free memory.
-> This repository contains all the tools and sources necessary to **build working MicroPython firmware** which can fully use the advantages of **4MB** (or more) of **psRAM**.
-> It is **huge difference** between MicroPython running with **less than 100KB** of free memory and running with **4MB** of free memory. +## Upload code +- Use [Ampy](https://github.com/adafruit/ampy) +- Use [Lobo Miropython filesystems](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki/filesystems) -
+## Contents +- [MicroPython API](#micropython-api) + - [LCD](#lcd) + - [Button](#button) + - [SD Card](#sd-card) + - [Speaker](#speaker) + - [GPIO](#gpio) + - [PWM](#pwm) + - [ADC](#adc) + - [DAC](#dac) + - [I2C](#i2c) + - [SPI](#spi) + - [UART](#uart) + - [Timer](#timer) + - [Neopixel](#neopixel) + - [RTC](#rtc) +- [LoBo MicroPython WiKi](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki) -ESP32 can use external **SPIRAM** (psRAM) to expand available RAM up to 16MB. -Currently, there are several modules & development boards which incorporates **4MB** of psRAM:
+# MicroPython API -* [**M5Stack**](http://www.m5stack.com) _Development Kit_ [version with psRAM](https://www.aliexpress.com/store/product/M5Stack-NEWEST-4M-PSRAM-ESP32-Development-Board-with-MPU9250-9DOF-Sensor-Color-LCD-for-Arduino-Micropython/3226069_32847906756.html?spm=2114.12010608.0.0.1ba0ee41gOPji) -* **TTGO T8 V1.1** _board_, available at [eBay](https://www.ebay.com/itm/TTGO-T8-V1-1-ESP32-4MB-PSRAM-TF-CARD-3D-ANTENNA-WiFi-bluetooth/152891206854?hash=item239906acc6:g:7QkAAOSwMfhadD85) -* **ESP-WROVER-KIT** _boards_ from Espressif, available from [ElectroDragon](http://www.electrodragon.com/product/esp32-wrover-kit/), [AnalogLamb](https://www.analoglamb.com/product/esp-wrover-kit-esp32-wrover-module/), ... -* **WiPy 3.0** _board_ from [Pycom](https://pycom.io/product/wipy-3/). -* **TTGO TAudio** _board_ ([eBay](https://www.ebay.com/itm/TTGO-TAudio-V1-0-ESP32-WROVER-SD-Card-Slot-Bluetooth-WI-FI-Module-MPU9250/152835010520?hash=item2395ad2fd8:g:Jt8AAOSwR2RaOdEp)) -* **Lolin32 Pro** _board_ from [Wemos](https://wiki.wemos.cc/products:lolin32:lolin32_pro) - **`no longer available`** ([Schematic](https://wiki.wemos.cc/_media/products:lolin32:sch_lolin32_pro_v1.0.0.pdf)). -* **ESP-WROVER** _module_ from Espressif, available from [ElectroDragon](http://www.electrodragon.com/product/esp32-wrover-v4-module-based-esp32/) and many other vendors. -* **ALB32-WROVER** _module_ (4 MB SPIRAM & 4/8/16 MB Flash) from [AnalogLamb](https://www.analoglamb.com/product/alb32-wrover-esp32-module-with-64mb-flash-and-32mb-psram/). -* **S01**, **L01** and **G01** _OEM modules_ from [Pycom](https://pycom.io/webshop#oem-products). +Micropython Getting Started + +In m5stack.py already init timer 0 as EXTBASE, lcd pwm use timer 1, speak use timer 2, 8 +```python +import m5stack +``` + +## **LCD** --- -[Wiki pages](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki) with detailed documentation specific to this **MicroPython** port are available. +Import M5Stack: + +```python +from m5stack import lcd +lcd.print('hello world!') +``` + +#### Colors -Some examples can be found in [modules_examples](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/tree/master/MicroPython_BUILD/components/micropython/esp32/modules_examples) directory. +**Color** value are given as 24 bit integer numbers, 8-bit per color. ---- +For example: **0xFF0000** represents the RED color. Only upper 6 bits of the color component value is used. + +The following color constants are defined and can be used as color arguments: + +**BLACK, NAVY, DARKGREEN, DARKCYAN, MAROON, PURPLE, OLIVE, LIGHTGREY, DARKGREY, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE, ORANGE, GREENYELLOW, PINK** + +#### Drawing -This repository contains all the tools and sources necessary to **build working MicroPython firmware** which can fully use the advantages of **4MB** (or more) of **psRAM** +All **drawings** coordinates are **relative** to the **display window**. + +Initialy, the display window is set to full screen, and there are methods to set the window to the part of the full screen. + +#### Fonts + +9 bit-mapped fornts and one vector 7-segment font are included. +Unlimited number of fonts from file can also be used. + +The following font constants are defined and can be used as font arguments: + +**FONT_Default, FONT_DefaultSmall, FONT_DejaVu18, FONT_Dejavu24, FONT_Ubuntu, FONT_Comic, FONT_Minya, FONT_Tooney, FONT_Small, FONT_7seg** -It is **huge difference** between MicroPython running with **less than 100KB** of free memory and running with **4MB** of free memory. --- -## **The MicroPython firmware is built as esp-idf component** +## Methods + + +### lcd.pixel(x, y [,color]) + +Draw the pixel at position (x,y).
+If *color* is not given, current foreground color is used. + + +### lcd.readPixel(x, y) + +Get the pixel color value at position (x,y). + + +### lcd.line(x, y, x1, y1 [,color]) + +Draw the line from point (x,y) to point (x1,y1)
+If *color* is not given, current foreground color is used. + + +### lcd.lineByAngle(x, y, start, length, angle [,color]) + +Draw the line from point (x,y) with length *lenght* starting st distance *start* from center.
+If *color* is not given, current foreground color is used.
+The angle is given in degrees (0~359). + + +### lcd.triangle(x, y, x1, y1, x2, y2 [,color, fillcolor]) + +Draw the triangel between points (x,y), (x1,y1) and (x2,y2).
+If *color* is not given, current foreground color is used.
+If *fillcolor* is given, filled triangle will be drawn. + + +### lcd.circle(x, y, r [,color, fillcolor]) + +Draw the circle with center at (x,y) and radius r.
+If *color* is not given, current foreground color is used.
+If *fillcolor* is given, filled circle will be drawn. + + +### lcd.ellipse(x, y, rx, ry [opt, color, fillcolor]) + +Draw the circle with center at (x,y) and radius r.
+If *color* is not given, current foreground color is used.
+**opt* argument defines the ellipse segment to be drawn, default id 15, all ellipse segments. + +Multiple segments can drawn, combine (logical or) the values. +* 1 - upper left segment +* 2 - upper right segment +* 4 - lower left segment +* 8 - lower right segment + +If *fillcolor* is given, filled elipse will be drawn. + + +### lcd.arc(x, y, r, thick, start, end [color, fillcolor]) + +Draw the arc with center at (x,y) and radius *r*, starting at angle *start* and ending at angle *end*
+The thicknes of the arc outline is set by the *thick* argument
+If *fillcolor* is given, filled arc will be drawn. + + +### lcd.poly(x, y, r, sides, thick, [color, fillcolor, rotate]) + +Draw the polygon with center at (x,y) and radius *r*, with number of sides *sides*
+The thicknes of the polygon outline is set by the *thick* argument
+If *fillcolor* is given, filled polygon will be drawn.
+If *rotate* is given, the polygon is rotated by the given angle (0~359) + + +### lcd.rect(x, y, width, height, [color, fillcolor]) + +Draw the rectangle from the upper left point at (x,y) and width *width* and height *height*
+If *fillcolor* is given, filled rectangle will be drawn. + + +### lcd.roundrect(x, y, width, height, r [color, fillcolor]) + +Draw the rectangle with rounded corners from the upper left point at **(x,y)** and width **width** and height **height**
+Corner radius is given by **r** argument.
+If **fillcolor** is given, filled rectangle will be drawn. + + +### lcd.clear([color]) + +Clear the screen with default background color or specific color if given. + + +### lcd.clearWin([color]) + +Clear the current display window with default background color or specific color if given. + + +### lcd.orient(orient) + +Set the display orientation.
+Use one of predifined constants:
**lcd.PORTRAIT**, **lcd.LANDSCAPE**, **lcd.PORTRAIT_FLIP**, **lcd.LANDSCAPE_FLIP** + + +### lcd.font(font [,rotate, transparent, fixedwidth, dist, width, outline, color]) + +Set the active font and its characteristics. + +| Argument | Description | +| - | - | +| font | required, use font name constant or font file name | +| rotate | optional, set font rotation angle (0~360) | +| transparent | only draw font's foreground pixels | +| fixedwidth | draw proportional font with fixed character width, max character width from the font is used | +| dist | only for 7-seg font, the distance between bars | +| width | only for 7-seg font, the width of the bar | +| outline | only for 7-seg font, draw the outline | +| color | font color, if not given the current foreground color is used | + + +### lcd.attrib7seg(dist, width, outline, color) + +Set characteristics of the 7-segment font + +| Argument | Description | +| - | - | +| dist | the distance between bars | +| width | the width of the bar | +| outline | outline color | +| color | fill color | + + +### lcd.fontSize() + +Return width and height of the active font + + +### lcd.print(text[,x, y, color, rotate, transparent, fixedwidth, wrap]) + +Display the string *text* at possition (x,y).
+If *color* is not given, current foreground color is used. + +* **x**: horizontal position of the upper left point in pixels, special values can be given: + * CENTER, centers the text + * RIGHT, right justifies the text + * LASTX, continues from last X position; offset can be used: LASTX+n +* **y**: vertical position of the upper left point in pixels, special values can be given: + * CENTER, centers the text + * BOTTOM, bottom justifies the text + * LASTY, continues from last Y position; offset can be used: LASTY+n +* **text**: string to be displayed. Two special characters are allowed in strings: + * ‘\r’ CR (0x0D), clears the display to EOL + * ‘\n’ LF (ox0A), continues to the new line, x=0 + + +### lcd.text(x, y, text [, color]) + +Display the string *text* at possition (x,y).
+If *color* is not given, current foreground color is used. + +* **x**: horizontal position of the upper left point in pixels, special values can be given: + * CENTER, centers the text + * RIGHT, right justifies the text + * LASTX, continues from last X position; offset can be used: LASTX+n +* **y**: vertical position of the upper left point in pixels, special values can be given: + * CENTER, centers the text + * BOTTOM, bottom justifies the text + * LASTY, continues from last Y position; offset can be used: LASTY+n +* **text**: string to be displayed. Two special characters are allowed in strings: + * ‘\r’ CR (0x0D), clears the display to EOL + * ‘\n’ LF (ox0A), continues to the new line, x=0 + + +### lcd.textWidth(text) + +Return the width of the string *text* using the active font fontSize + + +### lcd.textClear(x, y, text [, color]) + +Clear the the screen area used by string *text* at possition (x,y) using the bacckground color *color*.
+If *color* is not given, current background color is used. + + +### lcd.image(x, y, file [,scale, type]) + +Display the image from the file *file* on position (x,y) +* **JPG** and **BMP** can be displayed. +* Constants **lcd.CENTER**, **lcd.BOTTOM**, **lcd.RIGHT** can be used for x&y +* **x** and **y** values can be negative + +**scale** (jpg): image scale factor: 0 to 3; if scale>0, image is scaled by factor 1/(2^scale) (1/2, 1/4 or 1/8)
+**scale** (bmp): image scale factor: 0 to 7; if scale>0, image is scaled by factor 1/(scale+1)
+**type**: optional, set the image type, constants *lcd.JPG* or *lcd.BMP* can be used. If not set, file extension and/or file content will be used to determine the image type. + + +### lcd.setwin(x, y, x1, y1) + +Set active display window to screen rectangle (x,y) - (x1,y1) + -This means the regular esp-idf **menuconfig** system can be used for configuration. Besides the ESP32 configuration itself, many MicroPython options can also be configured via **menuconfig**. +### lcd.resetwin() -This way many features not available in standard ESP32 MicroPython are enabled, like unicore/dualcore, all Flash speed/mode options etc. No manual *sdkconfig.h* editing and tweaking is necessary. +Reset active display window to full screen size. + + +### lcd.savewin() + +Save active display window dimensions. + + +### lcd.restorewin() + +Restore active display window dimensions previously saved wint savewin(). + + +### lcd.screensize() + +Return the display size, (width, height) + + +### lcd.winsize() + +Return the active display window size, (width, height) + + +### lcd.hsb2rgb(hue, saturation, brightness) + +Converts the components of a color, as specified by the HSB model, to an equivalent set of values for the default RGB model.
+Returns 24-bit integer value suitable to be used as color argiment + +Arguments +* **hue**: float: any number, the floor of this number is subtracted from it to create a fraction between 0 and 1. This fractional number is then multiplied by 360 to produce the hue angle in the HSB color model. +* **saturation**: float; 0 ~ 1.0 +* **brightness**: float; 0 ~ 1.0 + + +### lcd.compileFont(file_name [,debug]) + +Compile the source font file (must have **.c** extension) to the binary font file (same name, **.fon** extension) which can be used as external font.
+If *debug=True* the information about compiled font will be printed. + +You can create the **c** source file from any **tft** font using the included [ttf2c_vc2003.exe](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/tree/master/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/) program. +See [README](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/tree/master/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/README.md) for instructions. + +## **Button** --- +### Method +```python +buttonA.isPressed() +buttonA.isReleased() +buttonA.pressedFor(timeout) + +# if set the callback param, it will interrupt callback function +# or if not set param it will return result at once +buttonA.wasPressed(callback=None) +buttonA.wasReleased(callback=None) +buttonA.releasedFor(timeout, callback=None) +``` -### Features - -* MicroPython core based on latest build from [main Micropython repository](https://github.com/micropython/micropython) -* added changes needed to build for ESP32 with psRAM -* Default configuration has **2MB** of MicroPython heap, **20KB** of MicroPython stack, **~200KB** of free DRAM heap for C modules and functions -* MicroPython can be built in **unicore** (FreeRTOS & MicroPython task running only on the first ESP32 core, or **dualcore** configuration (MicroPython task running on ESP32 **App** core) -* ESP32 Flash can be configured in any mode, **QIO**, **QOUT**, **DIO**, **DOUT** -* **BUILD.sh** script is provided to make **building** MicroPython firmware as **easy** as possible -* Internal Fat filesystem is built with esp-idf **wear leveling** driver, so there is less danger of damaging the flash with frequent writes. -* **SPIFFS** filesystem is supported and can be used instead of FatFS in SPI Flash. Configurable via **menuconfig** -* Flexible automatic and/or manual filesystem configuration -* **sdcard** support is included which uses esp-idf **sdmmc** driver and can work in **SD mode** (*1-bit* and *4-bit*) or in **SPI mode** (sd card can be connected to any pins). For imformation on how to connect sdcard see the documentation. -* Files **timestamp** is correctly set to system time both on internal fat filesysten and on sdcard -* **Native ESP32 VFS** support for spi Flash & sdcard filesystems. -* **RTC Class** is added to machine module, including methods for synchronization of system time to **ntp** server, **deepsleep**, **wakeup** from deepsleep **on external pin** level, ... -* **Time zone** can be configured via **menuconfig** and is used when syncronizing time from NTP server -* Built-in **ymodem module** for fast transfer of text/binary files to/from host -* Some additional frozen modules are added, like **pye** editor, **urequests**, **functools**, **logging**, ... -* **Btree** module included, can be Enabled/Disabled via **menuconfig** -* **_threads** module greatly improved, inter-thread **notifications** and **messaging** included -* **Neopixel** module using ESP32 **RMT** peripheral with many new features -* **DHT** module implemented using ESP32 RMT peripheral -* **1-wire** module implemented using ESP32 RMT peripheral -* **i2c** module uses ESP32 hardware i2c driver -* **spi** module uses ESP32 hardware spi driver -* **adc** module improved, new functions added -* **pwm** module, ESP32 hardware based -* **timer** module improved, new timer types and features -* **curl** module added, many client protocols including FTP and eMAIL -* **ssh** module added with sftp/scp support and _exec_ function to execute program on server -* **display** module added with full support for spi TFT displays -* **mqtt** module added, implemented in C, runs in separate task -* **mDNS** module added, implemented in C, runs in separate task -* **telnet** module added, connect to **REPL via WiFi** using telnet protocol -* **ftp** server module added, runs as separate ESP32 task -* **GSM/PPPoS** support, connect to the Internet via GSM module -* **OTA Update** supported, various partitions layouts -* **Eclipse** project files included. To include it into Eclipse goto File->Import->Existing Projects into Workspace->Select root directory->[select *MicroPython_BUILD* directory]->Finish. **Rebuild index**. +### Example +Loop: + +```python +from m5stack import * +import utime + +while True: + if buttonA.wasPressed(): + lcd.print('Button A was Pressed\n') + + if buttonA.wasReleased(): + lcd.print('Button A was Released\n') + + if buttonA.pressedFor(1.5): + lcd.print('Button A pressed for 1.5s\n') + + if buttonA.releasedFor(2): + lcd.print('Button A released for 2s press hold\n') + + utime.sleep(0.1) +``` + +Callback: + + +```python +from m5stack import * + +def on_wasPressed(): + lcd.print('Button B was Pressed\n') + +def on_wasReleased(): + lcd.print('Button B was Released\n') + +def on_releasedFor(): + lcd.print('Button B released for 1.2s press hold\n') + +buttonB.wasPressed(on_wasPressed) +buttonB.wasReleased(on_wasReleased) +buttonB.releasedFor(1.2, on_releasedFor) +``` + +## **SD Card** --- +```python +import uos + +uos.mountsd() +uos.listdir('/sd') +``` + -### How to Build +## **Speaker** --- -Detailed instructions on **MicroPython** building process are available in the [Wiki](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki/build). +```python +from m5stack import * + +speaker.volume(2) +speaker.tone(freq=1800) +speaker.tone(freq=1800, duration=200) # Non-blocking +``` + +## **GPIO** --- +```python +import machine + +pinout = machine.Pin(0, machine.Pin.OUT) +pinout.value(1) -#### Using file systems +pinin = machine.Pin(2, machine.Pin.IN) +val = pinin.value() +``` -Detailed information about using MicroPython file systems are available in the [Wiki](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/wiki/filesystems). +## **PWM** --- +`pwm = machine.PWM(pin [, freq=f] [, duty=d] [, timer=tm])` +`pwm.init([ freq=f] [, duty=d] [, timer=tm])` +| Arg | Description | +| - | - | +| pin | esp32 GPIO number to be used as pwm output
can be given as integer value or machine.Pin object | +| freq | **optional**, default 5 kHz; pwm frequeny in Hz (1 - 40000000) | +| duty | **optional**, default 50% kHz; pwm duty cycle in % (0 - 100) | +| timer | **optional**, default **0**; pwm timer (0 - 3) | -### Some examples +PWM channel is selected automatically from 8 available pwm channels. -Using new machine methods and RTC: ```python import machine +pwm = machine.PWM(26) +pwm.freq(5000) +pwm.duty(66) # 0.0 ~ 100.0 +``` -rtc = machine.RTC() -rtc.init((2017, 6, 12, 14, 35, 20)) +## **ADC** -rtc.now() +--- +```python +import machine -rtc.ntp_sync(server="" [,update_period=]) - # can be empty string, then the default server is used ("pool.ntp.org") +adc = machine.ADC(35) +adc.read() +``` -rtc.synced() - # returns True if time synchronized to NTP server -rtc.wake_on_ext0(Pin, level) -rtc.wake_on_ext1(Pin, level) - # wake up from deepsleep on pin level +## **DAC** -machine.deepsleep(10000) -ESP32: DEEP SLEEP +--- +```python +import machine -# ... -# ... +dac = machine.DAC(machine.Pin(26)) +dac.write(128) +``` + + +## **I2C** + +--- +```python +from machine import I2C -Reset reason: Deepsleep wake-up -Wakeup source: RTC wake-up - uPY stack: 19456 bytes - uPY heap: 3073664/5664/3068000 bytes (in SPIRAM using malloc) +i2c = I2C(freq=400000, sda=21, scl=22) + # create I2C peripheral at frequency of 400kHz + # depending on the port, extra parameters may be required + # to select the peripheral and/or pins to use -MicroPython ESP32_LoBo_v3.1.0 - 2017-01-03 on ESP32 board with ESP32 -Type "help()" for more information. +i2c.scan() # scan for slaves, returning a list of 7-bit addresses -machine.wake_reason() - # returns tuple with reset & wakeup reasons -machine.wake_description() - # returns tuple with strings describing reset & wakeup reasons +i2c.writeto(42, b'123') # write 3 bytes to slave with 7-bit address 42 +i2c.readfrom(42, 4) # read 4 bytes from slave with 7-bit address 42 +i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of slave 42, + # starting at memory-address 8 in the slave +i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of slave 42 + # starting at address 2 in the slave ``` -Using sdcard module: +## **SPI** +--- ```python -import uos +from machine import SPI, Pin + +spi = SPI( + spihost=SPI.HSPI, + baudrate=2600000 + sck=Pin(18), + mosi=Pin(23), + miso=Pin(19), + cs=Pin(4) +) + +spi.write(buf) #NOHEAP +spi.read(nbytes, *, write=0x00) #write is the byte to ?output on MOSI for each byte read in +spi.readinto(buf, *, write=0x00) #NOHEAP +spi.write_readinto(write_buf, read_buf) #NOHEAP; write_buf and read_buf can be the same -uos.mountsd() -uos.listdir('/sd') ``` -Working directory can be changed to root of the sd card automatically on mount: +## **UART** +--- ```python ->>> import uos ->>> uos.mountsd(True) ---------------------- - Mode: SD (4bit) - Name: NCard - Type: SDHC/SDXC -Speed: default speed (25 MHz) - Size: 15079 MB - CSD: ver=1, sector_size=512, capacity=30881792 read_bl_len=9 - SCR: sd_spec=2, bus_width=5 - ->>> uos.listdir() -['overlays', 'bcm2708-rpi-0-w.dtb', ...... ->>> +from machine import UART + +uart2 = UART(2, tx=17, rx=16) +uart2.init(115200, bits=8, parity=None, stop=1) +uart2.read(10) # read 10 characters, returns a bytes object +uart2.read() # read all available characters +uart2.readline() # read a line +uart2.readinto(buf) # read and store into the given buffer +uart2.write('abc') # write the 3 characters ``` +## **Timer** + --- +tm = machine.Timer(timer_no) -Tested on **ESP-WROVER-KIT v3** -![Tested on](https://raw.githubusercontent.com/loboris/MicroPython_ESP32_psRAM_LoBo/master/Documents/ESP-WROVER-KIT_v3_small.jpg) + timer_no argument is the timer number to be used for the timer. + It can be 0 - 3 for 4 hardware timers or 4 - 11 for extended timers. + If extended timer is selected, timer 0 must already be configured in EXTBASE mode. +```python +import machine ---- +tcounter = 0 -### Example terminal session +p1 = machine.Pin(27) +p1.init(p1.OUT) +p1.value(1) +def tcb(timer): + global tcounter + if tcounter & 1: + p1.value(0) + else: + p1.value(1) + tcounter += 1 + if (tcounter % 10000) == 0: + print("[tcb] timer: {} counter: {}".format(timer.timernum(), tcounter)) +t1 = machine.Timer(2) +t1.init(period=20, mode=t1.PERIODIC, callback=tcb) ``` -I (0) cpu_start: App cpu up. -I (1569) spiram: SPI SRAM memory test OK -I (1570) heap_init: Initializing. RAM available for dynamic allocation: -D (1570) heap_init: New heap initialised at 0x3ffae6e0 -I (1575) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM -D (1581) heap_init: New heap initialised at 0x3ffc1a00 -I (1586) heap_init: At 3FFC1A00 len 0001E600 (121 KiB): DRAM -I (1593) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM -I (1599) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM -D (1606) heap_init: New heap initialised at 0x4009d70c -I (1611) heap_init: At 4009D70C len 000028F4 (10 KiB): IRAM -I (1617) cpu_start: Pro cpu start user code -I (1622) spiram: Adding pool of 4096K of external SPI memory to heap allocator -I (1630) spiram: Reserving pool of 32K of internal memory for DMA/internal allocations -D (1646) clk: RTC_SLOW_CLK calibration value: 3305242 -D (89) intr_alloc: Connected src 46 to int 2 (cpu 0) -D (90) intr_alloc: Connected src 57 to int 3 (cpu 0) -D (90) intr_alloc: Connected src 24 to int 9 (cpu 0) -I (95) cpu_start: Starting scheduler on PRO CPU. -D (0) intr_alloc: Connected src 25 to int 2 (cpu 1) -I (4) cpu_start: Starting scheduler on APP CPU. -D (119) heap_init: New heap initialised at 0x3ffe0440 -D (125) heap_init: New heap initialised at 0x3ffe4350 -D (130) intr_alloc: Connected src 16 to int 12 (cpu 0) -D (145) nvs: nvs_flash_init_custom partition=nvs start=9 count=4 -D (178) intr_alloc: Connected src 34 to int 3 (cpu 1) -D (187) intr_alloc: Connected src 22 to int 4 (cpu 1) - -Internal FS (SPIFFS): Mounted on partition 'internalfs' [size: 1048576; Flash address: 0x2D0000] ----------------- -Filesystem size: 956416 B - Used: 512 B - Free: 955904 B ----------------- - -FreeRTOS running on BOTH CORES, MicroPython task running on both cores. -Running from partition at 10000, type 10 [MicroPython_1]. - - Reset reason: Power on reset - uPY stack: 19456 bytes - uPY heap: 3073664/5664/3068000 bytes (in SPIRAM using malloc) - -MicroPython ESP32_LoBo_v3.1.0 - 2017-01-03 on ESP32 board with ESP32 -Type "help()" for more information. ->>> ->>> import micropython, machine ->>> ->>> micropython.mem_info() -stack: 752 out of 19456 -GC: total: 3073664, used: 5904, free: 3067760 - No. of 1-blocks: 19, 2-blocks: 7, max blk sz: 325, max free sz: 191725 ->>> ->>> machine.heap_info() -Heap outside of MicroPython heap: ---------------------------------- - Free: 239920 - Allocated: 52328 - Minimum free: 233100 - Total blocks: 85 -Largest free block: 113804 - Allocated blocks: 79 - Free blocks: 6 - -SPIRAM info: ------------- - Free: 1048532 - Allocated: 3145728 - Minimum free: 1048532 - Total blocks: 2 -Largest free block: 1048532 - Allocated blocks: 1 - Free blocks: 1 ->>> + +## **Neopixel** + +--- +```python +import machine, time + +np = machine.Neopixel(machine.Pin(22), 24) + +def rainbow(loops=120, delay=1, sat=1.0, bri=0.2): + for pos in range(0, loops): + for i in range(0, 24): + dHue = 360.0/24*(pos+i); + hue = dHue % 360; + np.setHSB(i, hue, sat, bri, 1, False) + np.show() + if delay > 0: + time.sleep_ms(delay) + +def blinkRainbow(loops=10, delay=250): + for pos in range(0, loops): + for i in range(0, 24): + dHue = 360.0/24*(pos+i); + hue = dHue % 360; + np.setHSB(i, hue, 1.0, 0.1, 1, False) + np.show() + time.sleep_ms(delay) + np.clear() + time.sleep_ms(delay) +``` + +## **RTC** + +--- +```python +import machine +import utime + +rtc = machine.RTC() +rtc.ntp_sync(server="hr.pool.ntp.org", tz="CET-1CEST") +rtc.synced() +True +utime.gmtime() +(2018, 1, 29, 16, 3, 18, 2, 29) +utime.localtime() +(2018, 1, 29, 17, 3, 30, 2, 29) ``` diff --git a/Tools/.gitignore b/Tools/.gitignore index 2be2b7f1..f78a33e7 100644 --- a/Tools/.gitignore +++ b/Tools/.gitignore @@ -3,4 +3,7 @@ esp-idf_psram/ xtensa-esp32-elf/ xtensa-esp32-elf_psram/ esp-idf_patches/ +esp-idf_patches_novi/ *.id +*_new.tar.xz +*_old.tar.xz diff --git a/Tools/Linux/xtensa-esp32-elf_aarch64.tar.xz b/Tools/Linux/xtensa-esp32-elf_aarch64.tar.xz new file mode 100644 index 00000000..52f42465 Binary files /dev/null and b/Tools/Linux/xtensa-esp32-elf_aarch64.tar.xz differ diff --git a/Tools/Win/xtensa-esp32-elf.tar.xz b/Tools/Win/xtensa-esp32-elf.tar.xz deleted file mode 100644 index 022dafcb..00000000 Binary files a/Tools/Win/xtensa-esp32-elf.tar.xz and /dev/null differ diff --git a/Tools/esp-idf.tar.xz b/Tools/esp-idf.tar.xz index b18fa6f9..0b610024 100644 Binary files a/Tools/esp-idf.tar.xz and b/Tools/esp-idf.tar.xz differ diff --git a/Tools/esp-idf_github.sha b/Tools/esp-idf_github.sha new file mode 100644 index 00000000..6e851ff9 --- /dev/null +++ b/Tools/esp-idf_github.sha @@ -0,0 +1 @@ +53509c7bfde505b6d0aa5ce0cd1ac48bc3743039