diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..461fc2f --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,23 @@ +# MicroPython for ESP32 + +# 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 sources related to **MicroPython** are under **MIT** license. + +**esp-idf** on which this port is based, is released under **Apache v2.0** license. + +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. + +--- + +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. + +In case you don't want to use GPL licensed code, thit 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/.settings/language.settings.xml b/MicroPython_BUILD/.settings/language.settings.xml index ce5cbfe..a3d2bfd 100644 --- a/MicroPython_BUILD/.settings/language.settings.xml +++ b/MicroPython_BUILD/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/MicroPython_BUILD/BUILD.sh b/MicroPython_BUILD/BUILD.sh index e926857..fe22af0 100755 --- a/MicroPython_BUILD/BUILD.sh +++ b/MicroPython_BUILD/BUILD.sh @@ -45,7 +45,7 @@ #======================= -TOOLS_VER=ver20180127.id +TOOLS_VER=ver20180228.id #======================= # ----------------------------- diff --git a/MicroPython_BUILD/components/bootloader/Kconfig.projbuild b/MicroPython_BUILD/components/bootloader/Kconfig.projbuild deleted file mode 100644 index 3680a47..0000000 --- a/MicroPython_BUILD/components/bootloader/Kconfig.projbuild +++ /dev/null @@ -1,247 +0,0 @@ -menu "Bootloader config" -choice LOG_BOOTLOADER_LEVEL - bool "Bootloader log verbosity" - default LOG_BOOTLOADER_LEVEL_INFO - help - Specify how much output to see in bootloader logs. - -config LOG_BOOTLOADER_LEVEL_NONE - bool "No output" -config LOG_BOOTLOADER_LEVEL_ERROR - bool "Error" -config LOG_BOOTLOADER_LEVEL_WARN - bool "Warning" -config LOG_BOOTLOADER_LEVEL_INFO - bool "Info" -config LOG_BOOTLOADER_LEVEL_DEBUG - bool "Debug" -config LOG_BOOTLOADER_LEVEL_VERBOSE - bool "Verbose" -endchoice - -config LOG_BOOTLOADER_LEVEL - int - default 0 if LOG_BOOTLOADER_LEVEL_NONE - default 1 if LOG_BOOTLOADER_LEVEL_ERROR - default 2 if LOG_BOOTLOADER_LEVEL_WARN - default 3 if LOG_BOOTLOADER_LEVEL_INFO - default 4 if LOG_BOOTLOADER_LEVEL_DEBUG - default 5 if LOG_BOOTLOADER_LEVEL_VERBOSE - -config BOOTLOADER_SPI_WP_PIN - int "SPI Flash WP Pin when customising pins via efuse (read help)" - range 0 33 - default 7 - depends on FLASHMODE_QIO || FLASHMODE_QOUT - help - This value is ignored unless flash mode is set to QIO or QOUT *and* the SPI flash pins have been - overriden by setting the efuses SPI_PAD_CONFIG_xxx. - - When this is the case, the Efuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka ESP32 - pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in Efuse. That pin number is compiled into the bootloader - instead. - - The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash. - -config BOOTLOADER_VDDSDIO_BOOST - bool "Increase VDDSDIO 1.8V LDO voltage to 1.9V" - default y - help - If this option is enabled, and VDDSDIO LDO is set to 1.8V (using EFUSE - or MTDI bootstrapping pin), bootloader will change LDO settings to - output 1.9V instead. This helps prevent flash chip from browning out - during flash programming operations. - - This option has no effect if VDDSDIO is set to 3.3V, or if the internal - VDDSDIO regulator is disabled via efuse. - -endmenu # Bootloader - - -menu "Security features" - -config SECURE_BOOT_ENABLED - bool "Enable secure boot in bootloader (READ DOCS FIRST)" - default N - help - Build a bootloader which enables secure boot on first boot. - - Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature. There are implications for reflashing updated apps once secure boot is enabled. - - When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default. - - Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling. - -choice SECURE_BOOTLOADER_MODE - bool "Secure bootloader mode" - depends on SECURE_BOOT_ENABLED - default SECURE_BOOTLOADER_ONE_TIME_FLASH - -config SECURE_BOOTLOADER_ONE_TIME_FLASH - bool "One-time flash" - help - On first boot, the bootloader will generate a key which is not readable externally or by software. A digest is generated from the bootloader image itself. This digest will be verified on each subsequent boot. - - Enabling this option means that the bootloader cannot be changed after the first time it is booted. - -config SECURE_BOOTLOADER_REFLASHABLE - bool "Reflashable" - help - Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key. - - This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing key. - - This option is less secure than one-time flash, because a leak of the digest key from one device allows reflashing of any device that uses it. - -endchoice - -config SECURE_BOOT_BUILD_SIGNED_BINARIES - bool "Sign binaries during build" - depends on SECURE_BOOT_ENABLED - default y - help - Once secure boot is enabled, bootloader will only boot if partition table and app image are signed. - - If enabled, these binary files are signed as part of the build process. The file named in "Secure boot private signing key" will be used to sign the image. - - If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py (for example, on a remote signing server.) - -config SECURE_BOOT_SIGNING_KEY - string "Secure boot private signing key" - depends on SECURE_BOOT_BUILD_SIGNED_BINARIES - default secure_boot_signing_key.pem - help - Path to the key file used to sign partition tables and app images for secure boot. Once secure boot is enabled, bootloader will only boot if partition table and app image are signed. - - Key file is an ECDSA private key (NIST256p curve) in PEM format. - - Path is evaluated relative to the project directory. - - You can generate a new signing key by running the following command: - espsecure.py generate_signing_key secure_boot_signing_key.pem - - See docs/security/secure-boot.rst for details. - -config SECURE_BOOT_VERIFICATION_KEY - string "Secure boot public signature verification key" - depends on SECURE_BOOT_ENABLED && !SECURE_BOOT_BUILD_SIGNED_BINARIES - default signature_verification_key.bin - help - Path to a public key file used to verify signed images. This key is compiled into the bootloader, - and may also be used to verify signatures on OTA images after download. - - Key file is in raw binary format, and can be extracted from a - PEM formatted private key using the espsecure.py - extract_public_key command. - - Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling. - -config SECURE_BOOT_INSECURE - bool "Allow potentially insecure options" - depends on SECURE_BOOT_ENABLED - default N - help - You can disable some of the default protections offered by secure boot, in order to enable testing or a custom combination of security features. - - Only enable these options if you are very sure. - - Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling. - -config FLASH_ENCRYPTION_ENABLED - bool "Enable flash encryption on boot (READ DOCS FIRST)" - default N - help - If this option is set, flash contents will be encrypted by the bootloader on first boot. - - Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted - system is complicated and not always possible. - - Read https://esp-idf.readthedocs.io/en/latest/security/flash-encryption.html before enabling. - -config FLASH_ENCRYPTION_INSECURE - bool "Allow potentially insecure options" - depends on FLASH_ENCRYPTION_ENABLED - default N - help - You can disable some of the default protections offered by flash encryption, in order to enable testing or a custom combination of security features. - - Only enable these options if you are very sure. - - Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details. - -menu "Potentially insecure options" - visible if FLASH_ENCRYPTION_INSECURE || SECURE_BOOT_INSECURE - -# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE -# and/or FLASH_ENCRYPTION_INSECURE in "depends on", as the menu -# itself doesn't enable/disable its children (if it's not set, -# it's possible for the insecure menu to be disabled but the insecure option -# to remain on which is very bad.) - -config SECURE_BOOT_ALLOW_ROM_BASIC - bool "Leave ROM BASIC Interpreter available on reset" - depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE - default N - help - By default, the BASIC ROM Console starts on reset if no valid bootloader is - read from the flash. - - When either flash encryption or secure boot are enabled, the default is to - disable this BASIC fallback mode permanently via efuse. - - If this option is set, this efuse is not burned and the BASIC ROM Console may - remain accessible. Only set this option in testing environments. - -config SECURE_BOOT_ALLOW_JTAG - bool "Allow JTAG Debugging" - depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE - default N - help - If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot when either secure boot or flash encryption is enabled. - - Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption and some of the protections of secure boot. - - Only set this option in testing environments. - - -config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT - bool "Leave UART bootloader encryption enabled" - depends on FLASH_ENCRYPTION_INSECURE - default N - help - If not set (default), the bootloader will permanently disable UART bootloader encryption access on first boot. If set, the UART bootloader will still be able to access hardware encryption. - - It is recommended to only set this option in testing environments. - -config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT - bool "Leave UART bootloader decryption enabled" - depends on FLASH_ENCRYPTION_INSECURE - default N - help - If not set (default), the bootloader will permanently disable UART bootloader decryption access on first boot. If set, the UART bootloader will still be able to access hardware decryption. - - Only set this option in testing environments. Setting this option allows complete bypass of flash encryption. - -config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE - bool "Leave UART bootloader flash cache enabled" - depends on FLASH_ENCRYPTION_INSECURE - default N - help - If not set (default), the bootloader will permanently disable UART bootloader flash cache access on first boot. If set, the UART bootloader will still be able to access the flash cache. - - Only set this option in testing environments. - -config SECURE_BOOT_TEST_MODE - bool "Secure boot test mode: don't permanently set any efuses" - depends on SECURE_BOOT_INSECURE - default N - help - If this option is set, all permanent secure boot changes (via Efuse) are disabled. - - Log output will state changes which would be applied, but they will not be. - - This option is for testing purposes only - it completely disables secure boot protection. - - -endmenu # Potentially Insecure -endmenu # Security features diff --git a/MicroPython_BUILD/components/bootloader/Makefile.projbuild b/MicroPython_BUILD/components/bootloader/Makefile.projbuild deleted file mode 100644 index 7876635..0000000 --- a/MicroPython_BUILD/components/bootloader/Makefile.projbuild +++ /dev/null @@ -1,126 +0,0 @@ -# Bootloader component (top-level project parts) -# -# The bootloader is not a real component that gets linked into the project. -# Instead it is an entire standalone project (in subproject/) that gets -# built in the upper project's build directory. This Makefile.projbuild provides -# the glue to build the bootloader project from the original project. It -# basically runs Make in the subproject/ directory but it needs to -# zero some variables the ESP-IDF project.mk makefile exports first, to not -# let them interfere. -# -BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH) -BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader) -BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin - -# signing key path is resolved relative to the project directory -CONFIG_SECURE_BOOT_SIGNING_KEY ?= -SECURE_BOOT_SIGNING_KEY=$(abspath $(call dequote,$(CONFIG_SECURE_BOOT_SIGNING_KEY))) -export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component - -# Has a matching value in bootloader_support esp_flash_partitions.h -BOOTLOADER_OFFSET := 0x1000 - -# Custom recursive make for bootloader sub-project -# -# NB: Some variables are cleared in the environment, not -# overriden, because they need to be re-defined in the child -# project. -BOOTLOADER_MAKE= +\ - PROJECT_PATH= \ - COMPONENT_DIRS= \ - $(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/subproject \ - V=$(V) \ - BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \ - TEST_COMPONENTS= \ - TESTS_ALL= - -.PHONY: bootloader-clean bootloader-flash bootloader-list-components bootloader $(BOOTLOADER_BIN) - -$(BOOTLOADER_BIN): $(SDKCONFIG_MAKEFILE) - $(BOOTLOADER_MAKE) $@ - -clean: bootloader-clean - -bootloader-list-components: - $(BOOTLOADER_MAKE) list-components - -ifndef CONFIG_SECURE_BOOT_ENABLED -# If secure boot disabled, bootloader flashing is integrated -# with 'make flash' and no warnings are printed. - -bootloader: $(BOOTLOADER_BIN) - @echo $(SEPARATOR) - @echo "Bootloader built. Default flash command is:" - @echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $^" - -ESPTOOL_ALL_FLASH_ARGS += $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN) - -bootloader-flash: $(BOOTLOADER_BIN) $(call prereq_if_explicit,erase_flash) - $(ESPTOOLPY_WRITE_FLASH) 0x1000 $^ - -else ifdef CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH - -# One time flashing requires user to run esptool.py command themselves, -# and warning is printed about inability to reflash. -# -# The flashing command is deliberately printed without an auto-reset -# step, so the device doesn't immediately reset to flash itself. - -bootloader: $(BOOTLOADER_BIN) - @echo $(SEPARATOR) - @echo "Bootloader built. One-time flash command is:" - @echo "$(subst hard_reset,no_reset,$(ESPTOOLPY_WRITE_FLASH)) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)" - @echo $(SEPARATOR) - @echo "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device" - -else ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE -# Reflashable secure bootloader -# generates a digest binary (bootloader + digest) - -BOOTLOADER_DIGEST_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-reflash-digest.bin -SECURE_BOOTLOADER_KEY := $(BOOTLOADER_BUILD_DIR)/secure-bootloader-key.bin - -ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES -$(SECURE_BOOTLOADER_KEY): $(SECURE_BOOT_SIGNING_KEY) - $(ESPSECUREPY) digest_private_key -k $< $@ -else -$(SECURE_BOOTLOADER_KEY): - @echo "No pre-generated key for a reflashable secure bootloader is available, due to signing configuration." - @echo "To generate one, you can use this command:" - @echo "espsecure.py generate_flash_encryption_key $@" - @echo "then re-run make." - exit 1 -endif - -bootloader: $(BOOTLOADER_DIGEST_BIN) - @echo $(SEPARATOR) - @echo "Bootloader built and secure digest generated. First time flash command is:" - @echo "$(ESPEFUSEPY) burn_key secure_boot $(SECURE_BOOTLOADER_KEY)" - @echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)" - @echo $(SEPARATOR) - @echo "To reflash the bootloader after initial flash:" - @echo "$(ESPTOOLPY_WRITE_FLASH) 0x0 $(BOOTLOADER_DIGEST_BIN)" - @echo $(SEPARATOR) - @echo "* After first boot, only re-flashes of this kind (with same key) will be accepted." - @echo "* Not recommended to re-use the same secure boot keyfile on multiple production devices." - -$(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) - @echo "DIGEST $(notdir $@)" - $(Q) $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $< - -else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH -bootloader: - @echo "Invalid bootloader target: bad sdkconfig?" - @exit 1 -endif - -ifndef CONFIG_SECURE_BOOT_ENABLED -# don't build bootloader by default is secure boot is enabled -all_binaries: $(BOOTLOADER_BIN) -endif - -bootloader-clean: $(SDKCONFIG_MAKEFILE) - $(BOOTLOADER_MAKE) app-clean -ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE - rm -f $(SECURE_BOOTLOADER_KEY) $(BOOTLOADER_DIGEST_BIN) -endif diff --git a/MicroPython_BUILD/components/bootloader/component.mk b/MicroPython_BUILD/components/bootloader/component.mk deleted file mode 100644 index b3e40ee..0000000 --- a/MicroPython_BUILD/components/bootloader/component.mk +++ /dev/null @@ -1,7 +0,0 @@ -# bootloader component is special, as bootloader is also a project. -# -# This top-level component is only configuration files for the IDF project. -# -# See Makefile.projbuild for the targets which actually build the bootloader. -COMPONENT_CONFIG_ONLY := 1 - diff --git a/MicroPython_BUILD/components/bootloader/subproject/.gitignore b/MicroPython_BUILD/components/bootloader/subproject/.gitignore deleted file mode 100644 index 278a862..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build -sdkconfig diff --git a/MicroPython_BUILD/components/bootloader/subproject/Makefile b/MicroPython_BUILD/components/bootloader/subproject/Makefile deleted file mode 100644 index e01dc3c..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# -ifeq ("$(MAKELEVEL)","0") -$(error Bootloader makefile expects to be run as part of 'make bootloader' from a top-level project.) -endif - -PROJECT_NAME := bootloader - -COMPONENTS := esptool_py bootloader_support log spi_flash micro-ecc soc main - -# Clear C and CXX from top level project -CFLAGS = -CXXFLAGS = - -#We cannot include the esp32 component directly but we need its includes. -CFLAGS += -I $(IDF_PATH)/components/esp32/include - -# The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included. -# -# IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op -IS_BOOTLOADER_BUILD := 1 -export IS_BOOTLOADER_BUILD - -# BOOTLOADER_BUILD macro is the same, for source file changes -CFLAGS += -D BOOTLOADER_BUILD=1 - -# include the top-level "project" include directory, for sdkconfig.h -CFLAGS += -I$(BUILD_DIR_BASE)/../include - -include $(IDF_PATH)/make/project.mk diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/Makefile.projbuild b/MicroPython_BUILD/components/bootloader/subproject/main/Makefile.projbuild deleted file mode 100644 index c368c68..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/Makefile.projbuild +++ /dev/null @@ -1,4 +0,0 @@ -# Submodules normally added in component.mk, but fully qualified -# paths can be added at this level (we need binary librtc to be -# available to link bootloader). -COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp32/lib diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/bootloader_config.h b/MicroPython_BUILD/components/bootloader/subproject/main/bootloader_config.h deleted file mode 100644 index 289a9e3..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/bootloader_config.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef __BOOT_CONFIG_H__ -#define __BOOT_CONFIG_H__ - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "esp_flash_data_types.h" -#include "soc/soc.h" - -#define SPI_SEC_SIZE 0x1000 - -#define SPI_ERROR_LOG "spi flash error" - -#define MAX_OTA_SLOTS 16 - -typedef struct { - esp_partition_pos_t ota_info; - esp_partition_pos_t factory; - esp_partition_pos_t test; - esp_partition_pos_t ota[MAX_OTA_SLOTS]; - uint32_t app_count; - uint32_t selected_subtype; -} bootloader_state_t; - -bool flash_encrypt(bootloader_state_t *bs); - -#ifdef __cplusplus -} -#endif - -#endif /* __BOOT_CONFIG_H__ */ diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/bootloader_start.c b/MicroPython_BUILD/components/bootloader/subproject/main/bootloader_start.c deleted file mode 100644 index 0ee5348..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/bootloader_start.c +++ /dev/null @@ -1,994 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include -#include - -#include "esp_attr.h" -#include "esp_log.h" - -#include "rom/cache.h" -#include "rom/efuse.h" -#include "rom/ets_sys.h" -#include "rom/spi_flash.h" -#include "rom/crc.h" -#include "rom/rtc.h" -#include "rom/uart.h" -#include "rom/gpio.h" -#include "rom/secure_boot.h" - -#include "soc/soc.h" -#include "soc/cpu.h" -#include "soc/rtc.h" -#include "soc/dport_reg.h" -#include "soc/io_mux_reg.h" -#include "soc/efuse_reg.h" -#include "soc/rtc_cntl_reg.h" -#include "soc/timer_group_reg.h" -#include "soc/gpio_reg.h" -#include "soc/gpio_sig_map.h" - -#include "sdkconfig.h" -#include "esp_image_format.h" -#include "esp_secure_boot.h" -#include "esp_flash_encrypt.h" -#include "esp_flash_partitions.h" -#include "bootloader_flash.h" -#include "bootloader_random.h" -#include "bootloader_config.h" -#include "bootloader_clock.h" - -#include "flash_qio_mode.h" - -extern int _bss_start; -extern int _bss_end; -extern int _data_start; -extern int _data_end; - -static const char* TAG = "boot"; - -/* Reduce literal size for some generic string literals */ -#define MAP_MSG "Mapping segment %d as %s" -#define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped." - -void bootloader_main(); -static void unpack_load_app(const esp_image_metadata_t *data); -static void print_flash_info(const esp_image_header_t* pfhdr); -static void set_cache_and_start_app(uint32_t drom_addr, - uint32_t drom_load_addr, - uint32_t drom_size, - uint32_t irom_addr, - uint32_t irom_load_addr, - uint32_t irom_size, - uint32_t entry_addr); -static void update_flash_config(const esp_image_header_t* pfhdr); -static void vddsdio_configure(); -static void flash_gpio_configure(); -static void uart_console_configure(void); -static void wdt_reset_check(void); - -/* - * We arrive here after the ROM bootloader finished loading this second stage bootloader from flash. - * The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset. - * We do have a stack, so we can do the initialization in C. - */ -void call_start_cpu0() -{ - cpu_configure_region_protection(); - - /* Sanity check that static RAM is after the stack */ -#ifndef NDEBUG - { - int *sp = get_sp(); - assert(&_bss_start <= &_bss_end); - assert(&_data_start <= &_data_end); - assert(sp < &_bss_start); - assert(sp < &_data_start); - } -#endif - - //Clear bss - memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start)); - - /* completely reset MMU for both CPUs - (in case serial bootloader was running) */ - Cache_Read_Disable(0); - Cache_Read_Disable(1); - Cache_Flush(0); - Cache_Flush(1); - mmu_init(0); - DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR); - mmu_init(1); - DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR); - /* (above steps probably unnecessary for most serial bootloader - usage, all that's absolutely needed is that we unmask DROM0 - cache on the following two lines - normal ROM boot exits with - DROM0 cache unmasked, but serial bootloader exits with it - masked. However can't hurt to be thorough and reset - everything.) - - The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are - necessary to work around a hardware bug. - */ - DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0); - DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0); - - bootloader_main(); -} - - -/** @brief Load partition table - * - * Parse partition table, get useful data such as location of - * OTA data partition, factory app partition, and test app partition. - * - * @param bs bootloader state structure used to save read data - * @return return true if the partition table was succesfully loaded and MD5 checksum is valid. - */ -bool load_partition_table(bootloader_state_t* bs) -{ - const esp_partition_info_t *partitions; - const int ESP_PARTITION_TABLE_DATA_LEN = 0xC00; /* length of actual data (signature is appended to this) */ - char *partition_usage; - esp_err_t err; - int num_partitions; - -#ifdef CONFIG_SECURE_BOOT_ENABLED - if(esp_secure_boot_enabled()) { - ESP_LOGI(TAG, "Verifying partition table signature..."); - err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to verify partition table signature."); - return false; - } - ESP_LOGD(TAG, "Partition table signature verified"); - } -#endif - - partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN); - if (!partitions) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN); - return false; - } - ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions); - - err = esp_partition_table_basic_verify(partitions, true, &num_partitions); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to verify partition table"); - return false; - } - - ESP_LOGI(TAG, "Partition Table:"); - ESP_LOGI(TAG, "## Label Usage Type ST Offset Length"); - - for(int i = 0; i < num_partitions; i++) { - const esp_partition_info_t *partition = &partitions[i]; - ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition); - ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype); - partition_usage = "unknown"; - - /* valid partition table */ - switch(partition->type) { - case PART_TYPE_APP: /* app partition */ - switch(partition->subtype) { - case PART_SUBTYPE_FACTORY: /* factory binary */ - bs->factory = partition->pos; - partition_usage = "factory app"; - break; - case PART_SUBTYPE_TEST: /* test binary */ - bs->test = partition->pos; - partition_usage = "test app"; - break; - default: - /* OTA binary */ - if ((partition->subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) { - bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos; - ++bs->app_count; - partition_usage = "OTA app"; - } - else { - partition_usage = "Unknown app"; - } - break; - } - break; /* PART_TYPE_APP */ - case PART_TYPE_DATA: /* data partition */ - switch(partition->subtype) { - case PART_SUBTYPE_DATA_OTA: /* ota data */ - bs->ota_info = partition->pos; - partition_usage = "OTA data"; - break; - case PART_SUBTYPE_DATA_RF: - partition_usage = "RF data"; - break; - case PART_SUBTYPE_DATA_WIFI: - partition_usage = "WiFi data"; - break; - default: - partition_usage = "Unknown data"; - break; - } - break; /* PARTITION_USAGE_DATA */ - default: /* other partition type */ - break; - } - - /* print partition type info */ - ESP_LOGI(TAG, "%2d %-16s %-16s %02x %02x %08x %08x", i, partition->label, partition_usage, - partition->type, partition->subtype, - partition->pos.offset, partition->pos.size); - } - - bootloader_munmap(partitions); - - ESP_LOGI(TAG,"End of partition table"); - return true; -} - -static uint32_t ota_select_crc(const esp_ota_select_entry_t *s) -{ - return crc32_le(UINT32_MAX, (uint8_t*)&s->ota_seq, 4); -} - -static bool ota_select_valid(const esp_ota_select_entry_t *s) -{ - return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s); -} - -/* indexes used by index_to_partition are the OTA index - number, or these special constants */ -#define FACTORY_INDEX (-1) -#define TEST_APP_INDEX (-2) -#define INVALID_INDEX (-99) - -/* Given a partition index, return the partition position data from the bootloader_state_t structure */ -static esp_partition_pos_t index_to_partition(const bootloader_state_t *bs, int index) -{ - if (index == FACTORY_INDEX) { - return bs->factory; - } - - if (index == TEST_APP_INDEX) { - return bs->test; - } - - if (index >= 0 && index < MAX_OTA_SLOTS && index < bs->app_count) { - return bs->ota[index]; - } - - esp_partition_pos_t invalid = { 0 }; - return invalid; -} - -static void log_invalid_app_partition(int index) -{ - const char *not_bootable = " is not bootable"; /* save a few string literal bytes */ - switch(index) { - case FACTORY_INDEX: - ESP_LOGE(TAG, "Factory app partition%s", not_bootable); - break; - case TEST_APP_INDEX: - ESP_LOGE(TAG, "Factory test app partition%s", not_bootable); - break; - default: - ESP_LOGE(TAG, "OTA app partition slot %d%s", index, not_bootable); - break; - } -} - - -/** LoBo - * @function : ForceFactoryBoot - * @description: Add by Imtiaz @ Syrp for failsafe mode - * - * @inputs: void - */ -static uint8_t ForceFactoryBoot(void) -{ - #if CONFIG_GPIO_INPUT_FORCE_FACTORY - uint8_t timer = 0; - gpio_pad_select_gpio(2); - ets_delay_us(10000); //delay 10 msecs - - while (GPIO_INPUT_GET(2)) { - if ((timer % 5) == 0) { - ESP_LOGE(TAG, "Force Factory boot Pin is Active!"); - } - ets_delay_us(100000); // wait 100 ms - timer++; - if (timer == 30) { - ESP_LOGE(TAG, "Forcing boot to Factory partition"); - return 1; - } - } - ESP_LOGW(TAG, "Normal boot"); - #endif - return 0; -} - -/* Return the index of the selected boot partition. - - This is the preferred boot partition, as determined by the partition table & - any OTA sequence number found in OTA data. - - This partition will only be booted if it contains a valid app image, otherwise load_boot_image() will search - for a valid partition using this selection as the starting point. -*/ -static int get_selected_boot_partition(const bootloader_state_t *bs) -{ - esp_ota_select_entry_t sa,sb; - const esp_ota_select_entry_t *ota_select_map; - - if (bs->ota_info.offset != 0 && !ForceFactoryBoot()) { // LoBo - // partition table has OTA data partition - if (bs->ota_info.size < 2 * SPI_SEC_SIZE) { - ESP_LOGE(TAG, "ota_info partition size %d is too small (minimum %d bytes)", bs->ota_info.size, sizeof(esp_ota_select_entry_t)); - return INVALID_INDEX; // can't proceed - } - - ESP_LOGD(TAG, "OTA data offset 0x%x", bs->ota_info.offset); - ota_select_map = bootloader_mmap(bs->ota_info.offset, bs->ota_info.size); - if (!ota_select_map) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", bs->ota_info.offset, bs->ota_info.size); - return INVALID_INDEX; // can't proceed - } - memcpy(&sa, ota_select_map, sizeof(esp_ota_select_entry_t)); - memcpy(&sb, (uint8_t *)ota_select_map + SPI_SEC_SIZE, sizeof(esp_ota_select_entry_t)); - bootloader_munmap(ota_select_map); - - ESP_LOGD(TAG, "OTA sequence values A 0x%08x B 0x%08x", sa.ota_seq, sb.ota_seq); - if(sa.ota_seq == UINT32_MAX && sb.ota_seq == UINT32_MAX) { - ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF)"); - if (bs->factory.offset != 0) { - ESP_LOGI(TAG, "Defaulting to factory image"); - return FACTORY_INDEX; - } else { - ESP_LOGI(TAG, "No factory image, trying OTA 0"); - return 0; - } - } else { - bool ota_valid = false; - const char *ota_msg; - int ota_seq; // Raw OTA sequence number. May be more than # of OTA slots - if(ota_select_valid(&sa) && ota_select_valid(&sb)) { - ota_valid = true; - ota_msg = "Both OTA values"; - ota_seq = MAX(sa.ota_seq, sb.ota_seq) - 1; - } else if(ota_select_valid(&sa)) { - ota_valid = true; - ota_msg = "Only OTA sequence A is"; - ota_seq = sa.ota_seq - 1; - } else if(ota_select_valid(&sb)) { - ota_valid = true; - ota_msg = "Only OTA sequence B is"; - ota_seq = sb.ota_seq - 1; - } - - if (ota_valid) { - int ota_slot = ota_seq % bs->app_count; // Actual OTA partition selection - ESP_LOGD(TAG, "%s valid. Mapping seq %d -> OTA slot %d", ota_msg, ota_seq, ota_slot); - return ota_slot; - } else if (bs->factory.offset != 0) { - ESP_LOGE(TAG, "ota data partition invalid, falling back to factory"); - return FACTORY_INDEX; - } else { - ESP_LOGE(TAG, "ota data partition invalid and no factory, will try all partitions"); - return FACTORY_INDEX; - } - } - } - - // otherwise, start from factory app partition and let the search logic - // proceed from there - return FACTORY_INDEX; -} - -/* Return true if a partition has a valid app image that was successfully loaded */ -static bool try_load_partition(const esp_partition_pos_t *partition, esp_image_metadata_t *data) -{ - if (partition->size == 0) { - ESP_LOGD(TAG, "Can't boot from zero-length partition"); - return false; - } - - if (esp_image_load(ESP_IMAGE_LOAD, partition, data) == ESP_OK) { - ESP_LOGI(TAG, "Loaded app from partition at offset 0x%x", - partition->offset); - return true; - } - - return false; -} - -#define TRY_LOG_FORMAT "Trying partition index %d offs 0x%x size 0x%x" - -/* Load the app for booting. Start from partition 'start_index', if not bootable then work backwards to FACTORY_INDEX - * (ie try any OTA slots in descending order and then the factory partition). - * - * If still nothing, start from 'start_index + 1' and work up to highest numbered OTA partition. - * - * If still nothing, try TEST_APP_INDEX - * - * Returns true on success, false if there's no bootable app in the partition table. - */ -static bool load_boot_image(const bootloader_state_t *bs, int start_index, esp_image_metadata_t *result) -{ - int index = start_index; - esp_partition_pos_t part; - - /* work backwards from start_index, down to the factory app */ - for(index = start_index; index >= FACTORY_INDEX; index--) { - part = index_to_partition(bs, index); - if (part.size == 0) { - continue; - } - ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size); - if (try_load_partition(&part, result)) { - return true; - } - log_invalid_app_partition(index); - } - - /* failing that work forwards from start_index, try valid OTA slots */ - for(index = start_index + 1; index < bs->app_count; index++) { - part = index_to_partition(bs, index); - if (part.size == 0) { - continue; - } - ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size); - if (try_load_partition(&part, result)) { - return true; - } - log_invalid_app_partition(index); - } - - if (try_load_partition(&bs->test, result)) { - ESP_LOGW(TAG, "Falling back to test app as only bootable partition"); - return true; - } - - ESP_LOGE(TAG, "No bootable app partitions in the partition table"); - bzero(result, sizeof(esp_image_metadata_t)); - return false; -} - - -/** - * @function : bootloader_main - * @description: entry function of 2nd bootloader - * - * @inputs: void - */ - -void bootloader_main() -{ - vddsdio_configure(); - flash_gpio_configure(); - bootloader_clock_configure(); - uart_console_configure(); - wdt_reset_check(); - ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); -#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED) - esp_err_t err; -#endif - esp_image_header_t fhdr; - bootloader_state_t bs = { 0 }; - - ESP_LOGI(TAG, "compile time " __TIME__ ); - ets_set_appcpu_boot_addr(0); - - /* disable watch dog here */ - REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN ); - REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN ); - -#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH - const uint32_t spiconfig = ets_efuse_get_spiconfig(); - if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) { - ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig"); - return; - } -#endif - - esp_rom_spiflash_unlock(); - - ESP_LOGI(TAG, "Enabling RNG early entropy source..."); - bootloader_random_enable(); - -#if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT - bootloader_enable_qio_mode(); -#endif - - if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, - sizeof(esp_image_header_t), true) != ESP_OK) { - ESP_LOGE(TAG, "failed to load bootloader header!"); - return; - } - - print_flash_info(&fhdr); - - update_flash_config(&fhdr); - - if (!load_partition_table(&bs)) { - ESP_LOGE(TAG, "load partition table error!"); - return; - } - - int boot_index = get_selected_boot_partition(&bs); - if (boot_index == INVALID_INDEX) { - return; // Unrecoverable failure (not due to corrupt ota data or bad partition contents) - } - // Start from the default, look for the first bootable partition - esp_image_metadata_t image_data; - if (!load_boot_image(&bs, boot_index, &image_data)) { - return; - } - -#ifdef CONFIG_SECURE_BOOT_ENABLED - /* Generate secure digest from this bootloader to protect future - modifications */ - ESP_LOGI(TAG, "Checking secure boot..."); - err = esp_secure_boot_permanently_enable(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err); - /* Allow booting to continue, as the failure is probably - due to user-configured EFUSEs for testing... - */ - } -#endif - -#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED - /* encrypt flash */ - ESP_LOGI(TAG, "Checking flash encryption..."); - bool flash_encryption_enabled = esp_flash_encryption_enabled(); - err = esp_flash_encrypt_check_and_update(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Flash encryption check failed (%d).", err); - return; - } - - if (!flash_encryption_enabled && esp_flash_encryption_enabled()) { - /* Flash encryption was just enabled for the first time, - so issue a system reset to ensure flash encryption - cache resets properly */ - ESP_LOGI(TAG, "Resetting with flash encryption enabled..."); - REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST); - return; - } -#endif - - ESP_LOGI(TAG, "Disabling RNG early entropy source..."); - bootloader_random_disable(); - - // copy loaded segments to RAM, set up caches for mapped segments, and start application - unpack_load_app(&image_data); -} - -static void unpack_load_app(const esp_image_metadata_t* data) -{ - uint32_t drom_addr = 0; - uint32_t drom_load_addr = 0; - uint32_t drom_size = 0; - uint32_t irom_addr = 0; - uint32_t irom_load_addr = 0; - uint32_t irom_size = 0; - - // Find DROM & IROM addresses, to configure cache mappings - for (int i = 0; i < data->image.segment_count; i++) { - const esp_image_segment_header_t *header = &data->segments[i]; - if (header->load_addr >= SOC_IROM_LOW && header->load_addr < SOC_IROM_HIGH) { - if (drom_addr != 0) { - ESP_LOGE(TAG, MAP_ERR_MSG, "DROM"); - } else { - ESP_LOGD(TAG, "Mapping segment %d as %s", i, "DROM"); - } - drom_addr = data->segment_data[i]; - drom_load_addr = header->load_addr; - drom_size = header->data_len; - } - if (header->load_addr >= SOC_DROM_LOW && header->load_addr < SOC_DROM_HIGH) { - if (irom_addr != 0) { - ESP_LOGE(TAG, MAP_ERR_MSG, "IROM"); - } else { - ESP_LOGD(TAG, "Mapping segment %d as %s", i, "IROM"); - } - irom_addr = data->segment_data[i]; - irom_load_addr = header->load_addr; - irom_size = header->data_len; - } - } - - ESP_LOGD(TAG, "calling set_cache_and_start_app"); - set_cache_and_start_app(drom_addr, - drom_load_addr, - drom_size, - irom_addr, - irom_load_addr, - irom_size, - data->image.entry_addr); -} - -static void set_cache_and_start_app( - uint32_t drom_addr, - uint32_t drom_load_addr, - uint32_t drom_size, - uint32_t irom_addr, - uint32_t irom_load_addr, - uint32_t irom_size, - uint32_t entry_addr) -{ - ESP_LOGD(TAG, "configure drom and irom and start"); - Cache_Read_Disable( 0 ); - Cache_Flush( 0 ); - - /* Clear the MMU entries that are already set up, - so the new app only has the mappings it creates. - */ - for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) { - DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL; - } - - uint32_t drom_page_count = (drom_size + 64*1024 - 1) / (64*1024); // round up to 64k - ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d", drom_addr & 0xffff0000, drom_load_addr & 0xffff0000, drom_size, drom_page_count ); - int rc = cache_flash_mmu_set( 0, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count ); - ESP_LOGV(TAG, "rc=%d", rc ); - rc = cache_flash_mmu_set( 1, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count ); - ESP_LOGV(TAG, "rc=%d", rc ); - uint32_t irom_page_count = (irom_size + 64*1024 - 1) / (64*1024); // round up to 64k - ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d", irom_addr & 0xffff0000, irom_load_addr & 0xffff0000, irom_size, irom_page_count ); - rc = cache_flash_mmu_set( 0, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count ); - ESP_LOGV(TAG, "rc=%d", rc ); - rc = cache_flash_mmu_set( 1, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count ); - ESP_LOGV(TAG, "rc=%d", rc ); - DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG, (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | DPORT_PRO_CACHE_MASK_DRAM1 ); - DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG, (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | DPORT_APP_CACHE_MASK_DRAM1 ); - Cache_Read_Enable( 0 ); - - // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) - - ESP_LOGD(TAG, "start: 0x%08x", entry_addr); - typedef void (*entry_t)(void); - entry_t entry = ((entry_t) entry_addr); - - // TODO: we have used quite a bit of stack at this point. - // use "movsp" instruction to reset stack back to where ROM stack starts. - (*entry)(); -} - -static void update_flash_config(const esp_image_header_t* pfhdr) -{ - uint32_t size; - switch(pfhdr->spi_size) { - case ESP_IMAGE_FLASH_SIZE_1MB: - size = 1; - break; - case ESP_IMAGE_FLASH_SIZE_2MB: - size = 2; - break; - case ESP_IMAGE_FLASH_SIZE_4MB: - size = 4; - break; - case ESP_IMAGE_FLASH_SIZE_8MB: - size = 8; - break; - case ESP_IMAGE_FLASH_SIZE_16MB: - size = 16; - break; - default: - size = 2; - } - Cache_Read_Disable( 0 ); - // Set flash chip size - esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); - // TODO: set mode - // TODO: set frequency - Cache_Flush(0); - Cache_Read_Enable( 0 ); -} - -static void print_flash_info(const esp_image_header_t* phdr) -{ -#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE) - - ESP_LOGD(TAG, "magic %02x", phdr->magic ); - ESP_LOGD(TAG, "segments %02x", phdr->segment_count ); - ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode ); - ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed ); - ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size ); - - const char* str; - switch ( phdr->spi_speed ) { - case ESP_IMAGE_SPI_SPEED_40M: - str = "40MHz"; - break; - case ESP_IMAGE_SPI_SPEED_26M: - str = "26.7MHz"; - break; - case ESP_IMAGE_SPI_SPEED_20M: - str = "20MHz"; - break; - case ESP_IMAGE_SPI_SPEED_80M: - str = "80MHz"; - break; - default: - str = "20MHz"; - break; - } - ESP_LOGI(TAG, "SPI Speed : %s", str ); - - /* SPI mode could have been set to QIO during boot already, - so test the SPI registers not the flash header */ - uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0)); - if (spi_ctrl & SPI_FREAD_QIO) { - str = "QIO"; - } else if (spi_ctrl & SPI_FREAD_QUAD) { - str = "QOUT"; - } else if (spi_ctrl & SPI_FREAD_DIO) { - str = "DIO"; - } else if (spi_ctrl & SPI_FREAD_DUAL) { - str = "DOUT"; - } else if (spi_ctrl & SPI_FASTRD_MODE) { - str = "FAST READ"; - } else { - str = "SLOW READ"; - } - ESP_LOGI(TAG, "SPI Mode : %s", str ); - - switch ( phdr->spi_size ) { - case ESP_IMAGE_FLASH_SIZE_1MB: - str = "1MB"; - break; - case ESP_IMAGE_FLASH_SIZE_2MB: - str = "2MB"; - break; - case ESP_IMAGE_FLASH_SIZE_4MB: - str = "4MB"; - break; - case ESP_IMAGE_FLASH_SIZE_8MB: - str = "8MB"; - break; - case ESP_IMAGE_FLASH_SIZE_16MB: - str = "16MB"; - break; - default: - str = "2MB"; - break; - } - ESP_LOGI(TAG, "SPI Flash Size : %s", str ); -#endif -} - - -static void vddsdio_configure() -{ -#if CONFIG_BOOTLOADER_VDDSDIO_BOOST - rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); - if (cfg.enable == 1 && cfg.tieh == 0) { // VDDSDIO regulator is enabled @ 1.8V - cfg.drefh = 3; - cfg.drefm = 3; - cfg.drefl = 3; - cfg.force = 1; - rtc_vddsdio_set_config(cfg); - ets_delay_us(10); // wait for regulator to become stable - } -#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST -} - - -#define FLASH_CLK_IO 6 -#define FLASH_CS_IO 11 -#define FLASH_SPIQ_IO 7 -#define FLASH_SPID_IO 8 -#define FLASH_SPIWP_IO 10 -#define FLASH_SPIHD_IO 9 -#define FLASH_IO_MATRIX_DUMMY_40M 1 -#define FLASH_IO_MATRIX_DUMMY_80M 2 -static void IRAM_ATTR flash_gpio_configure() -{ - int spi_cache_dummy = 0; - int drv = 2; -#if CONFIG_FLASHMODE_QIO - spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3 -#elif CONFIG_FLASHMODE_QOUT - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7 -#elif CONFIG_FLASHMODE_DIO - spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3 -#elif CONFIG_FLASHMODE_DOUT - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7 -#endif - /* dummy_len_plus values defined in ROM for SPI flash configuration */ - extern uint8_t g_rom_spiflash_dummy_len_plus[]; -#if CONFIG_ESPTOOLPY_FLASHFREQ_40M - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY -#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY - drv = 3; -#endif - - uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); - uint32_t pkg_ver = chip_ver & 0x7; - - if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) { - // For ESP32D2WD the SPI pins are already configured - // flash clock signal should come from IO MUX. - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); - } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { - // For ESP32PICOD2 the SPI pins are already configured - // flash clock signal should come from IO MUX. - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); - } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { - // For ESP32PICOD4 the SPI pins are already configured - // flash clock signal should come from IO MUX. - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); - } else { - const uint32_t spiconfig = ets_efuse_get_spiconfig(); - if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) { - gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); - gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0); - gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0); - gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0); - gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0); - gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0); - //select pin function gpio - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO); - // flash clock signal should come from IO MUX. - // set drive ability for clock - PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); - SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); - } - } -} - - -static void uart_console_configure(void) -{ -#if CONFIG_CONSOLE_UART_NONE - ets_install_putc1(NULL); - ets_install_putc2(NULL); -#else // CONFIG_CONSOLE_UART_NONE - const int uart_num = CONFIG_CONSOLE_UART_NUM; - - uartAttach(); - ets_install_uart_printf(); - - // Wait for UART FIFO to be empty. - uart_tx_wait_idle(0); - -#if CONFIG_CONSOLE_UART_CUSTOM - // Some constants to make the following code less upper-case - const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO; - const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO; - // Switch to the new UART (this just changes UART number used for - // ets_printf in ROM code). - uart_tx_switch(uart_num); - // If console is attached to UART1 or if non-default pins are used, - // need to reconfigure pins using GPIO matrix - if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) { - // Change pin mode for GPIO1/3 from UART to GPIO - PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1); - // Route GPIO signals to/from pins - // (arrays should be optimized away by the compiler) - const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX }; - const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX }; - const uint32_t tx_idx = tx_idx_list[uart_num]; - const uint32_t rx_idx = rx_idx_list[uart_num]; - gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0); - gpio_matrix_in(uart_rx_gpio, rx_idx, 0); - } -#endif // CONFIG_CONSOLE_UART_CUSTOM - - // Set configured UART console baud rate - const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE; - uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud); - -#endif // CONFIG_CONSOLE_UART_NONE -} - -static void wdt_reset_cpu0_info_enable(void) -{ - //We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1. - DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE); - DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE); -} - -static void wdt_reset_info_dump(int cpu) -{ - uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0, - lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0; - char *cpu_name = cpu ? "APP" : "PRO"; - - if (cpu == 0) { - stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG); - pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG); - inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG); - dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG); - data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG); - pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG); - lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG); - lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG); - lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG); - - } else { - stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG); - pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG); - inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG); - dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG); - data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG); - pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG); - lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG); - lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG); - lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG); - } - if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 && - DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) { - ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc); - } else { - ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc); - } - ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat); - ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid); - ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst); - ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat); - ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data); - ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc); - ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat); - ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr); - ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata); -} - -static void wdt_reset_check(void) -{ - int wdt_rst = 0; - RESET_REASON rst_reas[2]; - - rst_reas[0] = rtc_get_reset_reason(0); - rst_reas[1] = rtc_get_reset_reason(1); - if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET || - rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) { - ESP_LOGW(TAG, "PRO CPU has been reset by WDT."); - wdt_rst = 1; - } - if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET || - rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) { - ESP_LOGW(TAG, "APP CPU has been reset by WDT."); - wdt_rst = 1; - } - if (wdt_rst) { - // if reset by WDT dump info from trace port - wdt_reset_info_dump(0); - wdt_reset_info_dump(1); - } - wdt_reset_cpu0_info_enable(); -} - -void __assert_func(const char *file, int line, const char *func, const char *expr) -{ - ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr); - while(1) {} -} diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/component.mk b/MicroPython_BUILD/components/bootloader/subproject/main/component.mk deleted file mode 100644 index a54fe30..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/component.mk +++ /dev/null @@ -1,21 +0,0 @@ -# -# Main bootloader Makefile. -# -# This is basically the same as a component makefile, but in the case of the bootloader -# we pull in bootloader-specific linker arguments. -# - -LINKER_SCRIPTS := \ - esp32.bootloader.ld \ - $(IDF_PATH)/components/esp32/ld/esp32.rom.ld \ - $(IDF_PATH)/components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld \ - $(IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \ - esp32.bootloader.rom.ld - -ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH -LINKER_SCRIPTS += $(IDF_PATH)/components/esp32/ld/esp32.rom.spiflash.ld -endif - -COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS)) - -COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS) diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/esp32.bootloader.ld b/MicroPython_BUILD/components/bootloader/subproject/main/esp32.bootloader.ld deleted file mode 100644 index 54fe1a9..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/esp32.bootloader.ld +++ /dev/null @@ -1,132 +0,0 @@ -/* -Linker file used to link the bootloader. -*/ - - -/* Simplified memory map for the bootloader - - The main purpose is to make sure the bootloader can load into main memory - without overwriting itself. -*/ -MEMORY -{ - /* I/O */ - dport0_seg (RW) : org = 0x3FF00000, len = 0x10 - /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, the main app enables APP CPU cache */ - iram_seg (RWX) : org = 0x40078000, len = 0x8000 - /* 64k at the end of DRAM, after ROM bootloader stack */ - dram_seg (RW) : org = 0x3FFF0000, len = 0x10000 -} - -/* Default entry point: */ -ENTRY(call_start_cpu0); - - -SECTIONS -{ - .iram1.text : - { - . = ALIGN (16); - *(.entry.text) - *(.init.literal) - *(.init) - } > iram_seg - - - /* Shared RAM */ - .dram0.bss (NOLOAD) : - { - . = ALIGN (8); - _bss_start = ABSOLUTE(.); - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.gnu.linkonce.sb.*) - *(.scommon) - *(.sbss2) - *(.sbss2.*) - *(.gnu.linkonce.sb2.*) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.gnu.linkonce.b.*) - *(COMMON) - . = ALIGN (8); - _bss_end = ABSOLUTE(.); - } >dram_seg - - .dram0.data : - { - _data_start = ABSOLUTE(.); - *(.data) - *(.data.*) - *(.gnu.linkonce.d.*) - *(.data1) - *(.sdata) - *(.sdata.*) - *(.gnu.linkonce.s.*) - *(.sdata2) - *(.sdata2.*) - *(.gnu.linkonce.s2.*) - *(.jcr) - _data_end = ABSOLUTE(.); - } >dram_seg - - .dram0.rodata : - { - _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) - *(.gnu.linkonce.r.*) - *(.rodata1) - __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); - *(.xt_except_table) - *(.gcc_except_table) - *(.gnu.linkonce.e.*) - *(.gnu.version_r) - *(.eh_frame) - . = (. + 3) & ~ 3; - /* C++ constructor and destructor tables, properly ordered: */ - __init_array_start = ABSOLUTE(.); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - /* C++ exception handlers table: */ - __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); - *(.xt_except_desc) - *(.gnu.linkonce.h.*) - __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); - *(.xt_except_desc_end) - *(.dynamic) - *(.gnu.version_d) - _rodata_end = ABSOLUTE(.); - /* Literals are also RO data. */ - _lit4_start = ABSOLUTE(.); - *(*.lit4) - *(.lit4.*) - *(.gnu.linkonce.lit4.*) - _lit4_end = ABSOLUTE(.); - . = ALIGN(4); - _heap_start = ABSOLUTE(.); - } >dram_seg - - .iram.text : - { - _stext = .; - _text_start = ABSOLUTE(.); - *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) - *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ - *(.fini.literal) - *(.fini) - *(.gnu.version) - _text_end = ABSOLUTE(.); - _etext = .; - } > iram_seg - -} diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/esp32.bootloader.rom.ld b/MicroPython_BUILD/components/bootloader/subproject/main/esp32.bootloader.rom.ld deleted file mode 100644 index 70f83bd..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/esp32.bootloader.rom.ld +++ /dev/null @@ -1 +0,0 @@ -PROVIDE ( ets_update_cpu_frequency = 0x40008550 ); /* Updates g_ticks_per_us on the current CPU only; not on the other core */ diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/flash_qio_mode.c b/MicroPython_BUILD/components/bootloader/subproject/main/flash_qio_mode.c deleted file mode 100644 index 79b145c..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/flash_qio_mode.c +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include "flash_qio_mode.h" -#include "esp_log.h" -#include "esp_err.h" -#include "rom/spi_flash.h" -#include "rom/efuse.h" -#include "soc/spi_struct.h" -#include "soc/efuse_reg.h" -#include "sdkconfig.h" - -/* SPI flash controller */ -#define SPIFLASH SPI1 - -/* SPI commands (actual on-wire commands not SPI controller bitmasks) - Suitable for use with the execute_flash_command static function. -*/ -#define CMD_RDID 0x9F -#define CMD_WRSR 0x01 -#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */ -#define CMD_WREN 0x06 -#define CMD_WRDI 0x04 -#define CMD_RDSR 0x05 -#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ - -static const char *TAG = "qio_mode"; - -typedef unsigned (*read_status_fn_t)(); -typedef void (*write_status_fn_t)(unsigned); - -typedef struct __attribute__((packed)) { - const char *manufacturer; - uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */ - uint16_t flash_id; /* 16-bit JEDEC flash chip ID */ - uint16_t id_mask; /* Bits to match on in flash chip ID */ - read_status_fn_t read_status_fn; - write_status_fn_t write_status_fn; - uint8_t status_qio_bit; -} qio_info_t; - -/* Read 8 bit status using RDSR command */ -static unsigned read_status_8b_rdsr(); -/* Read 8 bit status (second byte) using RDSR2 command */ -static unsigned read_status_8b_rdsr2(); -/* read 16 bit status using RDSR & RDSR2 (low and high bytes) */ -static unsigned read_status_16b_rdsr_rdsr2(); - -/* Write 8 bit status using WRSR */ -static void write_status_8b_wrsr(unsigned new_status); -/* Write 8 bit status (second byte) using WRSR2 */ -static void write_status_8b_wrsr2(unsigned new_status); -/* Write 16 bit status using WRSR */ -static void write_status_16b_wrsr(unsigned new_status); - -#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */ - -#ifndef CONFIG_BOOTLOADER_SPI_WP_PIN // Set in menuconfig if SPI flasher config is set to a quad mode -#define CONFIG_BOOTLOADER_SPI_WP_PIN ESP32_D2WD_WP_GPIO -#endif - -/* Array of known flash chips and data to enable Quad I/O mode - - Manufacturer & flash ID can be tested by running "esptool.py - flash_id" - - If manufacturer ID matches, and flash ID ORed with flash ID mask - matches, enable_qio_mode() will execute "Read Cmd", test if bit - number "QIE Bit" is set, and if not set it will call "Write Cmd" - with this bit set. - - Searching of this table stops when the first match is found. - */ -const static qio_info_t chip_data[] = { -/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */ - { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, - { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */ - { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, - { "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 }, - - /* Final entry is default entry, if no other IDs have matched. - - This approach works for chips including: - GigaDevice (mfg ID 0xC8, flash IDs including 4016), - FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016) - */ - { NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 }, -}; - -#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t)) - -static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, - write_status_fn_t write_status_fn, - uint8_t status_qio_bit); - -/* Generic function to use the "user command" SPI controller functionality - to send commands to the SPI flash and read the respopnse. - - The command passed here is always the on-the-wire command given to the SPI flash unit. -*/ -static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len); - -/* dummy_len_plus values defined in ROM for SPI flash configuration */ -extern uint8_t g_rom_spiflash_dummy_len_plus[]; - -void bootloader_enable_qio_mode(void) -{ - uint32_t old_ctrl_reg; - uint32_t raw_flash_id; - uint8_t mfg_id; - uint16_t flash_id; - int i; - - ESP_LOGD(TAG, "Probing for QIO mode enable..."); - esp_rom_spiflash_wait_idle(&g_rom_flashchip); - - /* Set up some of the SPIFLASH user/ctrl variables which don't change - while we're probing using execute_flash_command() */ - old_ctrl_reg = SPIFLASH.ctrl.val; - SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 0; - SPIFLASH.user.usr_command = 1; - SPIFLASH.user2.usr_command_bitlen = 7; - - raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24); - ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id); - - mfg_id = raw_flash_id & 0xFF; - flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00); - ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id); - - for (i = 0; i < NUM_CHIPS-1; i++) { - const qio_info_t *chip = &chip_data[i]; - if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) { - ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer); - break; - } - } - - if (i == NUM_CHIPS - 1) { - ESP_LOGI(TAG, "Enabling default flash chip QIO"); - } - - esp_err_t res = enable_qio_mode(chip_data[i].read_status_fn, - chip_data[i].write_status_fn, - chip_data[i].status_qio_bit); - if (res != ESP_OK) { - // Restore SPI flash CTRL setting, to keep us in DIO/DOUT mode - SPIFLASH.ctrl.val = old_ctrl_reg; - } -} - -static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, - write_status_fn_t write_status_fn, - uint8_t status_qio_bit) -{ - uint32_t status; - const uint32_t spiconfig = ets_efuse_get_spiconfig(); - - if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) { - // spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP, - // which is compiled into the bootloader instead. - // - // Most commonly an overriden pin mapping means ESP32-D2WD. Warn if chip is ESP32-D2WD - // but someone has changed the WP pin assignment from that chip's WP pin. - uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_RESERVE); - uint32_t pkg_ver = chip_ver & 0x7; - const int PKG_VER_ESP32_D2WD = 2; // TODO: use chip detection API once available - if (pkg_ver == PKG_VER_ESP32_D2WD && CONFIG_BOOTLOADER_SPI_WP_PIN != ESP32_D2WD_WP_GPIO) { - ESP_LOGW(TAG, "Chip is ESP32-D2WD but flash WP pin is different value to internal flash"); - } - } - - esp_rom_spiflash_wait_idle(&g_rom_flashchip); - - status = read_status_fn(); - ESP_LOGD(TAG, "Initial flash chip status 0x%x", status); - - if ((status & (1< 0; - SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0; - SPIFLASH.user.usr_mosi = mosi_len > 0; - SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0; - SPIFLASH.data_buf[0] = mosi_data; - - if (g_rom_spiflash_dummy_len_plus[1]) { - /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */ - if (miso_len > 0) { - SPIFLASH.user.usr_dummy = 1; - SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1; - } else { - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user1.usr_dummy_cyclelen = 0; - } - } - - SPIFLASH.cmd.usr = 1; - while(SPIFLASH.cmd.usr != 0) - { } - - return SPIFLASH.data_buf[0]; -} diff --git a/MicroPython_BUILD/components/bootloader/subproject/main/flash_qio_mode.h b/MicroPython_BUILD/components/bootloader/subproject/main/flash_qio_mode.h deleted file mode 100644 index 9efa131..0000000 --- a/MicroPython_BUILD/components/bootloader/subproject/main/flash_qio_mode.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief Enable Quad I/O mode in bootloader (if configured) - * - * Queries attached SPI flash ID and sends correct SPI flash - * commands to enable QIO or QOUT mode, then enables this mode. - */ -void bootloader_enable_qio_mode(void); - -#ifdef __cplusplus -} -#endif diff --git a/MicroPython_BUILD/components/micropython/Kconfig.projbuild b/MicroPython_BUILD/components/micropython/Kconfig.projbuild index ec252c2..bad4953 100644 --- a/MicroPython_BUILD/components/micropython/Kconfig.projbuild +++ b/MicroPython_BUILD/components/micropython/Kconfig.projbuild @@ -222,7 +222,7 @@ menu "MicroPython" Display module includes support for various SPI TFT displays config MICROPY_USE_EVE - bool "Use EVE display module" + bool "Use EVE display module (experimental, do not enable)" default n help Include EVE display module into build @@ -241,6 +241,15 @@ menu "MicroPython" 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 diff --git a/MicroPython_BUILD/components/micropython/component.mk b/MicroPython_BUILD/components/micropython/component.mk index 287a2a1..4f44f29 100644 --- a/MicroPython_BUILD/components/micropython/component.mk +++ b/MicroPython_BUILD/components/micropython/component.mk @@ -107,6 +107,11 @@ ifdef CONFIG_MICROPY_USE_MAIL MP_EXTRA_INC += -I$(PROJECT_PATH)/components/quickmail endif +ifdef CONFIG_MICROPY_USE_BLUETOOTH +MP_EXTRA_INC += -I$(ESPCOMP)/bt/include +MP_EXTRA_INC += -I$(ESPCOMP)/bt/bluedroid/api/include +endif + # CPP macro # ------------ CPP = $(CC) -E @@ -202,6 +207,11 @@ ifdef CONFIG_MICROPY_USE_ETHERNET SRC_C += esp32/network_lan.c endif +ifdef CONFIG_MICROPY_USE_BLUETOOTH +SRC_C += esp32/bluetooth_le.c +SRC_C += esp32/modbluetooth.c +endif + EXTMOD_SRC_C = $(addprefix extmod/,\ modbtree.c \ ) diff --git a/MicroPython_BUILD/components/micropython/esp32/bluetooth_le.c b/MicroPython_BUILD/components/micropython/esp32/bluetooth_le.c new file mode 100644 index 0000000..87d7a6c --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/bluetooth_le.c @@ -0,0 +1,1204 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * 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. + */ + + +// Free RTOS +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +// Generic +#include +#include + +// MicroPython +#include "py/runtime.h" +#include "py/obj.h" +#include "py/objstr.h" +#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" + +//extern bool bluetooth_enabled; + +static bool bluetooth_enabled = false; + +#define EVENT_DEBUG + +#ifdef EVENT_DEBUG +# define EVENT_DEBUG_GATTC +# define EVENT_DEBUG_GATTS +# define EVENT_DEBUG_GAP +#endif +#define MSEC_0_625_TO_UNIT(time) ((time) * 1000 / (625)) + +#define MALLOC(x) pvPortMalloc(x) +#define FREE(x) vPortFree(x) +#define UUID_LEN 16 +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define BAD_UUID(name) mp_raise_ValueError(name "must be bytearray(" TOSTRING(UUID_LEN) ")"); +#define BAD_PEER(name) mp_raise_ValueError(name "must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); +#define MP_OBJ_IS_BYTEARRAY_OR_BYTES(O) (MP_OBJ_IS_TYPE(O, &mp_type_bytes) || MP_OBJ_IS_TYPE(O, &mp_type_bytearray)) +#define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) + +#define CALLBACK_QUEUE_SIZE 10 + +typedef enum { + + // GATTS + BTLE_GATTS_CONNECT, + BTLE_GATTS_DISCONNECT, + + BTLE_GATTS_CREATE, + BTLE_GATTS_START, + BTLE_GATTS_STOP, + BTLE_GATTS_ADD_CHAR, // Add char + BTLE_GATTS_ADD_CHAR_DESCR, // Add descriptor + + // GAP / GATTC events + BTLE_GATTC_SCAN_RES, + BTLE_GATTC_SCAN_CMPL, // Found GATT servers + BTLE_GATTC_SEARCH_RES, // Found GATTS services + + BTLE_GATTC_GET_CHAR, + BTLE_GATTC_GET_DESCR, + + BTLE_GATTC_OPEN, + BTLE_GATTC_CLOSE, + + // characteristic events + BTLE_READ, + BTLE_WRITE, + BTLE_NOTIFY, + +} btle_event_t; + +typedef struct { + btle_event_t event; + union { + + struct { + uint16_t handle; + esp_gatt_srvc_id_t service_id; + } gatts_create; + /* + + struct { + uint16_t service_handle; + } gatts_start_stop; + + struct { + uint16_t service_handle; + uint16_t handle; + esp_bt_uuid_t uuid; + } gatts_add_char_descr; + + struct { + uint16_t conn_id; + esp_bd_addr_t bda; + } gatts_connect_disconnect; + + struct { + esp_bd_addr_t bda; + uint8_t* adv_data; // Need to free this! + uint8_t adv_data_len; + int rssi; + } gattc_scan_res; + + struct { + uint16_t conn_id; + esp_gatt_id_t service_id; + } gattc_search_res; + + struct { + uint16_t conn_id; + esp_gatt_srvc_id_t service_id; + esp_gatt_id_t char_id; + esp_gatt_char_prop_t props; + } gattc_get_char; + + struct { + uint16_t conn_id; + esp_gatt_srvc_id_t service_id; + esp_gatt_id_t char_id; + esp_gatt_id_t descr_id; + } gattc_get_descr; + + struct { + uint16_t conn_id; + uint16_t mtu; + esp_bd_addr_t bda; + + } gattc_open_close; + + struct { + uint16_t conn_id; + uint16_t handle; + uint32_t trans_id; + bool need_rsp; + } read; + + struct { + uint16_t conn_id; + uint16_t handle; + uint32_t trans_id; + bool need_rsp; + + // Following fields _must_ + // come after the first four above, + // which _must_ match the read struct + + uint8_t* value; // Need to free this! + size_t value_len; + } write; + + struct { + uint16_t conn_id; + esp_bd_addr_t remote_bda; + uint16_t handle; + + bool need_rsp; + + uint8_t* value; // Need to free this! + size_t value_len; + } notify; + */ + }; + +} callback_data_t; + +typedef struct { + uint8_t* value; // Need to free this! + size_t value_len; +} read_write_data_t; + +const mp_obj_type_t btle_type; + +STATIC SemaphoreHandle_t item_mut; +STATIC QueueHandle_t callback_q = NULL; +STATIC QueueHandle_t read_write_q = NULL; + +STATIC void dumpBuf(const uint8_t *buf, size_t len) { + while (len--) { + printf("%02X ", *buf++); + } +} + +typedef struct { + mp_obj_base_t base; + enum { + BTLE_STATE_DEINIT, + BTLE_STATE_INIT + } state; + bool advertising; + bool scanning; + bool gatts_connected; + + uint16_t conn_id; + esp_gatt_if_t gatts_interface; + esp_gatt_if_t gattc_interface; + + esp_ble_adv_params_t adv_params; + esp_ble_adv_data_t adv_data; + + mp_obj_t services; // GATTS, implemented as a list + + mp_obj_t connections; // GATTC, implemented as a list + + mp_obj_t callback; + mp_obj_t callback_userdata; +} btle_obj_t; + +// Singleton +STATIC btle_obj_t* btle_singleton = NULL; + +STATIC btle_obj_t* btle_get_singleton() { + + if (btle_singleton == NULL) { + btle_singleton = m_new_obj(btle_obj_t); + + btle_singleton->base.type = &btle_type; + + btle_singleton->state = BTLE_STATE_DEINIT; + btle_singleton->advertising = false; + btle_singleton->scanning = false; + btle_singleton->gatts_connected = false; + btle_singleton->conn_id = 0; + btle_singleton->gatts_interface = ESP_GATT_IF_NONE; + btle_singleton->gattc_interface = ESP_GATT_IF_NONE; + btle_singleton->adv_params.adv_int_min = 1280 * 1.6; + btle_singleton->adv_params.adv_int_max = 1280 * 1.6; + btle_singleton->adv_params.adv_type = ADV_TYPE_IND; + btle_singleton->adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC; + btle_singleton->adv_params.peer_addr_type = BLE_ADDR_TYPE_PUBLIC; + btle_singleton->adv_params.channel_map = ADV_CHNL_ALL; + btle_singleton->adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY; + btle_singleton->adv_data.set_scan_rsp = false; + btle_singleton->adv_data.include_name = false; + btle_singleton->adv_data.include_txpower = false; + btle_singleton->adv_data.min_interval = 1280 * 1.6; + btle_singleton->adv_data.max_interval = 1280 * 1.6; + btle_singleton->adv_data.appearance = 0; + btle_singleton->adv_data.p_manufacturer_data = NULL; + btle_singleton->adv_data.manufacturer_len = 0; + btle_singleton->adv_data.p_service_data = NULL; + btle_singleton->adv_data.service_data_len = 0; + btle_singleton->adv_data.p_service_uuid = 0; + btle_singleton->adv_data.service_uuid_len = 0; + btle_singleton->adv_data.flag = 0; + + btle_singleton->callback = mp_const_none; + btle_singleton->callback_userdata = mp_const_none; + + btle_singleton->services = mp_obj_new_list(0, NULL); + btle_singleton->connections = mp_obj_new_list(0, NULL); + memset(btle_singleton->adv_params.peer_addr, 0, sizeof(btle_singleton->adv_params.peer_addr)); + } + return btle_singleton; +} + +#if CONFIG_GATTS_ENABLE +STATIC void btle_gatts_event_handler( + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) { + + btle_obj_t* bluetooth = btle_get_singleton(); + if (bluetooth->state != BTLE_STATE_INIT) { + return; + } + +#ifdef EVENT_DEBUG_GATTS + //gatts_event_dump(event, gatts_if, param); +#endif +} +#endif + +#if CONFIG_GATTC_ENABLE +STATIC void btle_gattc_event_handler( + esp_gattc_cb_event_t event, + esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) { + + btle_obj_t* bluetooth = btle_get_singleton(); + if (bluetooth->state != BTLE_STATE_INIT) { + return; + } +#ifdef EVENT_DEBUG_GATTC + //gattc_event_dump(event, gattc_if, param); +#endif +} +#endif + + +#ifdef EVENT_DEBUG_GAP + +typedef struct { + uint8_t id; + const char * name; +} gatt_status_name_t; + +STATIC const gatt_status_name_t gatt_status_names[] = { + {0x00, "OK"}, + {0x01, "INVALID_HANDLE"}, + {0x02, "READ_NOT_PERMIT"}, + {0x03, "WRITE_NOT_PERMIT"}, + {0x04, "INVALID_PDU"}, + {0x05, "INSUF_AUTHENTICATION"}, + {0x06, "REQ_NOT_SUPPORTED"}, + {0x07, "INVALID_OFFSET"}, + {0x08, "INSUF_AUTHORIZATION"}, + {0x09, "PREPARE_Q_FULL"}, + {0x0a, "NOT_FOUND"}, + {0x0b, "NOT_LONG"}, + {0x0c, "INSUF_KEY_SIZE"}, + {0x0d, "INVALID_ATTR_LEN"}, + {0x0e, "ERR_UNLIKELY"}, + {0x0f, "INSUF_ENCRYPTION"}, + {0x10, "UNSUPPORT_GRP_TYPE"}, + {0x11, "INSUF_RESOURCE"}, + {0x80, "NO_RESOURCES"}, + {0x81, "INTERNAL_ERROR"}, + {0x82, "WRONG_STATE"}, + {0x83, "DB_FULL"}, + {0x84, "BUSY"}, + {0x85, "ERROR"}, + {0x86, "CMD_STARTED"}, + {0x87, "ILLEGAL_PARAMETER"}, + {0x88, "PENDING"}, + {0x89, "AUTH_FAIL"}, + {0x8a, "MORE"}, + {0x8b, "INVALID_CFG"}, + {0x8c, "SERVICE_STARTED"}, + {0x8d, "ENCRYPED_NO_MITM"}, + {0x8e, "NOT_ENCRYPTED"}, + {0x8f, "CONGESTED"}, + {0x90, "DUP_REG"}, + {0x91, "ALREADY_OPEN"}, + {0x92, "CANCEL"}, + {0xfd, "CCC_CFG_ERR"}, + {0xfe, "PRC_IN_PROGRESS"}, + {0xff, "OUT_OF_RANGE"}, + {0x00, NULL}, +}; + +#define PRINT_STATUS(STATUS) { \ + bool found = false; \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("status = %02X / ", (STATUS)); \ + for(int i = 0; gatt_status_names[i].name != NULL; i++) { \ + if (gatt_status_names[i].id == (STATUS)) { \ + found = true; \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("%s", gatt_status_names[i].name); \ + break; \ + } \ + } \ + if (!found) { \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("???"); \ + } \ +} +STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { + const char * event_names[] = { + "ADV_DATA_SET_COMPLETE", + "SCAN_RSP_DATA_SET_COMPLETE", + "SCAN_PARAM_SET_COMPLETE", + "SCAN_RESULT", + "ADV_DATA_RAW_SET_COMPLETE", + "SCAN_RSP_DATA_RAW_SET_COMPLETE", + "ADV_START_COMPLETE", + "SCAN_START_COMPLETE", + "AUTH_CMPL", + "KEY", + "SEC_REQ", + "PASSKEY_NOTIF", + "PASSKEY_REQ", + "OOB_REQ", + "LOCAL_IR", + "LOCAL_ER", + "NC_REQ", + "ADV_STOP_COMPLETE", + "SCAN_STOP_COMPLETE", + "SET_STATIC_RAND_ADDR_EVT", + "UPDATE_CONN_PARAMS_EVT", + "SET_PKT_LENGTH_COMPLETE_EVT" + }; + + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_gap_event_handler(event = %02X / %s", event, event_names[event]); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", param = ("); + switch (event) { + case ESP_GAP_BLE_EVT_MAX: + break; + + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT: + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + case ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT: + case ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT: + { + PRINT_STATUS(param->adv_data_cmpl.status); + } + break; + + + 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", + param->read_rssi_cmpl.rssi, + param->read_rssi_cmpl.remote_addr[0], + param->read_rssi_cmpl.remote_addr[1], + param->read_rssi_cmpl.remote_addr[2], + param->read_rssi_cmpl.remote_addr[3], + param->read_rssi_cmpl.remote_addr[4], + param->read_rssi_cmpl.remote_addr[5]); + } + break; + + case ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT: + { + PRINT_STATUS(param->adv_data_cmpl.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", wl_opration = %s", + param->update_whitelist_cmpl.wl_opration == ESP_BLE_WHITELIST_ADD + ? "ADD" : "REMOVE"); + } + break; + + case ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT: + { + PRINT_STATUS(param->adv_data_cmpl.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", dev_num = %d, bond_dev = ", + param->get_bond_dev_cmpl.dev_num); + } + break; + case ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT: + { + PRINT_STATUS(param->adv_data_cmpl.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", bda = %02X:%02X:%02X:%02X:%02X:%02X", + param->remove_bond_dev_cmpl.bd_addr[0], + param->remove_bond_dev_cmpl.bd_addr[1], + param->remove_bond_dev_cmpl.bd_addr[2], + param->remove_bond_dev_cmpl.bd_addr[3], + param->remove_bond_dev_cmpl.bd_addr[4], + param->remove_bond_dev_cmpl.bd_addr[5]); + } + break; + + case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT: + { + PRINT_STATUS(param->pkt_data_lenth_cmpl.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", rx_len = %04X" + ", tx_len = %04X", + param->pkt_data_lenth_cmpl.params.rx_len, + param->pkt_data_lenth_cmpl.params.tx_len + ); + + } + break; + + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + { + PRINT_STATUS(param->update_conn_params.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", min_int = %04X" + ", max_int = %04X" + ", latency = %04X" + ", conn_int = %04X" + ", timeout = %04X", + param->update_conn_params.bda[0], + param->update_conn_params.bda[1], + param->update_conn_params.bda[2], + param->update_conn_params.bda[3], + param->update_conn_params.bda[4], + param->update_conn_params.bda[5], + param->update_conn_params.min_int, + param->update_conn_params.max_int, + param->update_conn_params.latency, + param->update_conn_params.conn_int, + param->update_conn_params.timeout + ); + } + break; + + case ESP_GAP_BLE_SCAN_RESULT_EVT: + { + const char * search_events[7] = { + "INQ_RES", + "INQ_CMPL", + "DISC_RES", + "DISC_BLE_RES", + "DISC_CMPL", + "DI_DISC_CMPL", + "SEARCH_CANCEL_CMPL" + }; + + const char * dev_types[] = { "", "BREDR", "BLE", "DUMO" }; + const char * addr_types[] = { "PUBLIC", "RANDOM", "RPA_PUBLIC", "RPA_RANDOM" }; + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "search_evt = %s", + search_events[param->scan_rst.search_evt]); + + if (param->scan_rst.dev_type <= 3 && param->scan_rst.ble_addr_type <= 3) { + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", dev_type = %s" + ", ble_addr_type = %s" + ", rssi = %d" , + dev_types[param->scan_rst.dev_type], + addr_types[param->scan_rst.ble_addr_type], + param->scan_rst.rssi + + ); + } + + if (param->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", adv_data_len = %u" + ", scan_rsp_len = %u" , + param->scan_rst.bda[0], + param->scan_rst.bda[1], + param->scan_rst.bda[2], + param->scan_rst.bda[3], + param->scan_rst.bda[4], + param->scan_rst.bda[5], + param->scan_rst.adv_data_len, + param->scan_rst.scan_rsp_len); + + uint8_t * adv_name; + uint8_t adv_name_len = 0; + adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, + ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", adv_name = "); + for (int j = 0; j < adv_name_len; j++) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("%c", adv_name[j]); + } + NETWORK_BLUETOOTH_DEBUG_PRINTF("(%d bytes)", adv_name_len); + } + } + break; + + case ESP_GAP_BLE_AUTH_CMPL_EVT: + break; + case ESP_GAP_BLE_KEY_EVT: + break; + case ESP_GAP_BLE_SEC_REQ_EVT: + break; + case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: + break; + case ESP_GAP_BLE_PASSKEY_REQ_EVT: + break; + case ESP_GAP_BLE_OOB_REQ_EVT: + break; + case ESP_GAP_BLE_LOCAL_IR_EVT: + break; + case ESP_GAP_BLE_LOCAL_ER_EVT: + break; + case ESP_GAP_BLE_NC_REQ_EVT: + break; + } + + NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); + +} +#endif // EVENT_DEBUG + +//-------------------------------- +STATIC void btle_gap_event_handler +( + esp_gap_ble_cb_event_t event, + esp_ble_gap_cb_param_t *param) { + +#ifdef EVENT_DEBUG_GAP + gap_event_dump(event, param); +#endif + + btle_obj_t* bluetooth = btle_get_singleton(); + if (bluetooth->state != BTLE_STATE_INIT) { + return; + } + +} + +//--------------------------------------------------------------------------------------- +STATIC void btle_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + btle_obj_t *self = MP_OBJ_TO_PTR(self_in); + //#define BTLE_LF "\n" +#define BTLE_LF + mp_printf(print, + "Bluetooth(params=(conn_id=%04X" BTLE_LF + ", gatts_connected=%s" BTLE_LF + ", gatts_if=%u" BTLE_LF + ", gattc_if=%u" BTLE_LF + ", adv_params=(" + "adv_int_min=%u, " BTLE_LF + "adv_int_max=%u, " BTLE_LF + "adv_type=%u, " BTLE_LF + "own_addr_type=%u, " BTLE_LF + "peer_addr=%02X:%02X:%02X:%02X:%02X:%02X, " BTLE_LF + "peer_addr_type=%u, " BTLE_LF + "channel_map=%u, " BTLE_LF + "adv_filter_policy=%u" BTLE_LF + "state=%d" BTLE_LF + ")" + , + self->conn_id, + self->gatts_connected ? "True" : "False", + self->gatts_interface, + self->gattc_interface, + (unsigned int)(self->adv_params.adv_int_min / 1.6), + (unsigned int)(self->adv_params.adv_int_max / 1.6), + self->adv_params.adv_type, + self->adv_params.own_addr_type, + self->adv_params.peer_addr[0], + self->adv_params.peer_addr[1], + self->adv_params.peer_addr[2], + self->adv_params.peer_addr[3], + self->adv_params.peer_addr[4], + self->adv_params.peer_addr[5], + self->adv_params.peer_addr_type, + self->adv_params.channel_map, + self->adv_params.adv_filter_policy, + self->state + ); + mp_printf(print, + ", data=(" + "set_scan_rsp=%s, " BTLE_LF + "include_name=%s, " BTLE_LF + "include_txpower=%s, " BTLE_LF + "min_interval=%d, " BTLE_LF + "max_interval=%d, " BTLE_LF + "appearance=%d, " BTLE_LF + "manufacturer_len=%d, " BTLE_LF + "p_manufacturer_data=%s, " BTLE_LF + "service_data_len=%d, " BTLE_LF + "p_service_data=", + self->adv_data.set_scan_rsp ? "True" : "False", + self->adv_data.include_name ? "True" : "False", + self->adv_data.include_txpower ? "True" : "False", + self->adv_data.min_interval, + self->adv_data.max_interval, + self->adv_data.appearance, + self->adv_data.manufacturer_len, + self->adv_data.p_manufacturer_data ? (const char *)self->adv_data.p_manufacturer_data : "nil", + self->adv_data.service_data_len); + if (self->adv_data.p_service_data != NULL) { + dumpBuf(self->adv_data.p_service_data, self->adv_data.service_data_len); + } + mp_printf(print, ", " BTLE_LF "flag=%d" BTLE_LF , self->adv_data.flag); + mp_printf(print, ")"); +} + +// bluetooth.init(...) + +//----------------------------------------- +STATIC mp_obj_t btle_init(mp_obj_t self_in) +{ + btle_obj_t * self = (btle_obj_t*)self_in; + + if (bluetooth_enabled) return mp_const_none; + + if (item_mut == NULL) { + item_mut = xSemaphoreCreateMutex(); + xSemaphoreGive(item_mut); + } + + if (callback_q == NULL) { + callback_q = xQueueCreate(CALLBACK_QUEUE_SIZE, sizeof(callback_data_t)); + if (callback_q == NULL) { + mp_raise_msg(&mp_type_OSError, "unable to create callback queue"); + } + } else { + xQueueReset(callback_q); + } + + if (read_write_q == NULL) { + read_write_q = xQueueCreate(1, sizeof(read_write_data_t)); + if (read_write_q == NULL) { + mp_raise_msg(&mp_type_OSError, "unable to create read queue"); + } + } else { + xQueueReset(read_write_q); + } + + if (self->state == BTLE_STATE_DEINIT) { + + self->state = BTLE_STATE_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, "esp_bt_controller_init() failed"); + } + + // Enable Bluetooth dual mode + if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); + } + + if (esp_bluedroid_init() != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_init() failed"); + } + + if (esp_bluedroid_enable() != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed"); + } + + + #if CONFIG_GATTS_ENABLE + if (esp_ble_gatts_register_callback(btle_gatts_event_handler) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_register_callback() failed"); + } + #endif + + #if CONFIG_GATTC_ENABLE + if (esp_ble_gattc_register_callback(btle_gattc_event_handler) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_register_callback() failed"); + } + #endif + + if (esp_ble_gap_register_callback(btle_gap_event_handler) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gap_register_callback() failed"); + } + + #if CONFIG_GATTS_ENABLE + if (esp_ble_gatts_app_register(0) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() failed"); + } + #endif + + #if CONFIG_GATTC_ENABLE + if (esp_ble_gattc_app_register(1) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_register() failed"); + } + #endif + + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(btle_init_obj, btle_init); + +STATIC mp_obj_t btle_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + printf("enter btle_make_new\n"); + btle_obj_t *self = btle_get_singleton(); + if (n_args != 0 || n_kw != 0) { + mp_raise_TypeError("Constructor takes no arguments"); + } + + btle_init(self); + return MP_OBJ_FROM_PTR(self); +} + +STATIC void btle_adv_updated() { + btle_obj_t* self = btle_get_singleton(); + esp_ble_gap_stop_advertising(); + esp_ble_gap_config_adv_data(&self->adv_data); + + // Restart will be handled in btle_gap_event_handler +} + +STATIC mp_obj_t btle_adv_params(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + btle_obj_t *bluetooth = btle_get_singleton(); + + if (bluetooth->state != BTLE_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } + + bool changed = false; + + enum { + // params + ARG_int_min, + ARG_int_max, + ARG_type, + ARG_own_addr_type, + ARG_peer_addr, + ARG_peer_addr_type, + ARG_channel_map, + ARG_filter_policy + }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_adv_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_own_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_peer_addr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_peer_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_filter_policy, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(0, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t peer_addr_buf = { 0 }; + + // pre-check complex types + + // peer_addr + if (args[ARG_peer_addr].u_obj != NULL) { + if (!MP_OBJ_IS_TYPE(args[ARG_peer_addr].u_obj, &mp_type_bytearray)) { + BAD_PEER("peer addr "); + } + + mp_get_buffer(args[ARG_peer_addr].u_obj, &peer_addr_buf, MP_BUFFER_READ); + if (peer_addr_buf.len != ESP_BD_ADDR_LEN) { + BAD_PEER("peer addr "); + } + } + + + // update esp_ble_adv_params_t + + if (args[ARG_int_min].u_int != -1) { + bluetooth->adv_params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count + changed = true; + } + + if (args[ARG_int_max].u_int != -1) { + bluetooth->adv_params.adv_int_max = args[ARG_int_max].u_int * 1.6; + changed = true; + } + + if (args[ARG_type].u_int != -1) { + bluetooth->adv_params.adv_type = args[ARG_type].u_int; + changed = true; + } + + if (args[ARG_own_addr_type].u_int != -1) { + bluetooth->adv_params.own_addr_type = args[ARG_own_addr_type].u_int; + changed = true; + } + + if (peer_addr_buf.buf != NULL) { + memcpy(bluetooth->adv_params.peer_addr, peer_addr_buf.buf, ESP_BD_ADDR_LEN); + changed = true; + } + + if (args[ARG_peer_addr_type].u_int != -1) { + bluetooth->adv_params.peer_addr_type = args[ARG_peer_addr_type].u_int; + changed = true; + } + + if (args[ARG_channel_map].u_int != -1) { + bluetooth->adv_params.channel_map = args[ARG_channel_map].u_int; + changed = true; + } + + if (args[ARG_filter_policy].u_int != -1) { + bluetooth->adv_params.adv_filter_policy = args[ARG_filter_policy].u_int; + changed = true; + } + + if (changed) { + btle_adv_updated(); + } + + return mp_const_none; + + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(btle_adv_params_obj, 1, btle_adv_params); + +STATIC mp_obj_t btle_adv_data(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + btle_obj_t *bluetooth = btle_get_singleton(); + + if (bluetooth->state != BTLE_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } + + bool changed = false; + bool unset_man_name = false; + bool unset_dev_name = false; + bool unset_uuid = false; + + enum { + // data + ARG_is_scan_rsp, + ARG_dev_name, + ARG_man_name, + ARG_inc_txpower, + ARG_int_min, + ARG_int_max, + ARG_appearance, + ARG_uuid, + ARG_flags + }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_is_scan_rsp, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = NULL}}, + { MP_QSTR_dev_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_man_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_inc_tx_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = NULL }}, + { MP_QSTR_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_appearance, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_uuid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NULL }}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(0, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t man_name_buf = { 0 }; + mp_buffer_info_t dev_name_buf = { 0 }; + mp_buffer_info_t uuid_buf = { 0 }; + + // pre-check complex types + + // man_name + if (args[ARG_man_name].u_obj != NULL) { + if (mp_obj_get_type(args[ARG_man_name].u_obj) == mp_const_none) { + unset_man_name = true; + } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_man_name].u_obj)) { + mp_raise_ValueError("man_name must be type str or bytes"); + } + mp_obj_str_get_buffer(args[ARG_man_name].u_obj, &man_name_buf, MP_BUFFER_READ); + } + + // dev_name + if (args[ARG_dev_name].u_obj != NULL) { + if (mp_obj_get_type(args[ARG_dev_name].u_obj) == mp_const_none) { + unset_dev_name = true; + } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_dev_name].u_obj)) { + mp_raise_ValueError("dev_name must be type str or bytes"); + } + mp_obj_str_get_buffer(args[ARG_dev_name].u_obj, &dev_name_buf, MP_BUFFER_READ); + } + + // uuid + if (args[ARG_uuid].u_obj != NULL) { + if (mp_obj_get_type(args[ARG_uuid].u_obj) == mp_const_none) { + unset_uuid = true; + } else if (!MP_OBJ_IS_TYPE(mp_obj_get_type(args[ARG_uuid].u_obj), &mp_type_bytearray)) { + BAD_UUID("uuid "); + } + + mp_get_buffer(args[ARG_uuid].u_obj, &uuid_buf, MP_BUFFER_READ); + if (uuid_buf.len != UUID_LEN) { + // FIXME: Is length really a fixed amount? + BAD_UUID("uuid "); + } + } + + // update esp_ble_data_t + + if (args[ARG_is_scan_rsp].u_obj != NULL) { + bluetooth->adv_data.set_scan_rsp = mp_obj_is_true(args[ARG_is_scan_rsp].u_obj); + changed = true; + } + + if (unset_dev_name) { + esp_ble_gap_set_device_name(""); + bluetooth->adv_data.include_name = false; + } else if (dev_name_buf.buf != NULL) { + esp_ble_gap_set_device_name(dev_name_buf.buf); + bluetooth->adv_data.include_name = dev_name_buf.len > 0; + changed = true; + } + + if (unset_man_name || man_name_buf.buf != NULL) { + if (bluetooth->adv_data.p_manufacturer_data != NULL) { + FREE(bluetooth->adv_data.p_manufacturer_data); + bluetooth->adv_data.p_manufacturer_data = NULL; + } + + bluetooth->adv_data.manufacturer_len = man_name_buf.len; + if (man_name_buf.len > 0) { + bluetooth->adv_data.p_manufacturer_data = MALLOC(man_name_buf.len); + memcpy(bluetooth->adv_data.p_manufacturer_data, man_name_buf.buf, man_name_buf.len); + } + changed = true; + } + + if (args[ARG_inc_txpower].u_obj != NULL) { + bluetooth->adv_data.include_txpower = mp_obj_is_true(args[ARG_inc_txpower].u_obj); + changed = true; + } + + if (args[ARG_int_min].u_int != -1) { + bluetooth->adv_data.min_interval = args[ARG_int_min].u_int; + changed = true; + } + + if (args[ARG_int_max].u_int != -1) { + bluetooth->adv_data.max_interval = args[ARG_int_max].u_int; + changed = true; + } + + if (args[ARG_appearance].u_int != -1) { + bluetooth->adv_data.appearance = args[ARG_appearance].u_int; + changed = true; + } + + if (unset_uuid || uuid_buf.buf != NULL) { + + if (bluetooth->adv_data.p_service_uuid != NULL) { + FREE(bluetooth->adv_data.p_service_uuid); + bluetooth->adv_data.p_service_uuid = NULL; + } + + bluetooth->adv_data.service_uuid_len = uuid_buf.len; + if (uuid_buf.len > 0) { + bluetooth->adv_data.p_service_uuid = MALLOC(uuid_buf.len); + bluetooth->adv_data.service_uuid_len = uuid_buf.len; + memcpy(bluetooth->adv_data.p_service_uuid, uuid_buf.buf, uuid_buf.len); + } + changed = true; + } + + if (args[ARG_flags].u_int != -1) { + bluetooth->adv_data.flag = args[ARG_flags].u_int; + changed = true; + } + + if (changed) { + btle_adv_updated(); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(btle_adv_data_obj, 1, btle_adv_data); + +STATIC mp_obj_t btle_ble_adv_enable(mp_obj_t self_in, mp_obj_t enable_in) { + btle_obj_t * self = MP_OBJ_TO_PTR(self_in); + bool enable = mp_obj_is_true(enable_in); + if (enable) { + esp_ble_adv_params_t params = { + .adv_int_min = MSEC_0_625_TO_UNIT(100), // 100ms + .adv_int_max = MSEC_0_625_TO_UNIT(100), // 100ms + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + }; + esp_ble_gap_start_advertising(¶ms); + } else { + esp_ble_gap_stop_advertising(); + } + self->advertising = enable; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(btle_ble_adv_enable_obj, btle_ble_adv_enable); + + +STATIC const mp_rom_map_elem_t btle_locals_dict_table[] = { + // instance methods + + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&btle_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_adv_params), MP_ROM_PTR(&btle_adv_params_obj) }, + { MP_ROM_QSTR(MP_QSTR_adv_data), MP_ROM_PTR(&btle_adv_data_obj) }, + { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&btle_ble_adv_enable_obj) }, + /* + { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&btle_ble_settings_obj) }, + { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&btle_ble_adv_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&btle_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&btle_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&btle_gatts_service_type) }, + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&btle_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_conns), MP_ROM_PTR(&btle_conns_obj) }, + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&btle_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&btle_scan_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&btle_scan_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_scanning), MP_ROM_PTR(&btle_is_scanning_obj) }, + + // class constants + + // Callback types + { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(BTLE_GATTS_CONNECT) }, + { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(BTLE_GATTS_DISCONNECT) }, + { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(BTLE_READ) }, + { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(BTLE_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_NOTIFY), MP_ROM_INT(BTLE_NOTIFY) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_RES), MP_ROM_INT(BTLE_GATTC_SCAN_RES) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_CMPL), MP_ROM_INT(BTLE_GATTC_SCAN_CMPL) }, + + // esp_ble_adv_type_t + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, + + // esp_ble_addr_type_t + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + + // esp_ble_adv_channel_t + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + + // BLE_ADV_DATA_FLAG + + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_LIMIT_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_LIMIT_DISC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_GEN_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_GEN_DISC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_BREDR_NOT_SPT), MP_ROM_INT(ESP_BLE_ADV_FLAG_BREDR_NOT_SPT) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_DMT_CONTROLLER_SPT), MP_ROM_INT(ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_DMT_HOST_SPT), MP_ROM_INT(ESP_BLE_ADV_FLAG_DMT_HOST_SPT) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_NON_LIMIT_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_NON_LIMIT_DISC) }, + + // Scan param constants + { MP_ROM_QSTR(MP_QSTR_SCAN_TYPE_PASSIVE), MP_ROM_INT(BLE_SCAN_TYPE_PASSIVE) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_TYPE_ACTIVE), MP_ROM_INT(BLE_SCAN_TYPE_ACTIVE) }, + + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_ALL), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_ALL) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_ONLY_WLST), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_ONLY_WLST) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_UND_RPA_DIR), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_UND_RPA_DIR) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_WLIST_PRA_DIR), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR) }, + + + // exp_gatt_perm_t + { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_READ_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_READ_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE), MP_ROM_INT(ESP_GATT_PERM_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED_MITM) }, + + // esp_gatt_char_prop_t + + { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_BROADCAST) }, + { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_READ) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_NR), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE_NR) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_NOTIFY) }, + { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_INDICATE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_AUTH), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_AUTH) }, + { MP_ROM_QSTR(MP_QSTR_PROP_EXT_PROP), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) }, + + // esp_ble_adv_filter_t + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) + }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) + }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) + }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) + }, + */ +}; + +STATIC MP_DEFINE_CONST_DICT(btle_locals_dict, btle_locals_dict_table); + +const mp_obj_type_t btle_type = { + { &mp_type_type }, + .name = MP_QSTR_Bluetooth, + .print = btle_print, + .make_new = btle_make_new, + .locals_dict = (mp_obj_dict_t*)&btle_locals_dict, +}; + + diff --git a/MicroPython_BUILD/components/micropython/esp32/gccollect.c b/MicroPython_BUILD/components/micropython/esp32/gccollect.c index 60ff319..8b6e570 100644 --- a/MicroPython_BUILD/components/micropython/esp32/gccollect.c +++ b/MicroPython_BUILD/components/micropython/esp32/gccollect.c @@ -1,5 +1,5 @@ /* - * 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 * @@ -7,6 +7,7 @@ * * Copyright (c) 2014 Damien P. George * Copyright (c) 2017 Pycom Limited + * 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/esp32/gccollect.h b/MicroPython_BUILD/components/micropython/esp32/gccollect.h index fe02cc6..d8b49bb 100644 --- a/MicroPython_BUILD/components/micropython/esp32/gccollect.h +++ b/MicroPython_BUILD/components/micropython/esp32/gccollect.h @@ -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) 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/esp32/libs/esp_rmt.c b/MicroPython_BUILD/components/micropython/esp32/libs/esp_rmt.c index a1cb358..02feff4 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/esp_rmt.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/esp_rmt.c @@ -1,3 +1,28 @@ +/* + * 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 #include "driver/rmt.h" diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/esp_rmt.h b/MicroPython_BUILD/components/micropython/esp32/libs/esp_rmt.h index cbf02a2..5d2f04c 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/esp_rmt.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/esp_rmt.h @@ -1,3 +1,28 @@ +/* + * 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 diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c index 48e85da..46aac88 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.c @@ -1,9 +1,9 @@ /* - * This file is part of the LoBo MicroPython project + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) 2017-2018 LoBo (https://gihub.com/loboris) + * 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/esp32/libs/espcurl.h b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.h index d035efd..0cafabd 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/espcurl.h @@ -1,9 +1,9 @@ /* - * This file is part of the LoBo MicroPython project + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) 2017-2018 LoBo (https://gihub.com/loboris) + * 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/esp32/libs/ftp.c b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c index 430ef0d..16921dd 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.c @@ -1,16 +1,9 @@ /* - * This file is based on 'ftp' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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 @@ -30,6 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/* + * This file is based on 'ftp' from Pycom Limited. + * + * Author: LoBo, loboris@gmail.com + * Copyright (c) 2017, LoBo + */ #include "sdkconfig.h" @@ -172,6 +171,7 @@ typedef enum { E_FTP_CMD_QUIT, E_FTP_CMD_APPE, E_FTP_CMD_NLST, + E_FTP_CMD_AUTH, E_FTP_NUM_FTP_CMDS } ftp_cmd_index_t; @@ -192,7 +192,7 @@ static const ftp_cmd_t ftp_cmd_table[] = { { "FEAT" }, { "SYST" }, { "CDUP" }, { { "TYPE" }, { "USER" }, { "PASS" }, { "PASV" }, { "LIST" }, { "RETR" }, { "STOR" }, { "DELE" }, { "RMD" }, { "MKD" }, { "RNFR" }, { "RNTO" }, - { "NOOP" }, { "QUIT" }, { "APPE" }, { "NLST" } }; + { "NOOP" }, { "QUIT" }, { "APPE" }, { "NLST" }, { "AUTH" } }; // ==== PRIVATE FUNCTIONS =================================================== @@ -768,7 +768,7 @@ static void ftp_process_cmd (void) { // bufptr is moved as commands are being popped ftp_cmd_index_t cmd = ftp_pop_command(&bufptr); if (!ftp_data.loggin.passvalid && - ((cmd != E_FTP_CMD_USER) && (cmd != E_FTP_CMD_PASS) && (cmd != E_FTP_CMD_QUIT) && (cmd != E_FTP_CMD_FEAT))) { + ((cmd != E_FTP_CMD_USER) && (cmd != E_FTP_CMD_PASS) && (cmd != E_FTP_CMD_QUIT) && (cmd != E_FTP_CMD_FEAT) && (cmd != E_FTP_CMD_AUTH))) { ftp_send_reply(332, NULL); return; } @@ -782,6 +782,9 @@ static void ftp_process_cmd (void) { case E_FTP_CMD_FEAT: ftp_send_reply(502, "no-features"); break; + case E_FTP_CMD_AUTH: + ftp_send_reply(504, "not-supported"); + break; case E_FTP_CMD_SYST: ftp_send_reply(215, "UNIX Type: L8"); break; diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h index dca687a..78aeee6 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ftp.h @@ -1,16 +1,9 @@ /* - * This file is based on 'ftp' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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 @@ -30,6 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/* + * This file is based on 'ftp' from Pycom Limited. + * + * Author: LoBo, loboris@gmail.com + * Copyright (c) 2017, LoBo + */ #ifndef FTP_H_ #define FTP_H_ diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c b/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c index e8aab3b..b34603a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/libGSM.c @@ -1,10 +1,27 @@ -/* PPPoS Client Example with GSM (tested with Telit GL865-DUAL-V3) - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. +/* + * 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" @@ -551,7 +568,7 @@ static void enableAllInitCmd() static void checkSMS() { if ((New_SMS_cb) && (SMS_check_interval > 0) && (doCheckSMS)) { - // Check for new SMS + // Check for new SMS and schedule MicroPython callback function uint8_t dbg = debug; debug = 0; if (sms_timer > SMS_check_interval) { @@ -559,12 +576,23 @@ static void checkSMS() SMS_indexes indexes; int nmsg = smsCount(SMS_LIST_NEW, &indexes, SMS_SORT_NONE); if (nmsg > 0) { - mp_obj_t msgidx_tuple[nmsg]; - for (int i=0; i 100) nmsg = 100; + // Create a string containing SMS indexes + char sidx[4]; + char *sindexes = calloc(nmsg*3, 1); + if (sindexes) { + for (int i=0; i #include diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h b/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h index 7cc8075..646c983 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/neopixel.h @@ -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. + */ + #pragma once #include "driver/gpio.h" diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/ow/ds18b20.c b/MicroPython_BUILD/components/micropython/esp32/libs/ow/ds18b20.c index 6b33bbf..2a74bab 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ow/ds18b20.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ow/ds18b20.c @@ -2,6 +2,7 @@ * MIT License * * Copyright (c) 2017 David Antliff + * 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/esp32/libs/ow/ds18b20.h b/MicroPython_BUILD/components/micropython/esp32/libs/ow/ds18b20.h index a935f30..148ff21 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ow/ds18b20.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ow/ds18b20.h @@ -2,6 +2,7 @@ * MIT License * * Copyright (c) 2017 David Antliff + * 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/esp32/libs/ow/owb.c b/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb.c index 406cde8..03747dc 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb.c @@ -3,6 +3,7 @@ * * Copyright (c) 2017 David Antliff * Copyright (c) 2017 Chris Morgan + * 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/esp32/libs/ow/owb.h b/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb.h index 31586b2..094a77c 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb.h @@ -3,6 +3,7 @@ * * Copyright (c) 2017 David Antliff * Copyright (c) 2017 Chris Morgan + * 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/esp32/libs/ow/owb_rmt.c b/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb_rmt.c index aa200a7..c47a35c 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb_rmt.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/ow/owb_rmt.c @@ -1,6 +1,7 @@ /* Created by Chris Morgan based on the nodemcu project driver. Copyright 2017 Chris Morgan +Copyright (c) 2018 LoBo (https://github.com/loboris) Ported to ESP32 RMT peripheral for low-level signal generation by Arnim Laeuger. diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c index 88e5fcd..f0abb6c 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.c @@ -1,16 +1,9 @@ /* - * This file is based on 'telnet' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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 @@ -30,6 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/* + * This file is based on 'telnet' from Pycom Limited. + * + * Author: LoBo, loboris@gmail.com + * Copyright (c) 2017, LoBo + */ #include "sdkconfig.h" diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h index 8164476..a39850d 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/telnet.h @@ -1,16 +1,9 @@ /* - * This file is based on 'telnet' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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 @@ -30,6 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/* + * This file is based on 'telnet' from Pycom Limited. + * + * Author: LoBo, loboris@gmail.com + * Copyright (c) 2017, LoBo + */ #ifndef TELNET_H_ #define TELNET_H_ diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c index 663f59c..b7c8943 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/SmallFont.c @@ -3,16 +3,6 @@ // Font size : 8x12 pixels // Memory usage : 1144 bytes -#if defined(__AVR__) - #include - #define fontdatatype const uint8_t -#elif defined(__PIC32MX__) - #define PROGMEM - #define fontdatatype const unsigned char -#elif defined(__arm__) - #define PROGMEM - #define fontdatatype const unsigned char -#endif const unsigned char tft_SmallFont[1144] = { diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h b/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h index 6a52454..50f3e19 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/stmpe610.h @@ -1,3 +1,28 @@ +/* + * 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. + */ /* STMPE610 Touch controller constants */ @@ -7,7 +32,7 @@ #include -#define STMPE610_SPI_MODE 1 +#define STMPE610_SPI_MODE 0 // Identification registers #define STMPE610_REG_CHP_ID 0x00 // 16-bit @@ -67,5 +92,57 @@ #define STMPE610_REG_TSC_I_DRIVE 0x58 #define STMPE610_REG_TSC_SHIELD 0x59 +#define STMPE610_REG_TSC_CTRL_EN 0x01 +#define STMPE610_REG_TSC_CTRL_XYZ 0x00 +#define STMPE610_REG_TSC_CTRL_XY 0x02 +#define STMPE610_REG_INT_EN 0x0A +#define STMPE610_REG_INT_EN_TOUCHDET 0x01 +#define STMPE610_REG_INT_EN_FIFOTH 0x02 +#define STMPE610_REG_INT_EN_FIFOOF 0x04 +#define STMPE610_REG_INT_EN_FIFOFULL 0x08 +#define STMPE610_REG_INT_EN_FIFOEMPTY 0x10 +#define STMPE610_REG_INT_EN_ADC 0x40 +#define STMPE610_REG_INT_EN_GPIO 0x80 +#define STMPE610_REG_ADC_CTRL1_12BIT 0x08 +#define STMPE610_REG_ADC_CTRL1_10BIT 0x00 +#define STMPE610_REG_ADC_CTRL2_1_625MHZ 0x00 +#define STMPE610_REG_ADC_CTRL2_3_25MHZ 0x01 +#define STMPE610_REG_ADC_CTRL2_6_5MHZ 0x02 +#define STMPE610_REG_ADC_CTRL2_1_625MHZ 0x00 +#define STMPE610_REG_ADC_CTRL2_3_25MHZ 0x01 +#define STMPE610_REG_ADC_CTRL2_6_5MHZ 0x02 +#define STMPE610_REG_TSC_CFG_1SAMPLE 0x00 +#define STMPE610_REG_TSC_CFG_2SAMPLE 0x40 +#define STMPE610_REG_TSC_CFG_4SAMPLE 0x80 +#define STMPE610_REG_TSC_CFG_8SAMPLE 0xC0 +#define STMPE610_REG_TSC_CFG_DELAY_10US 0x00 +#define STMPE610_REG_TSC_CFG_DELAY_50US 0x08 +#define STMPE610_REG_TSC_CFG_DELAY_100US 0x10 +#define STMPE610_REG_TSC_CFG_DELAY_500US 0x18 +#define STMPE610_REG_TSC_CFG_DELAY_1MS 0x20 +#define STMPE610_REG_TSC_CFG_DELAY_5MS 0x28 +#define STMPE610_REG_TSC_CFG_DELAY_10MS 0x30 +#define STMPE610_REG_TSC_CFG_DELAY_50MS 0x38 +#define STMPE610_REG_TSC_CFG_SETTLE_10US 0x00 +#define STMPE610_REG_TSC_CFG_SETTLE_100US 0x01 +#define STMPE610_REG_TSC_CFG_SETTLE_500US 0x02 +#define STMPE610_REG_TSC_CFG_SETTLE_1MS 0x03 +#define STMPE610_REG_TSC_CFG_SETTLE_5MS 0x04 +#define STMPE610_REG_TSC_CFG_SETTLE_10MS 0x05 +#define STMPE610_REG_TSC_CFG_SETTLE_50MS 0x06 +#define STMPE610_REG_TSC_CFG_SETTLE_100MS 0x07 +#define STMPE610_REG_FIFO_STA_RESET 0x01 +#define STMPE610_REG_FIFO_STA_OFLOW 0x80 +#define STMPE610_REG_FIFO_STA_FULL 0x40 +#define STMPE610_REG_FIFO_STA_EMPTY 0x20 +#define STMPE610_REG_FIFO_STA_THTRIG 0x10 +#define STMPE610_REG_TSC_I_DRIVE_20MA 0x00 +#define STMPE610_REG_TSC_I_DRIVE_50MA 0x01 +#define STMPE610_REG_INT_CTRL_POL_HIGH 0x04 +#define STMPE610_REG_INT_CTRL_POL_LOW 0x00 +#define STMPE610_REG_INT_CTRL_EDGE 0x02 +#define STMPE610_REG_INT_CTRL_LEVEL 0x00 +#define STMPE610_REG_INT_CTRL_ENABLE 0x01 +#define STMPE610_REG_INT_CTRL_DISABLE 0x00 #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 45c8f11..1f7eb91 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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 Boris Lovosevic (https://github/loboris) + * 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 +27,7 @@ /* * TFT library * - * Author: LoBo, 08/2017 + * Author: LoBo, 01/2018 * * Library supporting SPI TFT displays based on ILI9341, ILI9488 & ST7789V controllers */ @@ -47,6 +47,7 @@ #include "tftspi.h" #include "py/mpprint.h" +#include "extmod/vfs_native.h" #define DEG_TO_RAD 0.01745329252 #define RAD_TO_DEG 57.295779513 @@ -63,14 +64,13 @@ // Embedded fonts extern uint8_t tft_SmallFont[]; extern uint8_t tft_DefaultFont[]; -extern uint8_t tft_def_small[]; extern uint8_t tft_Dejavu18[]; extern uint8_t tft_Dejavu24[]; extern uint8_t tft_Ubuntu16[]; extern uint8_t tft_Comic24[]; extern uint8_t tft_minya24[]; extern uint8_t tft_tooney32[]; - +extern uint8_t tft_def_small[]; // ==== Color definitions constants ============== const color_t TFT_BLACK = { 0, 0, 0 }; @@ -92,7 +92,6 @@ const color_t TFT_WHITE = { 252, 252, 252 }; const color_t TFT_ORANGE = { 252, 164, 0 }; const color_t TFT_GREENYELLOW = { 172, 252, 44 }; const color_t TFT_PINK = { 252, 192, 202 }; - // =============================================== // ============================================================== @@ -111,7 +110,6 @@ float _angleOffset = DEFAULT_ANGLE_OFFSET; int TFT_X = 0; int TFT_Y = 0; -uint8_t tp_type = TOUCH_TYPE_NONE; uint32_t tp_calx = 0; uint32_t tp_caly = 0; @@ -152,6 +150,7 @@ static uint8_t *userfont = NULL; static int TFT_OFFSET = 0; static propFont fontChar; static float _arcAngleMax = DEFAULT_ARC_ANGLE_MAX; +static bool image_trans = false; // ========================================================================= @@ -209,20 +208,6 @@ static void _drawFastVLine(int16_t x, int16_t y, int16_t h, color_t color) { TFT_pushColorRep(x, y, x, y+h-1, color, (uint32_t)h); } -//--------------------------------------------------------------------------- -static void _drawFastVLine_(int16_t x, int16_t y, int16_t h, color_t color) { - // clipping - if ((x < dispWin.x1) || (x > dispWin.x2) || (y > dispWin.y2)) return; - if (y < dispWin.y1) { - h -= (dispWin.y1 - y); - y = dispWin.y1; - } - if (h < 0) h = 0; - if ((y + h) > (dispWin.y2+1)) h = dispWin.y2 - y + 1; - if (h == 0) h = 1; - TFT_pushColorRep_nocs(x, y, x, y+h-1, color, (uint32_t)h); -} - //-------------------------------------------------------------------------- static void _drawFastHLine(int16_t x, int16_t y, int16_t w, color_t color) { // clipping @@ -423,33 +408,25 @@ static void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornerna int16_t x = 0; int16_t y = r; int16_t ylm = x0 - r; - uint8_t v = 0; - if (cornername == 3) v = 1; - disp_select(); while (x < y) { if (f >= 0) { - if (cornername & 0x1) _drawFastVLine_(x0 + y, y0 - x, 2 * x + 1 + delta, color); - if (cornername & 0x2) _drawFastVLine_(x0 - y, y0 - x, 2 * x + 1 + delta, color); + if (cornername & 0x1) _drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta, color); + if (cornername & 0x2) _drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta, color); ylm = x0 - y; y--; ddF_y += 2; f += ddF_y; } - if (v) { - _drawFastVLine_(x0 - x, y0 - y, 2 * y + 1 + delta, color); - v = 0; - } x++; ddF_x += 2; f += ddF_x; if ((x0 - x) > ylm) { - if (cornername & 0x1) _drawFastVLine_(x0 + x, y0 - y, 2 * y + 1 + delta, color); - if (cornername & 0x2) _drawFastVLine_(x0 - x, y0 - y, 2 * y + 1 + delta, color); + if (cornername & 0x1) _drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta, color); + if (cornername & 0x2) _drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta, color); } } - disp_deselect(); } // Draw a rounded rectangle @@ -674,6 +651,7 @@ void TFT_fillCircle(int16_t x, int16_t y, int radius, color_t color) { x += dispWin.x1; y += dispWin.y1; + _drawFastVLine(x, y-radius, 2*radius+1, color); fillCircleHelper(x, y, radius, 3, 0, color); } @@ -1082,7 +1060,17 @@ static int load_file_font(const char * fontfile, int info) struct stat sb; - // Check if file exists and get file size + spi_device_deselect(disp_spi); + spi_device_deselect(ts_spi); + // Open the file + FILE *fhndl = fopen(fontfile, "rb"); + if (fhndl == NULL) { + sprintf(err_msg, "Error opening font file '%s'", fontfile); + err = 1; + goto exit; + } + + // Get file size if (stat(fontfile, &sb) != 0) { sprintf(err_msg, "Error getting font file size"); err = 2; @@ -1098,18 +1086,11 @@ static int load_file_font(const char * fontfile, int info) userfont = malloc(fsize+4); if (userfont == NULL) { sprintf(err_msg, "Font memory allocation error"); + fclose(fhndl); err = 4; goto exit; } - // Open the file - FILE *fhndl = fopen(fontfile, "r"); - if (!fhndl) { - sprintf(err_msg, "Error opening font file '%s'", fontfile); - err = 1; - goto exit; - } - int read = fread(userfont, 1, fsize, fhndl); fclose(fhndl); @@ -1339,7 +1320,7 @@ int compile_font_file(char *fontfile, uint8_t dbg) sprintf(outfile, "%s", fontfile); sprintf(outfile+strlen(outfile)-1, "fon"); - uint8_t *uf = userfont; // save user font pointer + uint8_t *uf = userfont; // save userfont pointer userfont = NULL; if (load_file_font(outfile, 1) != 0) { sprintf(err_msg, "Error compiling file!"); @@ -1500,8 +1481,22 @@ static uint8_t getCharPtr(uint8_t c) { } /* -//----------------------- -static void _testFont() { +const char fontnames[] = { + "FONT_Default", + "FONT_DejaVu18", + "FONT_DejaVu24", + "FONT_Ubuntu", + "FONT_Comic", + "FONT_Minya", + "FONT_Tooney", + "FONT_Small", + "FONT_DefaultSmall", + "FONT_7seg", + "External font" +}; + +//--------------------- +void fontProperties() { if (cfont.x_size) { mp_printf(&mp_plat_print, "FONT TEST: fixed font\r\n"); return; @@ -1606,8 +1601,8 @@ static int printProportionalChar(int x, int y) { int len, bufPos; // === buffer Glyph data for faster sending === - len = char_width * cfont.y_size; - color_t *color_line = heap_caps_malloc(len*3, MALLOC_CAP_DMA); + len = (char_width+1) * cfont.y_size; + color_t *color_line = malloc(len*3); if (color_line) { // fill with background color for (int n = 0; n < len; n++) { @@ -1623,26 +1618,16 @@ static int printProportionalChar(int x, int y) { } if ((ch & mask) != 0) { // visible pixel - bufPos = ((j + fontChar.adjYOffset) * char_width) + (fontChar.xOffset + i); // bufY + bufX + bufPos = ((j + fontChar.adjYOffset) * (char_width+1)) + (fontChar.xOffset + i); // bufY + bufX color_line[bufPos] = _fg; - /* - bufY = (j + fontChar.adjYOffset) * char_width; - bufX = fontChar.xOffset + i; - if ((bufX < 0) || (bufX > char_width)) { - mp_printf(&mp_plat_print, "[%c] X ERR: %d\r\n", fontChar.charCode, bufX); - } - bufPos = bufY + bufX; - if ((bufPos < len) && (bufPos > 0)) color_line[bufPos] = _fg; - else mp_printf(&mp_plat_print, "[%c] ERR: %d > %d W=%d H=%d bufX=%d bufY=%d X=%d Y=%d\r\n", - fontChar.charCode, bufPos, len, char_width, cfont.y_size, bufX, bufY, fontChar.xOffset + i, j + fontChar.adjYOffset); - */ } mask >>= 1; } } // send to display in one transaction + wait_trans_finish(1); disp_select(); - send_data(x, y, x+char_width-1, y+cfont.y_size-1, len, color_line); + send_data(x, y, x+char_width, y+cfont.y_size-1, len, color_line, 1); disp_deselect(); free(color_line); @@ -1693,7 +1678,7 @@ static void printChar(uint8_t c, int x, int y) { if ((font_buffered_char) && (!font_transparent)) { // === buffer Glyph data for faster sending === len = cfont.x_size * cfont.y_size; - color_t *color_line = heap_caps_malloc(len*3, MALLOC_CAP_DMA); + color_t *color_line = malloc(len*3); if (color_line) { // fill with background color for (int n = 0; n < len; n++) { @@ -1712,8 +1697,9 @@ 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); + send_data(x, y, x+cfont.x_size-1, y+cfont.y_size-1, len, color_line, 1); disp_deselect(); free(color_line); @@ -2205,7 +2191,6 @@ color_t HSBtoRGB(float _hue, float _sat, float _brightness) { return color; } - //===================================================================== void TFT_setclipwin(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { @@ -2409,12 +2394,20 @@ static UINT tjd_output ( else src += 3; // skip } } - wait_trans_finish(1); - send_data(dleft, dtop, dright, dbottom, len, dev->linbuf[dev->linbuf_idx]); + 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 { - wait_trans_finish(1); + if (image_trans) wait_trans_finish(1); mp_printf(&mp_plat_print, "Data size error: %d jpg: (%d,%d,%d,%d) disp: (%d,%d,%d,%d)\r\n", len, left,top,right,bottom, dleft,dtop,dright,dbottom); return 0; // stop decompression } @@ -2463,7 +2456,10 @@ void TFT_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int s } } - if (scale > 3) scale = 3; + // Check if the image file is on sdcard + image_trans = file_noton_spi_sdcard(fname); + + if (scale > 3) scale = 3; work = malloc(sz_work); if (work) { @@ -2484,21 +2480,24 @@ 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] = heap_caps_malloc(JPG_IMAGE_LINE_BUF_SIZE*3, MALLOC_CAP_DMA); + 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] = heap_caps_malloc(JPG_IMAGE_LINE_BUF_SIZE*3, MALLOC_CAP_DMA); + 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 - disp_select(); + if (image_trans) disp_select(); rc = jd_decomp(&jd, tjd_output, scale); - disp_deselect(); + if (image_trans) { + wait_trans_finish(1); + disp_deselect(); + } if (rc != JDR_OK) { if (image_debug) mp_printf(&mp_plat_print, "jpg decompression error %d\r\n", rc); @@ -2571,6 +2570,9 @@ int TFT_bmp_image(int x, int y, uint8_t scale, char *fname, uint8_t *imgbuf, int else i = 0; } + // Check if the image file is on sdcard + image_trans = file_noton_spi_sdcard(fname); + sprintf(err_buf, "reading header"); if (i != 54) {err = -3; goto exit;} @@ -2652,14 +2654,14 @@ int TFT_bmp_image(int x, int y, uint8_t scale, char *fname, uint8_t *imgbuf, int } // ** Allocate memory for 2 lines of image pixels - line_buf[0] = heap_caps_malloc(img_xsize*3, MALLOC_CAP_DMA); + line_buf[0] = malloc(img_xsize*3); if (line_buf[0] == NULL) { sprintf(err_buf, "allocating line buffer #1"); err=-12; goto exit; } - line_buf[1] = heap_caps_malloc(img_xsize*3, MALLOC_CAP_DMA); + line_buf[1] = malloc(img_xsize*3); if (line_buf[1] == NULL) { sprintf(err_buf, "allocating line buffer #2"); err=-13; @@ -2708,7 +2710,7 @@ int TFT_bmp_image(int x, int y, uint8_t scale, char *fname, uint8_t *imgbuf, int 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)); // * Select the display - disp_select(); + if (image_trans) disp_select(); while ((disp_yend >= disp_ystart) && ((img_pos + (img_xsize*3)) <= size)) { if (img_pos > size) { @@ -2781,15 +2783,24 @@ int TFT_bmp_image(int x, int y, uint8_t scale, char *fname, uint8_t *imgbuf, int } } - wait_trans_finish(1); - send_data(disp_xstart, disp_yend, disp_xend, disp_yend, img_xlen, (color_t *)line_buf[lb_idx]); + if (image_trans) { + wait_trans_finish(1); + send_data(disp_xstart, disp_yend, disp_xend, disp_yend, img_xlen, (color_t *)line_buf[lb_idx], 0); + } + else { + disp_select(); + send_data(disp_xstart, disp_yend, disp_xend, disp_yend, img_xlen, (color_t *)line_buf[lb_idx], 0); + wait_trans_finish(1); + disp_deselect(); + } lb_idx = (lb_idx + 1) & 1; // change buffer disp_yend--; } + wait_trans_finish(1); err = 0; exit1: - disp_deselect(); + if (image_trans) disp_deselect(); exit: if (scale_buf) free(scale_buf); if (line_buf[0]) free(line_buf[0]); @@ -2806,7 +2817,7 @@ exit: //------------------------------------------------------- static int tp_get_data_xpt2046(uint8_t type, int samples) { - if (ts_spi == NULL) return 0; + if (ts_spi->handle == NULL) return 0; int n, result, val = 0; uint32_t i = 0; @@ -2868,7 +2879,7 @@ static int tp_get_data_xpt2046(uint8_t type, int samples) static int TFT_read_touch_xpt2046(int *x, int* y) { int res = 0, result = -1; - if (spi_lobo_device_select(ts_spi, 0) != ESP_OK) return 0; + if (spi_device_select(ts_spi, 0) != ESP_OK) return 0; result = tp_get_data_xpt2046(0xB0, 3); // Z; pressure; touch detect if (result <= 50) goto exit; @@ -2885,31 +2896,40 @@ static int TFT_read_touch_xpt2046(int *x, int* y) *y = result; res = 1; exit: - spi_lobo_device_deselect(ts_spi); + spi_device_deselect(ts_spi); return res; } - //============================================= int TFT_read_touch(int *x, int* y, uint8_t raw) { *x = 0; *y = 0; - if (ts_spi == NULL) return 0; - - int result = -1; + if (ts_spi->handle == NULL) return 0; + if (tft_touch_type == TOUCH_TYPE_NONE) return 0; + int result = -1; int X=0, Y=0; - if (tp_type == TOUCH_TYPE_XPT2046) { - result = TFT_read_touch_xpt2046(&X, &Y); - if (result == 0) return 0; + if (tft_touch_type == TOUCH_TYPE_XPT2046) { + if (tp_calx == 0) { + // Set default calibration constants + tp_calx = TP_CALX_XPT2046; + tp_caly = TP_CALY_XPT2046; + } + result = TFT_read_touch_xpt2046(&X, &Y); + if (result == 0) return 0; } - else if (tp_type == TOUCH_TYPE_STMPE610) { - uint16_t Xx, Yy, Z=0; - result = stmpe610_get_touch(&Xx, &Yy, &Z); - if (result == 0) return 0; - X = Xx; - Y = Yy; + else if (tft_touch_type == TOUCH_TYPE_STMPE610) { + if (tp_calx == 0) { + // Set default calibration constants + tp_calx = TP_CALX_STMPE610; + tp_caly = TP_CALY_STMPE610; + } + uint16_t Xx, Yy, Z=0; + result = stmpe610_get_touch(&Xx, &Yy, &Z); + if (result == 0) return 0; + X = Xx; + Y = Yy; } else return 0; @@ -2926,38 +2946,39 @@ int TFT_read_touch(int *x, int* y, uint8_t raw) int ytop = (tp_caly >> 16) & 0x3FFF; int ybottom = tp_caly & 0x3FFF; - int width = _width; - int height = _height; - if (((xright - xleft) <= 0) || ((ybottom - ytop) <= 0)) return 0; - if (tp_type == TOUCH_TYPE_XPT2046) { - X = ((X - xleft) * height) / (xright - xleft); - Y = ((Y - ytop) * width) / (ybottom - ytop); + if (tft_touch_type == TOUCH_TYPE_XPT2046) { + int width = _width; + int height = _height; + X = ((X - xleft) * height) / (xright - xleft); + Y = ((Y - ytop) * width) / (ybottom - ytop); - if (X < 0) X = 0; - if (X > height-1) X = height-1; - if (Y < 0) Y = 0; - if (Y > width-1) Y = width-1; + if (X < 0) X = 0; + if (X > height-1) X = height-1; + if (Y < 0) Y = 0; + if (Y > width-1) Y = width-1; - switch (orientation) { - case PORTRAIT: - tmp = X; - X = width - Y - 1; - Y = tmp; - break; - case PORTRAIT_FLIP: - tmp = X; - X = Y; - Y = height - tmp - 1; - break; - case LANDSCAPE_FLIP: - X = height - X - 1; - Y = width - Y - 1; - break; - } + switch (orientation) { + case PORTRAIT: + tmp = X; + X = width - Y - 1; + Y = tmp; + break; + case PORTRAIT_FLIP: + tmp = X; + X = Y; + Y = height - tmp - 1; + break; + case LANDSCAPE_FLIP: + X = height - X - 1; + Y = width - Y - 1; + break; + } } - else if (tp_type == TOUCH_TYPE_STMPE610) { + else if (tft_touch_type == TOUCH_TYPE_STMPE610) { + int width = _width; + int height = _height; if (_width > _height) { width = _height; height = _width; diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h index 5321082..a5ebc45 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tft.h @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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 Boris Lovosevic (https://github/loboris) + * 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 @@ -23,14 +23,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - /* - * TFT library - * - * Author: LoBo, 08/2017 - * - * Library supporting SPI TFT displays based on ILI9341, ILI9488 & ST7789V controllers -*/ + * High level TFT functions + * Author: LoBo 02/2018, https://github/loboris + * + */ #ifndef _TFT_H_ #define _TFT_H_ @@ -38,16 +35,6 @@ #include #include "tftspi.h" -#define TOUCH_TYPE_NONE 0 -#define TOUCH_TYPE_XPT2046 1 -#define TOUCH_TYPE_STMPE610 2 - -#define TP_CALX_XPT2046 7472920 -#define TP_CALY_XPT2046 122224794 - -#define TP_CALX_STMPE610 21368532 -#define TP_CALY_STMPE610 11800144 - typedef struct { uint16_t x1; uint16_t y1; @@ -89,7 +76,6 @@ 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 uint8_t tp_type; // touch controller type extern uint32_t tp_calx; // touch screen X calibration constant extern uint32_t tp_caly; // touch screen Y calibration constant // ========================================================================================= @@ -188,6 +174,7 @@ extern const color_t TFT_PINK; #define IMAGE_TYPE_JPG 1 #define IMAGE_TYPE_BMP 2 + // ===== PUBLIC FUNCTIONS ========================================================================= diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c index 2d73368..9f82d57 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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 Boris Lovosevic (https://github/loboris) + * 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 @@ -23,11 +23,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - /* - * Author: LoBo, 08/2017 + * Author: LoBo (loboris@gmail.com, loboris.github) * - * Library supporting SPI TFT displays based on ILI9341, ILI9488 & ST7789V controllers + * Module supporting SPI TFT displays based on ILI9341 & ILI9488 controllers * * HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS * USING DIRECT or DMA SPI TRANSFER MODEs @@ -39,7 +38,9 @@ #include "esp_system.h" #include "freertos/task.h" #include "esp_heap_caps.h" +#include "esp_attr.h" #include "soc/spi_reg.h" +#include "esp_log.h" // ==================================================== @@ -48,7 +49,7 @@ // Converts colors to grayscale if set to 1 uint8_t gray_scale = 0; // Spi clock for reading data from display memory in Hz -uint32_t max_rdclock = 8000000; +uint32_t max_rdclock = 4000000; // Default display dimensions int _width = DEFAULT_TFT_DISPLAY_WIDTH; @@ -56,22 +57,23 @@ int _height = DEFAULT_TFT_DISPLAY_HEIGHT; // Display type, DISP_TYPE_ILI9488 or DISP_TYPE_ILI9341 uint8_t tft_disp_type = DEFAULT_DISP_TYPE; +uint8_t tft_touch_type = TOUCH_TYPE_NONE; // Spi device handles for display and touch screen -spi_lobo_device_handle_t disp_spi = NULL; -spi_lobo_device_handle_t ts_spi = NULL; - -int8_t pin_bckl = -1; -uint8_t bckl_on = 0; -int8_t pin_rst = -1; -uint8_t pin_dc = PIN_NUM_DC; -uint8_t _invert_rot = 0; // set to 0, 1, 2 (for example the display on WROVER-KIT v3 requires 2) -uint8_t _rgb_bgr = 0; // set to 0 for RGB, to 8 for BGR display matrix +exspi_device_handle_t *disp_spi = NULL; +exspi_device_handle_t *ts_spi = NULL; +uint8_t bits_per_color = 16; +uint8_t TFT_RGB_BGR = 0; +uint8_t gamma_curve = 0; +uint32_t spi_speed = 10000000; // ==================================================== static color_t *trans_cline = NULL; -static uint8_t _dma_sending = 0; +static const char TAG[] = "[TFTSPI]"; +static uint8_t invertrot = 0; + +uint8_t spibus_is_init = 0; // RGB to GRAYSCALE constants // 0.2989 0.5870 0.1140 @@ -83,110 +85,54 @@ static uint8_t _dma_sending = 0; // ==== Functions ===================== -//------------------------------------------------------ -esp_err_t IRAM_ATTR wait_trans_finish(uint8_t free_line) -{ - // Wait for SPI bus ready - while (disp_spi->host->hw->cmd.usr); - if ((free_line) && (trans_cline)) { - free(trans_cline); - trans_cline = NULL; - } - if (_dma_sending) { - //Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset. - if (disp_spi->host->dma_chan) spi_lobo_dmaworkaround_idle(disp_spi->host->dma_chan); - - // Reset DMA - disp_spi->host->hw->dma_conf.val |= SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST; - disp_spi->host->hw->dma_out_link.start=0; - disp_spi->host->hw->dma_in_link.start=0; - disp_spi->host->hw->dma_conf.val &= ~(SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST); - disp_spi->host->hw->dma_conf.out_data_burst_en=1; - _dma_sending = 0; - } - return ESP_OK; -} - //------------------------------- esp_err_t IRAM_ATTR disp_select() { - wait_trans_finish(1); - return spi_lobo_device_select(disp_spi, 0); + //wait_trans_finish(1); + return spi_device_select(disp_spi, 0); } //--------------------------------- esp_err_t IRAM_ATTR disp_deselect() { - wait_trans_finish(1); - return spi_lobo_device_deselect(disp_spi); -} - -//--------------------------------------------------------------------------------------------------- -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; - } - else { - spi_dev->host->hw->miso_dlen.usr_miso_dbitlen = 0; - spi_dev->host->hw->user.usr_miso = 0; - } - // Start transfer - spi_dev->host->hw->cmd.usr = 1; - // Wait for SPI bus ready - while (spi_dev->host->hw->cmd.usr); -} - -// Send 1 byte display command, display must be selected -//------------------------------------------------ -void IRAM_ATTR disp_spi_transfer_cmd(int8_t cmd) { - // Wait for SPI bus ready - while (disp_spi->host->hw->cmd.usr); - - // Set DC to 0 (command mode); - gpio_set_level(pin_dc, 0); - - disp_spi->host->hw->data_buf[0] = (uint32_t)cmd; - _spi_transfer_start(disp_spi, 8, 0); + //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) { - // Wait for SPI bus ready - while (disp_spi->host->hw->cmd.usr); +//-------------------------------------------------------------------------------- +void IRAM_ATTR 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 // Set DC to 0 (command mode); - gpio_set_level(pin_dc, 0); + gpio_set_level(disp_spi->dc, 0); - disp_spi->host->hw->data_buf[0] = (uint32_t)cmd; + disp_spi->handle->host->hw->data_buf[0] = (uint32_t)cmd; _spi_transfer_start(disp_spi, 8, 0); if ((len == 0) || (data == NULL)) return; + while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready // Set DC to 1 (data mode); - gpio_set_level(pin_dc, 1); + gpio_set_level(disp_spi->dc, 1); uint8_t idx=0, bidx=0; uint32_t bits=0; uint32_t count=0; uint32_t wd = 0; while (count < len) { - // get data byte from buffer + // get data byte from buffer, fill spi buffer wd |= (uint32_t)data[count] << bidx; count++; bits += 8; bidx += 8; if (count == len) { - disp_spi->host->hw->data_buf[idx] = wd; + disp_spi->handle->host->hw->data_buf[idx] = wd; break; } if (bidx == 32) { - disp_spi->host->hw->data_buf[idx] = wd; + disp_spi->handle->host->hw->data_buf[idx] = wd; idx++; bidx = 0; wd = 0; @@ -203,55 +149,47 @@ void IRAM_ATTR disp_spi_transfer_cmd_data(int8_t cmd, uint8_t *data, uint32_t le if (bits > 0) _spi_transfer_start(disp_spi, bits, 0); } +// Send 1 byte display command, display must be selected +//---------------------------------------------- +void IRAM_ATTR disp_spi_transfer_cmd(int8_t cmd) +{ + while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + + // Set DC to 0 (command mode); + gpio_set_level(disp_spi->dc, 0); + + disp_spi->handle->host->hw->data_buf[0] = (uint32_t)cmd; + _spi_transfer_start(disp_spi, 8, 0); +} + // 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) { uint32_t wd; - taskDISABLE_INTERRUPTS(); - // Wait for SPI bus ready - while (disp_spi->host->hw->cmd.usr); - gpio_set_level(pin_dc, 0); + disp_spi_transfer_cmd(TFT_CASET); - disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_CASET; - disp_spi->host->hw->user.usr_mosi_highpart = 0; - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7; - disp_spi->host->hw->user.usr_mosi = 1; - disp_spi->host->hw->miso_dlen.usr_miso_dbitlen = 0; - disp_spi->host->hw->user.usr_miso = 0; + wd = (uint32_t)(x1 >> 8); + wd |= (uint32_t)(x1 & 0xff) << 8; + wd |= (uint32_t)(x2 >> 8) << 16; + wd |= (uint32_t)(x2 & 0xff) << 24; - disp_spi->host->hw->cmd.usr = 1; // Start transfer + while (disp_spi->handle->host->hw->cmd.usr); // wait transfer end + gpio_set_level(disp_spi->dc, 1); + disp_spi->handle->host->hw->data_buf[0] = wd; + _spi_transfer_start(disp_spi, 32, 0); - wd = (uint32_t)(x1>>8); - wd |= (uint32_t)(x1&0xff) << 8; - wd |= (uint32_t)(x2>>8) << 16; - wd |= (uint32_t)(x2&0xff) << 24; + disp_spi_transfer_cmd(TFT_PASET); - while (disp_spi->host->hw->cmd.usr); // wait transfer end - gpio_set_level(pin_dc, 1); - disp_spi->host->hw->data_buf[0] = wd; - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 31; - disp_spi->host->hw->cmd.usr = 1; // Start transfer + wd = (uint32_t)(y1 >> 8); + wd |= (uint32_t)(y1 & 0xff) << 8; + wd |= (uint32_t)(y2 >> 8) << 16; + wd |= (uint32_t)(y2 & 0xff) << 24; - while (disp_spi->host->hw->cmd.usr); - gpio_set_level(pin_dc, 0); - disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_PASET; - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7; - disp_spi->host->hw->cmd.usr = 1; // Start transfer - - wd = (uint32_t)(y1>>8); - wd |= (uint32_t)(y1&0xff) << 8; - wd |= (uint32_t)(y2>>8) << 16; - wd |= (uint32_t)(y2&0xff) << 24; - - while (disp_spi->host->hw->cmd.usr); - gpio_set_level(pin_dc, 1); - - disp_spi->host->hw->data_buf[0] = wd; - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 31; - disp_spi->host->hw->cmd.usr = 1; // Start transfer - while (disp_spi->host->hw->cmd.usr); - taskENABLE_INTERRUPTS(); + while (disp_spi->handle->host->hw->cmd.usr); // wait transfer end + gpio_set_level(disp_spi->dc, 1); + disp_spi->handle->host->hw->data_buf[0] = wd; + _spi_transfer_start(disp_spi, 32, 0); } // Convert color to gray scale @@ -269,194 +207,219 @@ static color_t IRAM_ATTR color2gs(color_t color) return _color; } +// Convert color to 16-bit 565 RGB value +//---------------------------------------------- +static uint16_t IRAM_ATTR color16(color_t color) +{ + uint16_t _color; + _color = (uint16_t)(color.r & 0xF8) << 8; + _color |= (uint16_t)(color.g & 0xFC) << 3; + _color |= (uint16_t)(color.b & 0xF8) >> 3; + return _color; +} + +//====================================================== +esp_err_t IRAM_ATTR wait_trans_finish(uint8_t free_line) +{ + _wait_trans_finish(disp_spi); + + if ((free_line) && (trans_cline)) { + free(trans_cline); + trans_cline = NULL; + } + return ESP_OK; +} + // 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) { - if (!(disp_spi->cfg.flags & LB_SPI_DEVICE_HALFDUPLEX)) return; - - if (sel) { - if (disp_select()) return; - } - else wait_trans_finish(1); + if ((sel) && (disp_select() != ESP_OK)) return; uint32_t wd = 0; color_t _color = color; if (gray_scale) _color = color2gs(color); - taskDISABLE_INTERRUPTS(); + wait_trans_finish(1); disp_spi_transfer_addrwin(x, x+1, y, y+1); // Send RAM WRITE command - gpio_set_level(pin_dc, 0); - disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_RAMWR; - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7; - disp_spi->host->hw->cmd.usr = 1; // Start transfer - while (disp_spi->host->hw->cmd.usr); // Wait for SPI bus ready - - wd = (uint32_t)_color.r; - wd |= (uint32_t)_color.g << 8; - wd |= (uint32_t)_color.b << 16; + disp_spi_transfer_cmd(TFT_RAMWR); + if (bits_per_color == 16) { + uint16_t _color16 = color16(_color); + wd = (uint32_t)(_color16 >> 8); + wd |= (uint32_t)(_color16 & 0xFF) << 8; + } + else { + wd = (uint32_t)_color.r; + wd |= (uint32_t)_color.g << 8; + wd |= (uint32_t)_color.b << 16; + } + while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready // Set DC to 1 (data mode); - gpio_set_level(pin_dc, 1); + gpio_set_level(disp_spi->dc, 1); + disp_spi->handle->host->hw->data_buf[0] = wd; + _spi_transfer_start(disp_spi, bits_per_color, 0); - disp_spi->host->hw->data_buf[0] = wd; - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 23; - disp_spi->host->hw->cmd.usr = 1; // Start transfer - while (disp_spi->host->hw->cmd.usr); // Wait for SPI bus ready - - taskENABLE_INTERRUPTS(); - if (sel) disp_deselect(); -} - -//----------------------------------------------------------- -static void IRAM_ATTR _dma_send(uint8_t *data, uint32_t size) -{ - //Fill DMA descriptors - spi_lobo_dmaworkaround_transfer_active(disp_spi->host->dma_chan); //mark channel as active - spi_lobo_setup_dma_desc_links(disp_spi->host->dmadesc_tx, size, data, false); - disp_spi->host->hw->user.usr_mosi_highpart=0; - disp_spi->host->hw->dma_out_link.addr=(int)(&disp_spi->host->dmadesc_tx[0]) & 0xFFFFF; - disp_spi->host->hw->dma_out_link.start=1; - disp_spi->host->hw->user.usr_mosi_highpart=0; - - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = (size * 8) - 1; - - _dma_sending = 1; - // Start transfer - disp_spi->host->hw->cmd.usr = 1; + if (sel) disp_deselect(); } +// 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) { uint32_t cidx = 0; // color buffer index uint32_t wd = 0; + uint16_t _color16 = 0; int idx = 0; int bits = 0; int wbits = 0; - taskDISABLE_INTERRUPTS(); + // Get first color data from color buffer (repeat color) color_t _color = color[0]; if ((rep) && (gray_scale)) _color = color2gs(color[0]); + if (bits_per_color == 16) _color16 = color16(_color); while (len) { - // ** Get color data from color buffer ** if (rep == 0) { + // Get color data from color buffer if (gray_scale) _color = color2gs(color[cidx]); else _color = color[cidx]; + if (bits_per_color == 16) _color16 = color16(_color); } - wd |= (uint32_t)_color.r << wbits; - wbits += 8; - if (wbits == 32) { - bits += wbits; - wbits = 0; - disp_spi->host->hw->data_buf[idx++] = wd; - wd = 0; + if (bits_per_color == 16) { + wd |= (uint32_t)(_color16 >> 8) << wbits; + wbits += 8; + wd |= (uint32_t)(_color16 & 0xFF) << wbits; + wbits += 8; + if (wbits == 32) { + bits += wbits; + wbits = 0; + disp_spi->handle->host->hw->data_buf[idx++] = wd; + wd = 0; + } } - wd |= (uint32_t)_color.g << wbits; - wbits += 8; - if (wbits == 32) { - bits += wbits; - wbits = 0; - disp_spi->host->hw->data_buf[idx++] = wd; - wd = 0; + else { + wd |= (uint32_t)_color.r << wbits; + wbits += 8; + if (wbits == 32) { + bits += wbits; + wbits = 0; + disp_spi->handle->host->hw->data_buf[idx++] = wd; + wd = 0; + } + wd |= (uint32_t)_color.g << wbits; + wbits += 8; + if (wbits == 32) { + bits += wbits; + wbits = 0; + disp_spi->handle->host->hw->data_buf[idx++] = wd; + wd = 0; + } + wd |= (uint32_t)_color.b << wbits; + wbits += 8; + if (wbits == 32) { + bits += wbits; + wbits = 0; + disp_spi->handle->host->hw->data_buf[idx++] = wd; + wd = 0; + } } - wd |= (uint32_t)_color.b << wbits; - wbits += 8; - if (wbits == 32) { - bits += wbits; - wbits = 0; - disp_spi->host->hw->data_buf[idx++] = wd; - wd = 0; - } - len--; // Decrement colors counter - if (rep == 0) cidx++; // if not repeating color, increment color buffer index + len--; // Decrement colors counter + cidx++; // increment color buffer index (used only if not repeating color) } - if (bits) { - while (disp_spi->host->hw->cmd.usr); // Wait for SPI bus ready - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = bits-1; // set number of bits to be sent - disp_spi->host->hw->cmd.usr = 1; // Start transfer - } - taskENABLE_INTERRUPTS(); + if (bits) _spi_transfer_start(disp_spi, bits, 0); } -// ================================================================ -// === Main function to send data to display ====================== +// ================================================================== +// === Main function to send data to display ======================== // If rep==true: repeat sending color data to display 'len' times // 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) { if (len == 0) return; - if (!(disp_spi->cfg.flags & LB_SPI_DEVICE_HALFDUPLEX)) return; // Send RAM WRITE command - gpio_set_level(pin_dc, 0); - disp_spi->host->hw->data_buf[0] = (uint32_t)TFT_RAMWR; - disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7; - disp_spi->host->hw->cmd.usr = 1; // Start transfer - while (disp_spi->host->hw->cmd.usr); // Wait for SPI bus ready + disp_spi_transfer_cmd(TFT_RAMWR); + while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready - gpio_set_level(pin_dc, 1); // Set DC to 1 (data mode); - - if ((len*24) <= 512) { + gpio_set_level(disp_spi->dc, 1); // Set DC to 1 (data mode); + if ((len * bits_per_color) <= 512) { + // --- up to 512 bits, send directly --- _direct_send(color, len, rep); - } else if (rep == 0) { - // ==== use DMA transfer ==== - // ** Prepare data - if (gray_scale) { - for (int n=0; n> 8); + trans_cline16[(n*2)+1] = (uint8_t)(_color16 & 0xFF); + } + else trans_cline[n] = _color; + } + } + _dma_send(disp_spi, (uint8_t *)trans_cline, len * (bits_per_color/8)); } else { - // ==== Repeat color, more than 512 bits total ==== - + // --- more than 512 bits, repeat color --- + if (trans_cline) return; color_t _color; + uint16_t _color16 = 0; + uint8_t *trans_cline16 = NULL; uint32_t buf_colors; int buf_bytes, to_send; - /* - to_send = len; - while (to_send > 0) { - wait_trans_finish(0); - _direct_send(color, ((to_send > 21) ? 21 : to_send), rep); - to_send -= 21; - } - */ - + // Prepare color buffer of maximum 2 lines buf_colors = ((len > (_width*2)) ? (_width*2) : len); - buf_bytes = buf_colors * 3; + buf_bytes = buf_colors * (bits_per_color / 8); + int buflen = ((buf_bytes*8) + 31) / 8; - // Prepare color buffer of maximum 2 color lines - trans_cline = heap_caps_malloc(buf_bytes, MALLOC_CAP_DMA); + trans_cline = heap_caps_malloc(buflen, MALLOC_CAP_DMA); if (trans_cline == NULL) return; // Prepare fill color if (gray_scale) _color = color2gs(color[0]); else _color = color[0]; - + if (bits_per_color == 16) { + _color16 = color16(_color); + trans_cline16 = (uint8_t *)trans_cline; + } // Fill color buffer with fill color for (uint32_t i=0; i> 8); + trans_cline16[(i*2)+1] = (uint8_t)(_color16 & 0xFF); + } + else trans_cline[i] = _color; } // Send 'len' colors to_send = len; while (to_send > 0) { wait_trans_finish(0); - _dma_send((uint8_t *)trans_cline, ((to_send > buf_colors) ? buf_bytes : (to_send*3))); + _dma_send(disp_spi, (uint8_t *)trans_cline, ((to_send > buf_colors) ? buf_bytes : (to_send * (bits_per_color/8)))); to_send -= buf_colors; } } @@ -465,41 +428,64 @@ 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_nocs(int x1, int y1, int x2, int y2, color_t color, uint32_t len) +//========================================================================================== +void IRAM_ATTR 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; + // ** Send address window ** disp_spi_transfer_addrwin(x1, x2, y1, y2); + // Send repeated color and wait for all data sent _TFT_pushColorRep(&color, len, 1, 1); -} -// 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) -{ - if (disp_select() != ESP_OK) return; - TFT_pushColorRep_nocs(x1, y1, x2, y2, color, len); disp_deselect(); } // 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) +// === 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) { + wait_trans_finish(1); // ** Send address window ** disp_spi_transfer_addrwin(x1, x2, y1, y2); - _TFT_pushColorRep(buf, len, 0, 0); + + // Send color buffer + _TFT_pushColorRep(buf, len, 0, wait); +} + +//=================================================== +uint32_t IRAM_ATTR read_cmd(uint8_t cmd, uint8_t len) +{ + if (disp_select() != ESP_OK) return -2; + + // Send command command + disp_spi_transfer_cmd(cmd); + + while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + + // Read data; + gpio_set_level(disp_spi->dc, 1); + disp_spi->handle->host->hw->data_buf[0] = 0xFFFFFFFF; + + _spi_transfer_start(disp_spi, 0, len*8); + while (disp_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + + uint32_t res = disp_spi->handle->host->hw->data_buf[0]; + + disp_deselect(); + return res; } // 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) { - spi_lobo_transaction_t t; + spi_transaction_t t; uint32_t current_clock = 0; memset(&t, 0, sizeof(t)); //Zero out the transaction @@ -508,8 +494,8 @@ int IRAM_ATTR read_data(int x1, int y1, int x2, int y2, int len, uint8_t *buf, u if (set_sp) { if (disp_deselect() != ESP_OK) return -1; // Change spi clock if needed - current_clock = spi_lobo_get_speed(disp_spi); - if (max_rdclock < current_clock) spi_lobo_set_speed(disp_spi, max_rdclock); + current_clock = spi_get_speed(disp_spi); + if (max_rdclock < current_clock) spi_set_speed(disp_spi, max_rdclock); } if (disp_select() != ESP_OK) return -2; @@ -520,25 +506,25 @@ int IRAM_ATTR read_data(int x1, int y1, int x2, int y2, int len, uint8_t *buf, u // ** GET pixels/colors ** disp_spi_transfer_cmd(TFT_RAMRD); - t.length=0; //Send nothing - t.tx_buffer=NULL; - t.rxlength=8*((len*3)+1); //Receive size in bits - t.rx_buffer=buf; + t.length = 0; //Send nothing + t.tx_buffer = NULL; + t.rxlength = 8 * ((len*3)+1); //Receive size in bits + t.rx_buffer = buf; - esp_err_t res = spi_lobo_transfer_data(disp_spi, &t); // Receive using direct mode + esp_err_t res = spi_transfer_data_nodma(disp_spi, &t); // Receive using direct mode disp_deselect(); if (set_sp) { // Restore spi clock if needed - if (max_rdclock < current_clock) spi_lobo_set_speed(disp_spi, current_clock); + if (max_rdclock < current_clock) spi_set_speed(disp_spi, current_clock); } return res; } // Reads one pixel/color from the TFT's GRAM at position (x,y) -//----------------------------------------------- +//=============================================== color_t IRAM_ATTR readPixel(int16_t x, int16_t y) { uint8_t color_buf[sizeof(color_t)+1] = {0}; @@ -552,78 +538,73 @@ color_t IRAM_ATTR readPixel(int16_t x, int16_t y) return color; } -// ===== Touch controller support ========================================================== - -// ----- XPT2046 --------------------------------------------------------------------------- - // 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) { - /* - esp_err_t ret; - spi_lobo_transaction_t t; - memset(&t, 0, sizeof(t)); //Zero out the transaction - uint8_t rxdata[2] = {0}; + /* + while (ts_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready - // send command byte & receive 2 byte response - t.rxlength=8*2; - t.rx_buffer=&rxdata; - t.command = type; - - ret = spi_lobo_transfer_data(ts_spi, &t); // Transmit using direct mode - - if (ret != ESP_OK) return -1; - return (((int)(rxdata[0] << 8) | (int)(rxdata[1])) >> 4); - */ - spi_lobo_device_select(ts_spi, 0); - - ts_spi->host->hw->data_buf[0] = type; + ts_spi->handle->host->hw->data_buf[0] = type; _spi_transfer_start(ts_spi, 24, 24); - uint16_t res = (uint16_t)(ts_spi->host->hw->data_buf[0] >> 8); + uint16_t res = (uint16_t)(ts_spi->handle->host->hw->data_buf[0] >> 8); + while (ts_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + */ + spi_transaction_t t; + memset(&t, 0, sizeof(t)); //Zero out the transaction - spi_lobo_device_deselect(ts_spi); + uint32_t buf = type; + t.length = 24; + t.tx_buffer = (uint8_t *)&buf; + t.rxlength = 24; + t.rx_buffer = (uint8_t *)&buf; + esp_err_t ret = spi_transfer_data_nodma(ts_spi, &t); + if (ret != ESP_OK) return 0; + + uint16_t res = (uint16_t)(buf >> 8); return res; } +// ==== STMPE610 =============================================================== + + // ----- STMPE610 -------------------------------------------------------------------------- -// Send 1 byte display command, display must be selected -//--------------------------------------------------------- -static void IRAM_ATTR stmpe610_write_reg(uint8_t reg, uint8_t val) { - - spi_lobo_device_select(ts_spi, 0); - - ts_spi->host->hw->data_buf[0] = (val << 8) | reg; - _spi_transfer_start(ts_spi, 16, 0); - - spi_lobo_device_deselect(ts_spi); +//---------------------------------------------------------------- +static void IRAM_ATTR 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; + _spi_transfer_start(ts_spi, 16, 16); + while (ts_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + spi_device_deselect(ts_spi); } -//----------------------------------------------- -static uint8_t IRAM_ATTR stmpe610_read_byte(uint8_t reg) { - spi_lobo_device_select(ts_spi, 0); - - ts_spi->host->hw->data_buf[0] = (reg << 8) | (reg | 0x80); - _spi_transfer_start(ts_spi, 16, 16); - uint8_t res = ts_spi->host->hw->data_buf[0] >> 8; - - spi_lobo_device_deselect(ts_spi); +//------------------------------------------------------ +static uint8_t IRAM_ATTR stmpe610_read_byte(uint8_t reg) +{ + spi_device_select(ts_spi, 0); + ts_spi->handle->host->hw->data_buf[0] = (reg << 8) | (reg | 0x80); + _spi_transfer_start(ts_spi, 24, 24); + while (ts_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + uint8_t res = (uint8_t)(ts_spi->handle->host->hw->data_buf[0] >> 8); + spi_device_deselect(ts_spi); return res; } -//----------------------------------------- -static uint16_t IRAM_ATTR stmpe610_read_word(uint8_t reg) { - spi_lobo_device_select(ts_spi, 0); - - ts_spi->host->hw->data_buf[0] = ((((reg+1) << 8) | ((reg+1) | 0x80)) << 16) | (reg << 8) | (reg | 0x80); +//------------------------------------------------------- +static uint16_t IRAM_ATTR 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); _spi_transfer_start(ts_spi, 32, 32); - uint16_t res = (uint16_t)(ts_spi->host->hw->data_buf[0] & 0xFF00); - res |= (uint16_t)(ts_spi->host->hw->data_buf[0] >> 24); + while (ts_spi->handle->host->hw->cmd.usr); // Wait for SPI bus ready + uint16_t res = (uint16_t)(ts_spi->handle->host->hw->data_buf[0] & 0xFF00); + res |= (uint16_t)(ts_spi->handle->host->hw->data_buf[0] >> 24); + spi_device_deselect(ts_spi); - spi_lobo_device_deselect(ts_spi); return res; } @@ -638,6 +619,7 @@ uint32_t stmpe610_getID() //================== void stmpe610_Init() { + /* stmpe610_write_reg(STMPE610_REG_SYS_CTRL1, 0x02); // Software chip reset vTaskDelay(10 / portTICK_RATE_MS); @@ -645,7 +627,7 @@ void stmpe610_Init() stmpe610_write_reg(STMPE610_REG_INT_EN, 0x00); // Don't Interrupt on INT pin - stmpe610_write_reg(STMPE610_REG_ADC_CTRL1, 0x48); // ADC conversion time = 80 clock ticks, 12-bit ADC, internal voltage refernce + stmpe610_write_reg(STMPE610_REG_ADC_CTRL1, 0x48); // ADC conversion time = 80 clock ticks, 12-bit ADC, internal voltage reference vTaskDelay(2 / portTICK_RATE_MS); stmpe610_write_reg(STMPE610_REG_ADC_CTRL2, 0x01); // ADC speed 3.25MHz stmpe610_write_reg(STMPE610_REG_GPIO_AF, 0x00); // GPIO alternate function - OFF @@ -659,25 +641,70 @@ void stmpe610_Init() stmpe610_write_reg(STMPE610_REG_TSC_CTRL, 0x31); // X&Y&Z, 16 reading window, TSC enable stmpe610_write_reg(STMPE610_REG_INT_STA, 0xFF); // Clear all interrupts stmpe610_write_reg(STMPE610_REG_INT_CTRL, 0x00); // Level interrupt, disable interrupts + */ + + stmpe610_write_reg(STMPE610_REG_SYS_CTRL1, 0x02); // Software chip reset + vTaskDelay(10 / portTICK_RATE_MS); + stmpe610_write_reg(STMPE610_REG_SYS_CTRL2, 0x0); // turn on clocks! + vTaskDelay(2 / portTICK_RATE_MS); + stmpe610_write_reg(STMPE610_REG_TSC_CTRL, STMPE610_REG_TSC_CTRL_XYZ | STMPE610_REG_TSC_CTRL_EN); // XYZ and enable! + stmpe610_write_reg(STMPE610_REG_INT_EN, STMPE610_REG_INT_EN_TOUCHDET); + stmpe610_write_reg(STMPE610_REG_ADC_CTRL1, STMPE610_REG_ADC_CTRL1_10BIT | (0x6 << 4)); // 96 clocks per conversion + vTaskDelay(2 / portTICK_RATE_MS); + stmpe610_write_reg(STMPE610_REG_ADC_CTRL2, STMPE610_REG_ADC_CTRL2_6_5MHZ); + stmpe610_write_reg(STMPE610_REG_TSC_CFG, STMPE610_REG_TSC_CFG_4SAMPLE | STMPE610_REG_TSC_CFG_DELAY_1MS | STMPE610_REG_TSC_CFG_SETTLE_5MS); + stmpe610_write_reg(STMPE610_REG_TSC_FRACT_XYZ, 0x6); + stmpe610_write_reg(STMPE610_REG_FIFO_TH, 1); + stmpe610_write_reg(STMPE610_REG_FIFO_STA, STMPE610_REG_FIFO_STA_RESET); + stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0); // unreset + stmpe610_write_reg(STMPE610_REG_TSC_I_DRIVE, STMPE610_REG_TSC_I_DRIVE_50MA); + stmpe610_write_reg(STMPE610_REG_INT_STA, 0xFF); // reset all ints + stmpe610_write_reg(STMPE610_REG_INT_CTRL, STMPE610_REG_INT_CTRL_POL_HIGH | STMPE610_REG_INT_CTRL_ENABLE); +} + +//--------------------------------------------------------------- +static void stmpe_readData(uint32_t *x, uint32_t *y, uint32_t *z) +{ + uint8_t data[4]; + + data[0] = stmpe610_read_byte(STMPE610_REG_TSC_DATA); + data[1] = stmpe610_read_byte(STMPE610_REG_TSC_DATA); + data[2] = stmpe610_read_byte(STMPE610_REG_TSC_DATA); + data[3] = stmpe610_read_byte(STMPE610_REG_TSC_DATA); + + *x += ((data[0]) << 4) | (data[1] >> 4); + *y += ((data[1] & 0x0F) << 8) | data[2]; + *z += data[3]; + + if ((stmpe610_read_byte(STMPE610_REG_FIFO_STA) & STMPE610_REG_FIFO_STA_EMPTY)) { + stmpe610_write_reg(STMPE610_REG_INT_STA, 0xFF); // reset all interrupts + } } //=========================================================== int stmpe610_get_touch(uint16_t *x, uint16_t *y, uint16_t *z) { - if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) return 0; + /* + if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) return 0; + int n = 0; // Get touch data uint8_t fifo_size = stmpe610_read_byte(STMPE610_REG_FIFO_SIZE); while (fifo_size < 2) { if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) return 0; fifo_size = stmpe610_read_byte(STMPE610_REG_FIFO_SIZE); + n++; + if (n > 1000) return 0; } + n = 0; while (fifo_size > 120) { if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) return 0; *x = stmpe610_read_word(STMPE610_REG_TSC_DATA_X); *y = stmpe610_read_word(STMPE610_REG_TSC_DATA_Y); *z = stmpe610_read_byte(STMPE610_REG_TSC_DATA_Z); fifo_size = stmpe610_read_byte(STMPE610_REG_FIFO_SIZE); + n++; + if (n > 1000) return 0; } for (uint8_t i=0; i < (fifo_size-1); i++) { *x = stmpe610_read_word(STMPE610_REG_TSC_DATA_X); @@ -686,17 +713,41 @@ int stmpe610_get_touch(uint16_t *x, uint16_t *y, uint16_t *z) } *x = 4096 - *x; - /* // Clear the rest of the fifo - { - stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x01); // FIFO reset enable - stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x00); // FIFO reset disable - } + //{ + // stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x01); // FIFO reset enable + // stmpe610_write_reg(STMPE610_REG_FIFO_STA, 0x00); // FIFO reset disable + //} */ + + *x = 0; + *y = 0; + *z = 0; + if (!(stmpe610_read_byte(STMPE610_REG_TSC_CTRL) & 0x80)) { + // no touch data + return 0; + } + + int n = 0; + uint32_t tx = 0; + uint32_t ty = 0; + uint32_t tz = 0; + while (!((stmpe610_read_byte(STMPE610_REG_FIFO_STA) & STMPE610_REG_FIFO_STA_EMPTY))) { + stmpe_readData(&tx, &ty, &tz); + n++; + } + + if (n) { + // return the average values + *x = 4096 - (uint16_t)(tx / n); + *y = (uint16_t)(ty / n); + *z = (uint16_t)(tz / n); + } + return 1; } -// ========================================================================================= +// ==== STMPE610 =========================================================================== // Find maximum spi clock for successful read from display RAM @@ -714,9 +765,9 @@ uint32_t find_rd_speed() uint8_t gs = gray_scale; gray_scale = 0; - cur_speed = spi_lobo_get_speed(disp_spi); + cur_speed = spi_get_speed(disp_spi); - color_line = malloc(_width*3); + color_line = malloc(_width*3); if (color_line == NULL) goto exit; line_rdbuf = malloc((_width*3)+1); @@ -725,21 +776,21 @@ uint32_t find_rd_speed() color_t *rdline = (color_t *)(line_rdbuf+1); // Fill test line with colors - color = (color_t){0xEC,0xA8,0x74}; + color = (color_t){0xE8,0xAC,0x78}; for (int x=0; x<_width; x++) { color_line[x] = color; } // Find maximum read spi clock for (uint32_t speed=2000000; speed<=cur_speed; speed += 1000000) { - change_speed = spi_lobo_set_speed(disp_spi, speed); + change_speed = spi_set_speed(disp_spi, speed); if (change_speed == 0) goto exit; memset(line_rdbuf, 0, _width*sizeof(color_t)+1); if (disp_select()) goto exit; // Write color line - send_data(0, _height/2, _width-1, _height/2, _width, color_line); + send_data(0, _height/2, _width-1, _height/2, _width, color_line, 1); if (disp_deselect()) goto exit; // Read color line @@ -749,8 +800,8 @@ uint32_t find_rd_speed() line_check = 0; if (ret == ESP_OK) { for (int y=0; y<_width; y++) { - if ((color_line[y].g & 0xFC) != (rdline[y].g & 0xFC)) line_check = 1; - else if ((color_line[y].r & 0xFC) != (rdline[y].r & 0xFC)) line_check = 1; + if ((color_line[y].r & 0xFC) != (rdline[y].r & 0xFC)) line_check = 1; + else if ((color_line[y].g & 0xFC) != (rdline[y].g & 0xFC)) line_check = 1; else if ((color_line[y].b & 0xFC) != (rdline[y].b & 0xFC)) line_check = 1; if (line_check) break; } @@ -767,7 +818,7 @@ exit: if (color_line) free(color_line); // restore spi clk - change_speed = spi_lobo_set_speed(disp_spi, cur_speed); + change_speed = spi_set_speed(disp_spi, cur_speed); return max_speed; } @@ -775,28 +826,28 @@ exit: //--------------------------------------------------------------------------- // Companion code to the initialization table. // Reads and issues a series of LCD commands stored in byte array -//--------------------------------------------------------------------------- -static void commandList(spi_lobo_device_handle_t spi, const uint8_t *addr) { - uint8_t numCommands, numArgs, cmd; - uint16_t ms; +//-------------------------------------------- +static void commandList(const uint8_t *addr) { + uint8_t numCommands, numArgs, cmd; + uint16_t ms; - numCommands = *addr++; // Number of commands to follow - while (numCommands--) { // For each command... - cmd = *addr++; // save command - numArgs = *addr++; // Number of args to follow - ms = numArgs & TFT_CMD_DELAY; // If high bit set, delay follows args - numArgs &= ~TFT_CMD_DELAY; // Mask out delay bit + numCommands = *addr++; // Number of commands to follow + while(numCommands--) { // For each command... + cmd = *addr++; // save command + numArgs = *addr++; // Number of args to follow + ms = numArgs & TFT_CMD_DELAY; // If high bit set, delay follows args + numArgs &= ~TFT_CMD_DELAY; // Mask out delay bit - disp_spi_transfer_cmd_data(cmd, (uint8_t *)addr, numArgs); + disp_spi_transfer_cmd_data(cmd, (uint8_t *)addr, numArgs); - addr += numArgs; + addr += numArgs; - if (ms) { - ms = *addr++; // Read post-command delay time (ms) - if(ms == 255) ms = 500; // If 255, delay for 500 ms - vTaskDelay(ms / portTICK_RATE_MS); - } - } + if(ms) { + ms = *addr++; // Read post-command delay time (ms) + if(ms == 255) ms = 500; // If 255, delay for 500 ms + vTaskDelay(ms / portTICK_RATE_MS); + } + } } //================================== @@ -807,7 +858,7 @@ void _tft_setRotation(uint8_t rot) { uint16_t tmp; if ((rotation & 1)) { - // in landscape modes width > height + // in landscape modes must be width > height if (_width < _height) { tmp = _width; _width = _height; @@ -815,77 +866,77 @@ void _tft_setRotation(uint8_t rot) { } } else { - // in portrait modes width < height + // in portrait modes must be width < height if (_width > _height) { tmp = _width; _width = _height; _height = tmp; } } - if (_invert_rot == 1) { - switch (rotation) { - case PORTRAIT: - madctl = (MADCTL_MV | _rgb_bgr); - break; - case LANDSCAPE: - madctl = (MADCTL_MX | _rgb_bgr); - break; - case PORTRAIT_FLIP: - madctl = (MADCTL_MV | _rgb_bgr); - break; - case LANDSCAPE_FLIP: - madctl = (MADCTL_MY | _rgb_bgr); - break; - } + if (invertrot == 2) { + switch (rotation) { + case PORTRAIT: + madctl = (MADCTL_MV | TFT_RGB_BGR); + break; + case LANDSCAPE: + madctl = (MADCTL_MX | TFT_RGB_BGR); + break; + case PORTRAIT_FLIP: + madctl = (MADCTL_MV | TFT_RGB_BGR); + break; + case LANDSCAPE_FLIP: + madctl = (MADCTL_MY | TFT_RGB_BGR); + break; + } } - else if (_invert_rot == 2) { - switch (rotation) { - case PORTRAIT: - madctl = (MADCTL_MY | MADCTL_MX | _rgb_bgr); - break; - case LANDSCAPE: - madctl = (MADCTL_MY | MADCTL_MV | _rgb_bgr); - break; - case PORTRAIT_FLIP: - madctl = (_rgb_bgr); - break; - case LANDSCAPE_FLIP: - madctl = (MADCTL_MX | MADCTL_MV | _rgb_bgr); - break; - } + else if (invertrot == 3) { + // used for M5Stack display + switch (rotation) { + case PORTRAIT: + madctl = (MADCTL_MX | MADCTL_MV | TFT_RGB_BGR); + break; + case LANDSCAPE: + madctl = (TFT_RGB_BGR); + break; + case PORTRAIT_FLIP: + madctl = (MADCTL_MY | MADCTL_MV | TFT_RGB_BGR); + break; + case LANDSCAPE_FLIP: + madctl = (MADCTL_MY | MADCTL_MX | TFT_RGB_BGR); + break; + } } - else if (_invert_rot == 3) { - // used for M5Stack display - switch (rotation) { - case PORTRAIT: - madctl = (MADCTL_MX | MADCTL_MV | _rgb_bgr); - break; - case LANDSCAPE: - madctl = (_rgb_bgr); - break; - case PORTRAIT_FLIP: - madctl = (MADCTL_MY | MADCTL_MV | _rgb_bgr); - break; - case LANDSCAPE_FLIP: - madctl = (MADCTL_MY | MADCTL_MX | _rgb_bgr); - break; - } + else if (invertrot == 1) { + switch (rotation) { + case PORTRAIT: + madctl = (MADCTL_MY | MADCTL_MX | TFT_RGB_BGR); + break; + case LANDSCAPE: + madctl = (MADCTL_MY | MADCTL_MV | TFT_RGB_BGR); + break; + case PORTRAIT_FLIP: + madctl = (TFT_RGB_BGR); + break; + case LANDSCAPE_FLIP: + madctl = (MADCTL_MX | MADCTL_MV | TFT_RGB_BGR); + break; + } } else { - switch (rotation) { - case PORTRAIT: - madctl = (MADCTL_MX | _rgb_bgr); - break; - case LANDSCAPE: - madctl = (MADCTL_MV | _rgb_bgr); - break; - case PORTRAIT_FLIP: - madctl = (MADCTL_MY | _rgb_bgr); - break; - case LANDSCAPE_FLIP: - madctl = (MADCTL_MX | MADCTL_MY | MADCTL_MV | _rgb_bgr); - break; - } + switch (rotation) { + case PORTRAIT: + madctl = (MADCTL_MX | TFT_RGB_BGR); + break; + case LANDSCAPE: + madctl = (MADCTL_MV | TFT_RGB_BGR); + break; + case PORTRAIT_FLIP: + madctl = (MADCTL_MY | TFT_RGB_BGR); + break; + case LANDSCAPE_FLIP: + madctl = (MADCTL_MX | MADCTL_MY | MADCTL_MV | TFT_RGB_BGR); + break; + } } if (send) { if (disp_select() == ESP_OK) { @@ -896,69 +947,300 @@ void _tft_setRotation(uint8_t rot) { } -//-------------- -void bcklOff() { - if (pin_bckl >= 0) gpio_set_level(pin_bckl, (bckl_on&1) ^ 1); +//--------------------------------------- +void bcklOff(display_config_t *dconfig) { + if (dconfig->bckl >= 0) { + gpio_set_level(dconfig->bckl, (dconfig->bckl_on & 1) ^ 1); + } } -//------------- -void bcklOn() { - if (pin_bckl >= 0) gpio_set_level(pin_bckl, bckl_on&1); +//-------------------------------------- +void bcklOn(display_config_t *dconfig) { + if (dconfig->bckl >= 0) { + gpio_set_level(dconfig->bckl, dconfig->bckl_on & 1); + } +} + +//=========================================== +void _tft_setBitsPerColor(uint8_t bitsperc) { + if ((tft_disp_type != DISP_TYPE_ILI9488) && ((bitsperc == 16) || (bitsperc == 24))) { + uint8_t bpc = DISP_COLOR_BITS_16; + if (bitsperc == 24) bpc = DISP_COLOR_BITS_24; + if (disp_select() == ESP_OK) { + disp_spi_transfer_cmd_data(TFT_CMD_PIXFMT, &bpc, 1); + disp_deselect(); + } + bits_per_color = bitsperc; + } +} + +//-------------------------------------------------------- +static void TFT_PinsInit(display_config_t *dconfig) +{ + // Route all used pins to GPIO control + if (!spibus_is_init) { + gpio_pad_select_gpio(dconfig->miso); + 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_pad_select_gpio(dconfig->dc); + + gpio_set_direction(dconfig->cs, GPIO_MODE_OUTPUT); + gpio_set_direction(dconfig->dc, GPIO_MODE_OUTPUT); + + gpio_set_level(dconfig->dc, 0); + gpio_set_level(dconfig->cs, 1); + if (dconfig->touch != TOUCH_TYPE_NONE) { + gpio_pad_select_gpio(dconfig->tcs); + gpio_set_direction(dconfig->tcs, GPIO_MODE_OUTPUT); + gpio_set_level(dconfig->tcs, 1); + } + if (dconfig->bckl >= 0) { + gpio_pad_select_gpio(dconfig->bckl); + gpio_set_direction(dconfig->bckl, GPIO_MODE_OUTPUT); + gpio_set_level(dconfig->bckl, dconfig->bckl_on ^ 1); + } + if (dconfig->rst >= 0) { + gpio_pad_select_gpio(dconfig->rst); + gpio_set_direction(dconfig->rst, GPIO_MODE_OUTPUT); + gpio_set_level(dconfig->rst, 0); + } +} + +//----------------------------------------------------- +static esp_err_t TFT_spiInit(display_config_t *dconfig) +{ + esp_err_t ret; + + int used_spi = spi_host_used_by_sdspi(); + if ((used_spi != 0) && (used_spi == dconfig->host)) { + // change spi host + if (used_spi == VSPI_HOST) disp_spi->spihost = HSPI_HOST; + else disp_spi->spihost = VSPI_HOST; + ESP_LOGW(TAG, "spi bus changed (%d -> %d)", used_spi, disp_spi->spihost); + } + else disp_spi->spihost = dconfig->host; + + disp_spi->buscfg = SPIbus_configs[disp_spi->spihost]; + if (disp_spi->buscfg == NULL) { + ESP_LOGE(TAG, "spi bus %d not available ", disp_spi->spihost); + return ESP_ERR_INVALID_ARG; + } + + disp_spi->dma_channel = 1; + disp_spi->curr_clock = 8000000; // for initialization set the clock to 8MHz + disp_spi->handle = NULL; + disp_spi->cs = dconfig->cs; + disp_spi->dc = dconfig->dc; + disp_spi->selected = 0; + + disp_spi->buscfg->miso_io_num = dconfig->miso; // set SPI MISO pin + disp_spi->buscfg->mosi_io_num = dconfig->mosi; // set SPI MOSI pin + disp_spi->buscfg->sclk_io_num = dconfig->sck; // set SPI CLK pin + disp_spi->buscfg->quadwp_io_num = -1; + disp_spi->buscfg->quadhd_io_num = -1; + disp_spi->buscfg->max_transfer_sz = 6*1024; + + disp_spi->devcfg.clock_speed_hz = disp_spi->curr_clock; // Initial clock + disp_spi->devcfg.duty_cycle_pos = 128; // 50% duty cycle + disp_spi->devcfg.mode=0; // SPI mode 0 + disp_spi->devcfg.spics_io_num = -1; // we will use external CS pin + disp_spi->devcfg.queue_size=1; // we need only one transaction + disp_spi->devcfg.flags=SPI_DEVICE_HALFDUPLEX; // ALWAYS SET to HALF DUPLEX MODE!! for display spi + + if (dconfig->touch != TOUCH_TYPE_NONE) { + ts_spi->spihost = disp_spi->spihost; // Use the same spi bus as display + ts_spi->buscfg = SPIbus_configs[ts_spi->spihost]; + + ts_spi->dma_channel = 1; + ts_spi->handle = NULL; + ts_spi->cs = dconfig->tcs; // external CS + ts_spi->dc = -1; + ts_spi->selected = 0; + + if (dconfig->touch == TOUCH_TYPE_STMPE610) { + ts_spi->curr_clock = 1000000; + ts_spi->devcfg.clock_speed_hz = 1000000; // Clock 1 MHz + ts_spi->devcfg.mode = STMPE610_SPI_MODE; // SPI mode 1 + } + else { + ts_spi->curr_clock = 2500000; + ts_spi->devcfg.clock_speed_hz = 2500000; // Clock 2.5 MHz + ts_spi->devcfg.mode = 0; //SPI mode 0 + } + + ts_spi->devcfg.duty_cycle_pos = 128; // 50% duty cycle + ts_spi->devcfg.spics_io_num = -1; // External Touch CS pin (dconfig->tcs) + ts_spi->devcfg.queue_size = 1; // we need only one transaction + ts_spi->devcfg.flags = 0; + } + + // ================================================================== + // ==== Initialize the SPI bus and attach the LCD to the SPI bus ==== + ret = add_extspi_device(disp_spi); + if (ret != ESP_OK) { + return ret; + } + + ESP_LOGD(TAG, "spi bus configured (%d)", disp_spi->spihost); + + + // ==== Test select/deselect ==== + ret = spi_device_select(disp_spi, 1); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error selecting display device"); + } + vTaskDelay(10 / portTICK_RATE_MS); + ret = spi_device_deselect(disp_spi); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error deselecting display device"); + } + + ESP_LOGI(TAG, "attached display device, speed=%u", spi_get_speed(disp_spi)); + ESP_LOGI(TAG, "bus uses native pins: %s", spi_uses_native_pins(disp_spi->handle) ? "true" : "false"); + + if (dconfig->touch != TOUCH_TYPE_NONE) { + // ===================================================== + // ==== Attach the touch screen to the same SPI bus ==== + + ret = add_extspi_device(ts_spi); + if (ret == ESP_OK) { + ESP_LOGD(TAG, "touch screen device added to spi bus (%d)", disp_spi->spihost); + + // ==== Test select/deselect ==== + ret = spi_device_select(ts_spi, 1); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error selecting touch device"); + } + ret = spi_device_deselect(ts_spi); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error deselecting touch device"); + } + + ESP_LOGD(TAG, "attached TS device, speed=%u", spi_get_speed(ts_spi)); + if (dconfig->touch == TOUCH_TYPE_STMPE610) { + stmpe610_Init(); + vTaskDelay(10 / portTICK_RATE_MS); + uint32_t tver = stmpe610_getID(); + ESP_LOGW(TAG, "STMPE touch initialized, ver: %04x - %02x", tver >> 8, tver & 0xFF); + } + } + else { + ESP_LOGE(TAG, "Error adding touch device to spi bus"); + ts_spi->handle = NULL; + dconfig->touch = TOUCH_TYPE_NONE; + } + } + return ESP_OK; +} + +//================================================= +void TFT_display_setvars(display_config_t *dconfig) +{ + // === SET GLOBAL VARIABLES ========================== + tft_disp_type = dconfig->type; + tft_touch_type = dconfig->touch; + _width = dconfig->width; + _height = dconfig->height; + // ==== Set maximum spi clock for display read ==== + // operations, function 'find_rd_speed()' ==== + // can be used after display initialization ==== + max_rdclock = dconfig->rdspeed; + TFT_RGB_BGR = dconfig->bgr; + gamma_curve = dconfig->gamma; + spi_speed = dconfig->speed; + bits_per_color = dconfig->color_bits; + invertrot = dconfig->invrot; + // =================================================== } // Initialize the display -// ==================== -void TFT_display_init() +// ================================================== +esp_err_t TFT_display_init(display_config_t *dconfig) { - bcklOff(); + esp_err_t ret; + TFT_PinsInit(dconfig); + ret = TFT_spiInit(dconfig); + if (ret != ESP_OK) return ret; - if (pin_rst >= 0) { - // Reset the display - gpio_set_level(pin_rst, 0); - vTaskDelay(20 / portTICK_RATE_MS); - gpio_set_level(pin_rst, 1); - vTaskDelay(150 / portTICK_RATE_MS); - disp_select(); + TFT_display_setvars(dconfig); + + if (dconfig->rst >= 0) { + //Reset the display + gpio_set_level(dconfig->rst, 0); + vTaskDelay(20 / portTICK_RATE_MS); + gpio_set_level(dconfig->rst, 1); + vTaskDelay(150 / portTICK_RATE_MS); } - else { - // Soft reset - disp_select(); - disp_spi_transfer_cmd_data(TFT_CMD_SWRESET, NULL, 0); - vTaskDelay(200 / portTICK_RATE_MS); - } + else { + disp_spi_transfer_cmd_data(TFT_CMD_SWRESET, NULL, 0); + vTaskDelay(200 / portTICK_RATE_MS); + } + + disp_select(); //Send all the initialization commands - if (tft_disp_type == DISP_TYPE_ILI9341) { - commandList(disp_spi, ILI9341_init); - } - else if (tft_disp_type == DISP_TYPE_ILI9488) { - commandList(disp_spi, ILI9488_init); - } - else if (tft_disp_type == DISP_TYPE_ST7789V) { - commandList(disp_spi, ST7789V_init); - } - else if (tft_disp_type == DISP_TYPE_ST7735) { - commandList(disp_spi, STP7735_init); - } - else if (tft_disp_type == DISP_TYPE_ST7735R) { - commandList(disp_spi, STP7735R_init); - commandList(disp_spi, Rcmd2green); - commandList(disp_spi, Rcmd3); - } - else if (tft_disp_type == DISP_TYPE_ST7735B) { - commandList(disp_spi, STP7735R_init); - commandList(disp_spi, Rcmd2red); - commandList(disp_spi, Rcmd3); - uint8_t dt = 0xC0; - disp_select(); - disp_spi_transfer_cmd_data(TFT_MADCTL, &dt, 1); - } + if ((tft_disp_type == DISP_TYPE_ILI9341) || (tft_disp_type == DISP_TYPE_M5STACK)) { + if (dconfig->rst < 0) { + vTaskDelay(50 / portTICK_RATE_MS); + } + commandList(ILI9341_init); + _tft_setBitsPerColor(bits_per_color); + } + else if (tft_disp_type == DISP_TYPE_ILI9488) { + commandList(ILI9488_init); + } + else if (tft_disp_type == DISP_TYPE_ST7789V) { + commandList(ST7789V_init); + _tft_setBitsPerColor(bits_per_color); + } + else if (tft_disp_type == DISP_TYPE_ST7735) { + commandList(STP7735_init); + } + else if (tft_disp_type == DISP_TYPE_ST7735R) { + commandList(STP7735R_init); + commandList(Rcmd2green); + commandList(Rcmd3); + } + else if (tft_disp_type == DISP_TYPE_ST7735B) { + commandList(STP7735R_init); + commandList(Rcmd2red); + commandList(Rcmd3); + uint8_t dt = 0xC0; + disp_spi_transfer_cmd_data(TFT_MADCTL, &dt, 1); + } + else if (tft_disp_type == DISP_TYPE_GENERIC) { + ESP_LOGW(TAG, "Generic display type, you must init the display manually"); + ///Enable backlight + if (dconfig->bckl >= 0) { + gpio_set_level(dconfig->bckl, dconfig->bckl_on); + } + return ESP_OK; + } + else { + ESP_LOGE(TAG, "Display type %d not supported", tft_disp_type); + disp_deselect(); + return ESP_FAIL; + } disp_deselect(); - // Clear screen + // Clear screen _tft_setRotation(PORTRAIT); - TFT_pushColorRep(0, 0, _width-1, _height-1, (color_t){0,0,0}, (uint32_t)(_height*_width)); + TFT_pushColorRep(0, 0, _width-1, _height-1, (color_t){0,0,0}, (uint32_t)(_height*_width)); + + ///Enable backlight + if (dconfig->bckl >= 0) { + gpio_set_level(dconfig->bckl, dconfig->bckl_on); + } + return ESP_OK; } diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h index e7a0d39..a841999 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/tft/tftspi.h @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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 Boris Lovosevic (https://github/loboris) + * 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 @@ -23,14 +23,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - /* - * Author: LoBo, 08/2017 - * - * Library supporting SPI TFT displays based on ILI9341, ILI9488 & ST7789V controllers * - * HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS - * USING DIRECT or DMA SPI TRANSFER MODEs + * HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS USING DIRECT TRANSFER MODE * */ @@ -38,11 +33,58 @@ #define _TFTSPI_H_ #include "tftspi.h" -#include "spi_master_lobo.h" +//#include "driver/spi_master.h" +//#include "driver/spi_master_internal.h" +#include "driver/spi_master_utils.h" #include "sdkconfig.h" #include "stmpe610.h" -// === Various display constants constants === +typedef struct { + uint32_t speed; // SPI clock in Hz + uint32_t rdspeed; // Read SPI clock in Hz + uint8_t type; // Display type, use one of the defined DISP_TYPE_* values + 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 + uint8_t dc; // Display DC pin (command/data) + int8_t tcs; // Touch screen CS pin + int8_t rst; // GPIO used for RESET control + int8_t bckl; // GPIO used for backlight control + uint8_t bckl_on; // GPIO value for backlight ON + uint8_t color_bits; // Bits per color (16 or 24) + uint8_t gamma; // Gamma curve used + uint16_t width; // Display width (smaller dimension) + uint16_t height; // Display height (larger dimension) + uint8_t invrot; // rotation + uint8_t bgr; // SET TO 0X00 FOR DISPLAYS WITH RGB MATRIX, 0x08 FOR DISPLAYS WITH BGR MATRIX + uint8_t touch; // Touch panel type +} display_config_t; + +// 24-bit color type structure +typedef struct __attribute__((__packed__)) { + uint8_t r; + uint8_t g; + uint8_t b; +} color_t ; + + +#define DISP_COLOR_BITS_24 0x66 +#define DISP_COLOR_BITS_16 0x55 +#define DISP_COLOR_BITS DISP_COLOR_BITS_16 + +#define TOUCH_TYPE_NONE 0 +#define TOUCH_TYPE_XPT2046 1 +#define TOUCH_TYPE_STMPE610 2 + +#define TP_CALX_XPT2046 7472920 +#define TP_CALY_XPT2046 122224794 + +#define TP_CALX_STMPE610 21368532 +#define TP_CALY_STMPE610 11800144 + +// === Screen orientation constants === #define PORTRAIT 0 #define LANDSCAPE 1 #define PORTRAIT_FLIP 2 @@ -54,31 +96,80 @@ #define DISP_TYPE_ST7735 3 #define DISP_TYPE_ST7735R 4 #define DISP_TYPE_ST7735B 5 -#define DISP_TYPE_MAX 6 - -#define DISP_COLOR_BITS_24 0x66 -//#define DISP_COLOR_BITS_16 0x55 - -#define DISP_COLOR_BITS_24 0x66 -#define TFT_RGB_BGR 0x00 // default only, set when initializing the display - -// Pins defaults (ESP32-WROVER-KIT v3) -#define PIN_NUM_MISO 25 // SPI MISO -#define PIN_NUM_MOSI 23 // SPI MOSI -#define PIN_NUM_CLK 19 // SPI CLOCK pin -#define PIN_NUM_CS 22 // Display CS pin -#define PIN_NUM_DC 21 // Display command/data pin -#define PIN_NUM_TCS 0 // Touch screen CS pin -//#define PIN_NUM_RST 18 // GPIO used for RESET control -//#define PIN_NUM_BCKL 5 // GPIO used for backlight control -//#define PIN_BCKL_ON 0 // GPIO value for backlight ON -//#define PIN_BCKL_OFF 1 // GPIO value for backlight OFF +#define DISP_TYPE_M5STACK 6 +#define DISP_TYPE_GENERIC 7 +#define DISP_TYPE_MAX 8 #define DEFAULT_TFT_DISPLAY_WIDTH 240 #define DEFAULT_TFT_DISPLAY_HEIGHT 320 -#define DEFAULT_GAMMA_CURVE 0 -#define DEFAULT_SPI_CLOCK 26000000 -#define DEFAULT_DISP_TYPE DISP_TYPE_ST7789V +#define DEFAULT_DISP_TYPE DISP_TYPE_ILI9341 + + +#define WROVER_V3_CONFIG() {\ + .type = DISP_TYPE_ST7789V, \ + .host = HSPI_HOST, \ + .speed = 26000000, \ + .miso = 25, \ + .mosi = 23, \ + .sck = 19, \ + .cs = 22, \ + .dc = 21, \ + .tcs = -1, \ + .rst = 18, \ + .bckl = 5, \ + .bckl_on = 0, \ + .color_bits = 24, \ + .gamma = 0, \ + .width = 240, \ + .height = 320, \ + .invrot = 1, \ + .bgr = 0, \ + .touch = TOUCH_TYPE_NONE \ +} + +#define ADAFRUIT_TFT_FEATHER_CONFIG() {\ + .type = DISP_TYPE_ILI9341, \ + .host = HSPI_HOST, \ + .speed = 26000000, \ + .miso = 19, \ + .mosi = 18, \ + .sck = 5, \ + .cs = 15, \ + .dc = 33, \ + .tcs = 32, \ + .rst = -1, \ + .bckl = -1, \ + .bckl_on = 0, \ + .color_bits = 16, \ + .gamma = 0, \ + .width = 240, \ + .height = 320, \ + .invrot = 0, \ + .bgr = 8, \ + .touch = TOUCH_TYPE_STMPE610 \ +} + +#define DISPLAY_CONFIG_DEFAULT() { \ + .type = DISP_TYPE_ILI9341, \ + .host = HSPI_HOST, \ + .speed = 26000000, \ + .miso = 19, \ + .mosi = 23, \ + .sck = 18, \ + .cs = 5, \ + .dc = 26, \ + .tcs = -1, \ + .rst = -1, \ + .bckl = -1, \ + .bckl_on = 0, \ + .color_bits = 16, \ + .gamma = 0, \ + .width = 240, \ + .height = 320, \ + .invrot = 0, \ + .bgr = 8, \ + .touch = TOUCH_TYPE_NONE \ +} // ############################################################## @@ -95,32 +186,22 @@ extern uint32_t max_rdclock; extern int _width; extern int _height; -// ==== Display type, DISP_TYPE_ILI9488 or DISP_TYPE_ILI9341 ==== +// ==== Display & touch type ==== extern uint8_t tft_disp_type; +extern uint8_t tft_touch_type; // ==== Spi device handles for display and touch screen ========= -extern spi_lobo_device_handle_t disp_spi; -extern spi_lobo_device_handle_t ts_spi; +extern exspi_device_handle_t *disp_spi; +extern exspi_device_handle_t *ts_spi; -extern uint8_t pin_dc; -extern int8_t pin_bckl; -extern uint8_t bckl_on; -extern int8_t pin_rst; - -extern uint8_t _invert_rot; -extern uint8_t _rgb_bgr; +extern uint8_t bits_per_color; +extern uint8_t TFT_RGB_BGR; +extern uint8_t gamma_curve; +extern uint32_t spi_speed; +extern uint8_t spibus_is_init; // ############################################################## - -// 24-bit color type structure -typedef struct __attribute__((__packed__)) { -//typedef struct { - uint8_t r; - uint8_t g; - uint8_t b; -} color_t ; - // ==== Display commands constants ==== #define TFT_INVOFF 0x20 #define TFT_INVONN 0x21 @@ -227,7 +308,7 @@ typedef struct __attribute__((__packed__)) { #define TFT_CMD_DELAY 0x80 -// Initialization sequence for ILI7341 +// Initialization sequence for ILI7749 // ==================================== static const uint8_t ST7789V_init[] = { 15, // 15 commands in list @@ -242,8 +323,8 @@ static const uint8_t ST7789V_init[] = { ST_CMD_PWCTR1, 2, 0xA4, 0xA1, TFT_CMD_GMCTRP1, 14, 0xD0, 0x00, 0x05, 0x0E, 0x15, 0x0D, 0x37, 0x43, 0x47, 0x09, 0x15, 0x12, 0x16, 0x19, TFT_CMD_GMCTRN1, 14, 0xD0, 0x00, 0x05, 0x0D, 0x0C, 0x06, 0x2D, 0x44, 0x40, 0x0E, 0x1C, 0x18, 0x16, 0x19, - TFT_MADCTL, 1, (MADCTL_MX | TFT_RGB_BGR), // Memory Access Control (orientation) - TFT_CMD_PIXFMT, 1, DISP_COLOR_BITS_24, // *** INTERFACE PIXEL FORMAT: 0x66 -> 18 bit; 0x55 -> 16 bit + TFT_MADCTL, 1, (MADCTL_MX | 8), // Memory Access Control (orientation) + TFT_CMD_PIXFMT, 1, DISP_COLOR_BITS_16, // *** INTERFACE PIXEL FORMAT: 0x66 -> 18 bit; 0x55 -> 16 bit TFT_CMD_SLPOUT, TFT_CMD_DELAY, 120, // Sleep out, // 120 ms delay TFT_DISPON, TFT_CMD_DELAY, 120, }; @@ -251,7 +332,7 @@ static const uint8_t ST7789V_init[] = { // Initialization sequence for ILI7341 // ==================================== static const uint8_t ILI9341_init[] = { - 23, // 24 commands in list + 23, // 22 commands in list TFT_CMD_POWERA, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, TFT_CMD_POWERB, 3, 0x00, 0XC1, 0X30, 0xEF, 3, 0x03, 0x80, 0x02, @@ -263,10 +344,10 @@ static const uint8_t ILI9341_init[] = { TFT_CMD_PWCTR2, 1, 0x10, //Power control SAP[2:0];BT[3:0] TFT_CMD_VMCTR1, 2, 0x3e, 0x28, //VCM control TFT_CMD_VMCTR2, 1, 0x86, //VCM control2 - TFT_MADCTL, 1, // Memory Access Control (orientation) - (MADCTL_MX | TFT_RGB_BGR), + TFT_MADCTL, 1, (MADCTL_MX | 8), // Memory Access Control (orientation) + // *** INTERFACE PIXEL FORMAT: 0x66 -> 18 bit; 0x55 -> 16 bit - TFT_CMD_PIXFMT, 1, DISP_COLOR_BITS_24, + TFT_CMD_PIXFMT, 1, DISP_COLOR_BITS_16, TFT_INVOFF, 0, TFT_CMD_FRMCTR1, 2, 0x00, 0x18, TFT_CMD_DFUNCTR, 4, 0x08, 0x82, 0x27, 0x00, // Display Function Control @@ -274,12 +355,12 @@ static const uint8_t ILI9341_init[] = { TFT_CMD_3GAMMA_EN, 1, 0x00, // 3Gamma Function: Disable (0x02), Enable (0x03) TFT_CMD_GAMMASET, 1, 0x01, //Gamma curve selected (0x01, 0x02, 0x04, 0x08) TFT_CMD_GMCTRP1, 15, //Positive Gamma Correction - 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, + 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, TFT_CMD_GMCTRN1, 15, //Negative Gamma Correction - 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, + 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, TFT_CMD_SLPOUT, TFT_CMD_DELAY, // Sleep out - 120, // 120 ms delay - TFT_DISPON, TFT_CMD_DELAY, 120, + 200, // 120 ms delay + TFT_DISPON, TFT_CMD_DELAY, 200, }; // Initialization sequence for ILI9488 @@ -288,34 +369,66 @@ static const uint8_t ILI9488_init[] = { 17, // 17 commands in list 0xE0, 15, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F, 0xE1, 15, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F, - 0xC0, 2, 0x17, 0x15, //Power Control 1 (Vreg1out & Verg2out) - 0xC1, 1, 0x41, //Power Control 2 (VGH,VGL) - 0xC5, 3, 0x00, 0x12, 0x80, //Power Control 3 (Vcomm) - TFT_MADCTL, 1, (MADCTL_MX | TFT_RGB_BGR), // Memory Access Control (orientation), set to portrait + 0xC0, 2, //Power Control 1 + 0x17, //Vreg1out + 0x15, //Verg2out + + 0xC1, 1, //Power Control 2 + 0x41, //VGH,VGL + + 0xC5, 3, //Power Control 3 + 0x00, + 0x12, //Vcom + 0x80, + + TFT_MADCTL, 1, MADCTL_MX, // Memory Access Control (orientation), set to portrait + // *** INTERFACE PIXEL FORMAT: 0x66 -> 18 bit; TFT_CMD_PIXFMT, 1, DISP_COLOR_BITS_24, - 0xB0, 1, 0x00, // Interface Mode Control: 0x80: SDO NOT USE; 0x00 USE SDO - 0xB1, 1, 0xA0, //Frame rate: 60Hz - 0xB4, 1, 0x02, //Display Inversion Control:2-dot - 0xB6, 2, 0x02, 0x02, //Display Function Control RGB/MCU Interface Control (MCU, Source,Gate scan direction) - 0xE9, 1, 0x00, // Set Image Function: Disable 24 bit data - 0x53, 1, 0x28, // Write CTRL Display Value: BCTRL && DD on - 0x51, 1, 0x7F, // Write Display Brightness Value - 0xF7, 4, 0xA9, 0x51, 0x2C, 0x02, // Adjust Control: D7 stream, loose - 0x11, TFT_CMD_DELAY, 120, //Exit Sleep - 0x29, 0, //Display on + + 0xB0, 1, // Interface Mode Control + 0x00, // 0x80: SDO NOT USE; 0x00 USE SDO + + 0xB1, 1, //Frame rate + 0xA0, //60Hz + + 0xB4, 1, //Display Inversion Control + 0x02, //2-dot + + 0xB6, 2, //Display Function Control RGB/MCU Interface Control + 0x02, //MCU + 0x02, //Source,Gate scan direction + + 0xE9, 1, // Set Image Function + 0x00, // Disable 24 bit data + + 0x53, 1, // Write CTRL Display Value + 0x28, // BCTRL && DD on + + 0x51, 1, // Write Display Brightness Value + 0x7F, // + + 0xF7, 4, // Adjust Control + 0xA9, + 0x51, + 0x2C, + 0x02, // D7 stream, loose + + + 0x11, TFT_CMD_DELAY, //Exit Sleep + 120, + 0x29, 0, //Display on }; + // Initialization commands for 7735B screens // ------------------------------------ static const uint8_t STP7735_init[] = { - 17, // 18 commands in list: - ST7735_SLPOUT , TFT_CMD_DELAY, // 2: Out of sleep mode, no args, w/delay - 255, // 255 = 500 ms delay - TFT_CMD_PIXFMT , 1+TFT_CMD_DELAY, // 3: Set color mode, 1 arg + delay: - 1, 0x06, // 18-bit color 6-6-6 color format - 10, // 10 ms delay + 16, // 16 commands in list + TFT_CMD_PIXFMT, 1+TFT_CMD_DELAY, // 3: Set color mode, 1 arg + delay: + 0x06, // 18-bit color 6-6-6 color format + 10, // 10 ms delay ST7735_FRMCTR1, 3+TFT_CMD_DELAY, // 4: Frame rate control, 3 args + delay: 0x00, // fastest refresh 0x06, // 6 lines front porch @@ -370,9 +483,7 @@ static const uint8_t STP7735_init[] = { // Init for 7735R, part 1 (red or green tab) // -------------------------------------- static const uint8_t STP7735R_init[] = { - 15, // 15 commands in list: - ST7735_SWRESET, TFT_CMD_DELAY, // 1: Software reset, 0 args, w/delay - 150, // 150 ms delay + 14, // 14 commands in list ST7735_SLPOUT , TFT_CMD_DELAY, // 2: Out of sleep mode, 0 args, w/delay 255, // 500 ms delay ST7735_FRMCTR1, 3 , // 3: Frame rate ctrl - normal mode, 3 args: @@ -456,21 +567,23 @@ static const uint8_t Rcmd3[] = { // ==== Public functions ========================================================= // == Low level functions; usually not used directly == - esp_err_t wait_trans_finish(uint8_t free_line); void disp_spi_transfer_cmd(int8_t cmd); void disp_spi_transfer_cmd_data(int8_t cmd, uint8_t *data, uint32_t len); void drawPixel(int16_t x, int16_t y, color_t color, uint8_t sel); -void send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t *buf); -void TFT_pushColorRep_nocs(int x1, int y1, int x2, int y2, color_t data, uint32_t len); +void send_data(int x1, int y1, int x2, int y2, uint32_t len, color_t *buf, uint8_t wait); void TFT_pushColorRep(int x1, int y1, int x2, int y2, color_t data, uint32_t len); int read_data(int x1, int y1, int x2, int y2, int len, uint8_t *buf, uint8_t set_sp); +uint32_t read_cmd(uint8_t cmd, uint8_t len); color_t readPixel(int16_t x, int16_t y); int touch_get_data(uint8_t type); +void bcklOn(display_config_t *dconfig); +void bcklOff(display_config_t *dconfig); -void bcklOff(); -void bcklOn(); +void TFT_display_setvars(display_config_t *dconfig); + +void _tft_setBitsPerColor(uint8_t bitsperc); // Deactivate display's CS line //======================== @@ -494,10 +607,8 @@ void _tft_setRotation(uint8_t rot); // Perform display initialization sequence // Sets orientation to landscape; clears the screen -// * SPI interface must already be setup -// * 'tft_disp_type', 'COLOR_BITS', '_width', '_height' variables must be set -//====================== -void TFT_display_init(); +//============================================================ +esp_err_t TFT_display_init(display_config_t *display_config); //=================== void stmpe610_Init(); @@ -508,6 +619,7 @@ int stmpe610_get_touch(uint16_t *x, uint16_t *y, uint16_t *z); //======================== uint32_t stmpe610_getID(); + // =============================================================================== #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/libs/websrv.c b/MicroPython_BUILD/components/micropython/esp32/libs/websrv.c index 31b7f3e..0a53b76 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/websrv.c +++ b/MicroPython_BUILD/components/micropython/esp32/libs/websrv.c @@ -1,16 +1,9 @@ /* - * This file is based on 'ftp' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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/esp32/libs/websrv.h b/MicroPython_BUILD/components/micropython/esp32/libs/websrv.h index 576a59d..2e13a09 100644 --- a/MicroPython_BUILD/components/micropython/esp32/libs/websrv.h +++ b/MicroPython_BUILD/components/micropython/esp32/libs/websrv.h @@ -1,16 +1,9 @@ /* - * This file is based on 'ftp' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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/esp32/machine_adc.c b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c index 4786edd..331e77e 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_adc.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_adc.c @@ -1,9 +1,10 @@ /* - * 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 @@ -32,6 +33,8 @@ #include "driver/gpio.h" #include "driver/adc.h" #include "esp_adc_cal.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/sens_reg.h" #include "py/runtime.h" #include "py/mphal.h" diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_dht.c b/MicroPython_BUILD/components/micropython/esp32/machine_dht.c index b79c4a0..8965fd1 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_dht.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_dht.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/esp32/machine_hw_i2c.c b/MicroPython_BUILD/components/micropython/esp32/machine_hw_i2c.c index 7f32c10..d8b31f7 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_hw_i2c.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_hw_i2c.c @@ -1,20 +1,9 @@ /* - * This file is derived from the MicroPython project, http://micropython.org/ - * - * Copyright (c) 2016, Pycom Limited and its licensors. - * - * This software is licensed under the GNU GPL version 3 or any later version, - * with permitted additional terms. For more information see the Pycom Licence - * v1.0 document supplied with this file, or available at: - * https://www.pycom.io/opensource/licensing - */ - -/* - * 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) 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 @@ -50,29 +39,46 @@ #include "driver/gpio.h" #include "driver/periph_ctrl.h" -#define I2C_MASTER_TX_BUF_DISABLE 0 // I2C master does not need buffer -#define I2C_MASTER_RX_BUF_DISABLE 0 // I2C master does not need buffer #define I2C_ACK_CHECK_EN (1) -#define I2C_ACK_VAL (0) -#define I2C_NACK_VAL (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) -typedef struct _machine_hw_i2c_obj_t { +typedef struct _mp_machine_i2c_obj_t { mp_obj_base_t base; uint32_t speed; + uint8_t mode; uint8_t scl; uint8_t sda; int8_t bus_id; i2c_cmd_handle_t cmd; -} machine_hw_i2c_obj_t; - - -STATIC const uint8_t mach_i2c_def_pin[2] = {12, 13}; + uint16_t rx_buflen; // low level commands receive buffer length + uint16_t rx_bufidx; // low level commands receive buffer index + 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 +} mp_machine_i2c_obj_t; const mp_obj_type_t machine_hw_i2c_type; -//------------------------------------------------------------------ -STATIC void hw_i2c_initialise_master (machine_hw_i2c_obj_t *i2c_obj) +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 }; + + +// ============================================================================================ +// === 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; @@ -84,70 +90,49 @@ STATIC void hw_i2c_initialise_master (machine_hw_i2c_obj_t *i2c_obj) conf.master.clk_speed = i2c_obj->speed; i2c_param_config(i2c_obj->bus_id, &conf); - i2c_driver_install(i2c_obj->bus_id, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); + return i2c_driver_install(i2c_obj->bus_id, I2C_MODE_MASTER, 0, 0, 0); } -//------------------------------------------------------------------------------------------------------------------------------------------------------------ -STATIC void hw_i2c_master_writeto(machine_hw_i2c_obj_t *i2c_obj, uint16_t slave_addr, bool memwrite, uint32_t memaddr, uint8_t *data, uint16_t len, bool stop) +//-------------------------------------------------------- +STATIC esp_err_t i2c_init_slave (mp_machine_i2c_obj_t *i2c_obj) { - esp_err_t ret = ESP_FAIL; + i2c_config_t conf; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + conf.mode = I2C_MODE_SLAVE; + conf.sda_io_num = i2c_obj->sda; + conf.scl_io_num = i2c_obj->scl; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.slave.addr_10bit_en = 0; + conf.slave.slave_addr = i2c_obj->slave_addr; - if (i2c_master_start(cmd) != ESP_OK) goto error; - if (i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN) != ESP_OK) goto error; - - if (memwrite) { - if (memaddr > 0xFF) { - if (i2c_master_write_byte(cmd, (memaddr >> 8), I2C_ACK_CHECK_EN) != ESP_OK) goto error; - } - if (i2c_master_write_byte(cmd, memaddr, I2C_ACK_CHECK_EN) != ESP_OK) goto error; - } - - if (i2c_master_write(cmd, data, len, I2C_ACK_CHECK_EN) != ESP_OK) goto error; - if (stop) { - if (i2c_master_stop(cmd) != ESP_OK) goto error; - } - - ret = i2c_master_cmd_begin(i2c_obj->bus_id, cmd, (5000 + (1000 * len)) / portTICK_RATE_MS); - -error: - i2c_cmd_link_delete(cmd); - - if (ret != ESP_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); - } + 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); } -//------------------------------------------------------------------------------------------------------------------------------------------------- -STATIC void hw_i2c_master_readfrom(machine_hw_i2c_obj_t *i2c_obj, uint16_t slave_addr, bool memread, uint32_t memaddr, uint8_t *data, uint16_t len) +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +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) { esp_err_t ret = ESP_FAIL; i2c_cmd_handle_t cmd = i2c_cmd_link_create(); if (i2c_master_start(cmd) != ESP_OK) {ret=1; goto error;}; + // send slave address + if (i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN) != ESP_OK) {ret=2; goto error;}; - if (memread) { - if (i2c_master_write_byte(cmd, ( slave_addr << 1 ) | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN) != ESP_OK) {ret=2; goto error;}; - if (memaddr > 0xFF) { - if (i2c_master_write_byte(cmd, (memaddr >> 8), I2C_ACK_CHECK_EN) != ESP_OK) {ret=3; goto error;}; - } - if (i2c_master_write_byte(cmd, memaddr, I2C_ACK_CHECK_EN) != ESP_OK) {ret=4; goto error;}; - - // repeated start - if (i2c_master_start(cmd) != ESP_OK) {ret=5; goto error;}; + while (memwrite > 0) { + // send memory address, MSByte first + memwrite--; + if (i2c_master_write_byte(cmd, (memaddr >> (memwrite*8)), I2C_ACK_CHECK_EN) != ESP_OK) {ret=3; goto error;}; } - if (i2c_master_write_byte(cmd, ( slave_addr << 1 ) | I2C_MASTER_READ, I2C_ACK_CHECK_EN) != ESP_OK) {ret=6; goto error;}; - - if (len > 1) { - if (i2c_master_read(cmd, data, len - 1, I2C_ACK_VAL) != ESP_OK) {ret=7; goto error;}; + // send data + 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;}; } - if (i2c_master_read_byte(cmd, data + len - 1, I2C_NACK_VAL) != ESP_OK) {ret=8; goto error;}; - if (i2c_master_stop(cmd) != ESP_OK) {ret=8; goto error;}; - ret = i2c_master_cmd_begin(i2c_obj->bus_id, cmd, (5000 + (1000 * len)) / portTICK_RATE_MS); error: @@ -160,8 +145,68 @@ error: } } -//-------------------------------------------------------------------------------- -STATIC bool hw_i2c_slave_ping (machine_hw_i2c_obj_t *i2c_obj, uint16_t slave_addr) +//----------------------------------------------------------------------------------------------------------------------------------------------------------- +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) +{ + esp_err_t ret = ESP_FAIL; + + memset(data, 0xFF, len); + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + + if (i2c_master_start(cmd) != ESP_OK) {ret=1; goto error;}; + + if (memread) { + // send slave address + if (i2c_master_write_byte(cmd, ( slave_addr << 1 ) | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN) != ESP_OK) {ret=2; goto error;}; + + if (memread > 0) { + // send memory address, MSByte first + while (memread > 0) { + // send memory address, MSByte first + memread--; + if (i2c_master_write_byte(cmd, (memaddr >> (memread*8)), I2C_ACK_CHECK_EN) != ESP_OK) {ret=3; goto error;}; + } + + if (stop) { + // Finish the write transaction + if (i2c_master_stop(cmd) != ESP_OK) {ret=5; goto error;}; + if (i2c_master_cmd_begin(i2c_obj->bus_id, cmd, 100 / portTICK_RATE_MS) != ESP_OK) {ret=6; goto error;}; + i2c_cmd_link_delete(cmd); + // Start the read transaction + cmd = i2c_cmd_link_create(); + if (i2c_master_start(cmd) != ESP_OK) {ret=7; goto error;}; + } + else { + // repeated start, generate START signal, slave address will be send next + if (i2c_master_start(cmd) != ESP_OK) {ret=4; goto error;}; + } + } + } + + // READ, send slave address + if (i2c_master_write_byte(cmd, ( slave_addr << 1 ) | I2C_MASTER_READ, I2C_ACK_CHECK_EN) != ESP_OK) {ret=8; goto error;}; + + if (len > 1) { + if (i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK) != ESP_OK) {ret=9; goto error;}; + } + + if (i2c_master_read_byte(cmd, data + len - 1, I2C_MASTER_NACK) != ESP_OK) {ret=10; goto error;}; + if (i2c_master_stop(cmd) != ESP_OK) {ret=11; goto error;}; + + ret = i2c_master_cmd_begin(i2c_obj->bus_id, cmd, (5000 + (1000 * len)) / portTICK_RATE_MS); + +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)); + } +} + +//---------------------------------------------------------------------------------- +STATIC bool hw_i2c_slave_detect (mp_machine_i2c_obj_t *i2c_obj, uint16_t slave_addr) { esp_err_t ret = ESP_FAIL; @@ -179,194 +224,447 @@ error: } -/******************************************************************************/ -// MicroPython bindings for I2C +// ============================================================================================ +// === I2C MicroPython bindings =============================================================== +// ============================================================================================ -//----------------------------------------------------------------------------------------------- -STATIC void machine_hw_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) -{ - machine_hw_i2c_obj_t *self = self_in; - mp_printf(print, "I2C(Port=%u, Mode=MASTER, speed=%uHz, sda=GPIO_NUM_%d, scl=GPIO_NUM_%d)", self->bus_id, self->speed, self->sda, self->scl); -} +enum { ARG_id, ARG_mode, ARG_speed, ARG_freq, ARG_sda, ARG_scl, ARG_slaveaddr, ARG_slavebuflen }; -//--------------------------------------------------------- -STATIC const mp_arg_t machine_hw_i2c_init_allowed_args[] = { - { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_mode, MP_ARG_INT, {.u_int = I2C_MODE_MASTER} }, - { MP_QSTR_speed, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, - { 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} }, +//---------------------------------------------------------- +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_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +//--------------------------------------------------------------------------------------- +STATIC void _sched_callback(mp_obj_t function, int cmd, int addr, int len, uint8_t *sarg) { - enum { ARG_id, ARG_mode, ARG_speed, ARG_freq, ARG_sda, ARG_scl }; + 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); +} - mp_arg_val_t args[MP_ARRAY_SIZE(machine_hw_i2c_init_allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(machine_hw_i2c_init_allowed_args), machine_hw_i2c_init_allowed_args, args); +//-------------------------------------------- +STATIC void i2c_slave_task(void *pvParameters) +{ + 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); +} + +//---------------------------------- +STATIC void _checkAddr(uint8_t addr) +{ + if ((addr < 0x08) || (addr > 0x77)) { + mp_raise_ValueError("Wrong i2c address (0x08 - 0x77 allowed)"); + } +} + +//-------------------------------------------------- +STATIC void _checkMaster(mp_machine_i2c_obj_t *self) +{ + if (self->mode != I2C_MODE_MASTER) { + mp_raise_ValueError("I2C not in MASTER mode)"); + } +} + +//------------------------------------------------- +STATIC void _checkSlave(mp_machine_i2c_obj_t *self) +{ + if (self->mode != I2C_MODE_SLAVE) { + mp_raise_ValueError("I2C not in SLAVE mode)"); + } +} + +//----------------------------------------------------------------------------------------------- +STATIC void mp_machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ + mp_machine_i2c_obj_t *self = self_in; + if (i2c_used[self->bus_id] >= 0) { + 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])); + } + } + } + else { + mp_printf(print, "I2C (Deinitialized)"); + } +} + +//--------------------------------------------------------------------------------------------------------------- +mp_obj_t mp_machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) +{ + mp_arg_val_t args[MP_ARRAY_SIZE(mp_machine_i2c_init_allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(mp_machine_i2c_init_allowed_args), mp_machine_i2c_init_allowed_args, args); int8_t sda; int8_t scl; + int32_t speed; int8_t bus_id = args[ARG_id].u_int; - uint32_t speed; + if (bus_id < 0) bus_id = I2C_NUM_0; + if (args[ARG_freq].u_int > 0) speed = args[ARG_freq].u_int; else speed = args[ARG_speed].u_int; + if (speed < 0) speed = 100000; // Check the peripheral id if (bus_id < 0 || bus_id > 1) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus not available")); } + if (i2c_used[bus_id] >= 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus already used")); + } // Check mode - if (args[ARG_mode].u_int != I2C_MODE_MASTER) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Only I2C MASTER mode available for now")); + 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")); } - if (args[ARG_sda].u_obj == MP_OBJ_NULL) { - sda = mach_i2c_def_pin[0]; - } else { - sda = machine_pin_get_id(args[ARG_sda].u_obj); + sda = machine_pin_get_gpio(args[ARG_sda].u_obj); + scl = machine_pin_get_gpio(args[ARG_scl].u_obj); + + // Create I2C object + mp_machine_i2c_obj_t *self = m_new_obj(mp_machine_i2c_obj_t ); + self->base.type = &machine_hw_i2c_type; + self->mode = mode; + self->bus_id = bus_id; + self->speed = speed; + self->scl = scl; + self->sda = sda; + self->cmd = NULL; + self->rx_buflen = 0; + self->rx_bufidx = 0; + self->rx_data = NULL; + self->slave_buflen = 0; + self->slave_addr = 0; + self->slave_data = NULL; + self->slave_cb_read = NULL; + self->slave_cb_write = NULL; + self->slave_cb_data = NULL; + + if (mode == I2C_MODE_MASTER) { + // Setup I2C master + if (i2c_init_master(self) != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error installing I2C driver")); + } } - if (args[ARG_scl].u_obj == MP_OBJ_NULL) { - scl = mach_i2c_def_pin[1]; - } else { - scl = machine_pin_get_id(args[ARG_scl].u_obj); + else { + if (slave_mutex == NULL) { + slave_mutex = xSemaphoreCreateMutex(); + } + // Set I2C slave address + if (args[ARG_slaveaddr].u_int > 0) { + _checkAddr(args[ARG_slaveaddr].u_int); + self->slave_addr = args[ARG_slaveaddr].u_int; + } + 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)) + 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 (i2c_init_slave(self) != ESP_OK) { + free(self->slave_data); + self->slave_data = NULL; + 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]); + } } - // Setup the I2C object - machine_hw_i2c_obj_t *self = m_new_obj(machine_hw_i2c_obj_t ); - self->base.type = &machine_hw_i2c_type; - self->bus_id = bus_id; - self->speed = speed; - self->scl = scl; - self->sda = sda; - - hw_i2c_initialise_master(self); + i2c_used[bus_id] = mode; return MP_OBJ_FROM_PTR(self); } //------------------------------------------------------------------------------------------------ -STATIC mp_obj_t machine_hw_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +STATIC mp_obj_t mp_machine_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - machine_hw_i2c_obj_t *self = pos_args[0]; - enum { ARG_id, ARG_mode, ARG_speed, ARG_freq, ARG_sda, ARG_scl }; + mp_machine_i2c_obj_t *self = pos_args[0]; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_hw_i2c_init_allowed_args)]; - mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(machine_hw_i2c_init_allowed_args), machine_hw_i2c_init_allowed_args, 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; + int32_t speed; + uint8_t changed = 0; + + int8_t old_bus_id = self->bus_id; int8_t bus_id = args[ARG_id].u_int; - uint32_t speed; + if (bus_id < 0) bus_id = self->bus_id; + if (args[ARG_freq].u_int > 0) speed = args[ARG_freq].u_int; else speed = args[ARG_speed].u_int; - uint8_t changed = 0; + if (speed < 0) speed = self->speed; // Check the peripheral id if (bus_id < 0 || bus_id > 1) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus not available")); } // Check mode - if (args[ARG_mode].u_int != I2C_MODE_MASTER) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Only I2C MASTER mode available for now")); + int mode = args[ARG_mode].u_int; + if ((mode >= 0) && (mode != self->mode)) { + 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")); + } + changed++; + } + else mode = self->mode; + + scl = self->scl; + sda = self->sda; + + if (args[ARG_sda].u_obj != MP_OBJ_NULL) { + sda = machine_pin_get_gpio(args[ARG_sda].u_obj); + } + if (args[ARG_scl].u_obj != MP_OBJ_NULL) { + scl = machine_pin_get_gpio(args[ARG_scl].u_obj); } - if (args[ARG_sda].u_obj == MP_OBJ_NULL) { - sda = mach_i2c_def_pin[0]; - } else { - sda = machine_pin_get_id(args[ARG_sda].u_obj); - } - if (args[ARG_scl].u_obj == MP_OBJ_NULL) { - scl = mach_i2c_def_pin[1]; - } else { - scl = machine_pin_get_id(args[ARG_scl].u_obj); - } - - if (self->bus_id != bus_id) changed++; + // Check if the configuration changed + if (old_bus_id != bus_id) changed++; if (self->speed != speed) changed++; 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 (changed) { - if (self->speed > 0) i2c_driver_delete(self->bus_id); + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + if (i2c_used[old_bus_id] >= 0) { + i2c_driver_delete(old_bus_id); + i2c_used[old_bus_id] = -1; + } + if (i2c_used[bus_id] >= 0) { + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreGive(slave_mutex); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus already used")); + } self->bus_id = bus_id; self->speed = speed; self->scl = scl; self->sda = sda; - hw_i2c_initialise_master(self); + if (mode == I2C_MODE_MASTER) { + if (i2c_init_master(self) != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error installing I2C driver")); + } + } + 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); + 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]); + } + } + i2c_used[bus_id] = mode; + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreGive(slave_mutex); } - return MP_OBJ_FROM_PTR(self); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_i2c_init_obj, 1, machine_hw_i2c_init); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_init_obj, 1, mp_machine_i2c_init); //--------------------------------------------------- -STATIC mp_obj_t machine_hw_i2c_scan(mp_obj_t self_in) +STATIC mp_obj_t mp_machine_i2c_scan(mp_obj_t self_in) { - machine_hw_i2c_obj_t *self = self_in; + mp_machine_i2c_obj_t *self = self_in; + _checkMaster(self); + mp_obj_t list = mp_obj_new_list(0, NULL); - // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved + // don't include in scan the reserved 7-bit addresses: 0x00-0x07 & 0x78-0x7F - for (int addr = 0x08; addr <= 0x78; ++addr) { - if (hw_i2c_slave_ping(self, addr)) { + for (int addr = 0x08; addr < 0x78; ++addr) { + if (hw_i2c_slave_detect(self, addr)) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); } } return list; } -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_i2c_scan_obj, machine_hw_i2c_scan); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_scan_obj, mp_machine_i2c_scan); //---------------------------------------------------------------------------------------------------- -STATIC mp_obj_t machine_hw_i2c_readfrom(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +STATIC mp_obj_t mp_machine_i2c_readfrom(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { STATIC const mp_arg_t machine_i2c_readfrom_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, }; - machine_hw_i2c_obj_t *self = pos_args[0]; + mp_machine_i2c_obj_t *self = pos_args[0]; + _checkMaster(self); - // parse args + // parse arguments mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_readfrom_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), machine_i2c_readfrom_args, args); + _checkAddr(args[0].u_int); + vstr_t vstr; vstr_init_len(&vstr, args[1].u_int); - hw_i2c_master_readfrom(self, args[0].u_int, false, 0, (uint8_t*)vstr.buf, vstr.len); + 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); } -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_i2c_readfrom_obj, 1, machine_hw_i2c_readfrom); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_readfrom_obj, 1, mp_machine_i2c_readfrom); -//----------------------------------------------------------------------------------------------------------- -STATIC mp_obj_t machine_hw_i2c_readfrom_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - machine_hw_i2c_obj_t *self = pos_args[0]; +//--------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_readfrom_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + mp_machine_i2c_obj_t *self = pos_args[0]; + _checkMaster(self); STATIC const mp_arg_t machine_i2c_readfrom_into_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; - // parse args + // parse arguments mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_readfrom_into_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), machine_i2c_readfrom_into_args, args); + _checkAddr(args[0].u_int); + mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1].u_obj, &bufinfo, MP_BUFFER_WRITE); - hw_i2c_master_readfrom(self, args[0].u_int, false, 0, bufinfo.buf, bufinfo.len); + mp_i2c_master_read(self, args[0].u_int, false, 0, bufinfo.buf, bufinfo.len, false); + // Return read length return mp_obj_new_int(bufinfo.len); } -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_i2c_readfrom_into_obj, 1, machine_hw_i2c_readfrom_into); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_readfrom_into_obj, 1, mp_machine_i2c_readfrom_into); -//----------------------------------------------------------------------------------------------------- -STATIC mp_obj_t machine_hw_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - machine_hw_i2c_obj_t *self = pos_args[0]; +//--------------------------------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + mp_machine_i2c_obj_t *self = pos_args[0]; + _checkMaster(self); STATIC const mp_arg_t machine_i2c_writeto_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, @@ -374,165 +672,525 @@ STATIC mp_obj_t machine_hw_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_arg { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; - // parse args + // parse arguments mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_writeto_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), machine_i2c_writeto_args, args); + _checkAddr(args[0].u_int); + mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1].u_obj, &bufinfo, MP_BUFFER_READ); - hw_i2c_master_writeto(self, args[0].u_int, false, 0x0, bufinfo.buf, bufinfo.len, args[2].u_bool); + mp_i2c_master_write(self, args[0].u_int, 0, 0, bufinfo.buf, bufinfo.len, args[2].u_bool); return mp_obj_new_int(bufinfo.len); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_i2c_writeto_obj, 1, machine_hw_i2c_writeto); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_writeto_obj, 1, mp_machine_i2c_writeto); + //--------------------------------------------------------- -STATIC const mp_arg_t machine_hw_i2c_mem_allowed_args[] = { - { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, +STATIC const mp_arg_t mp_machine_i2c_mem_allowed_args[] = { + { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_adrlen, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, }; -//------------------------------------------------------------------------------------------------------- -STATIC mp_obj_t machine_hw_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_n }; - machine_hw_i2c_obj_t *self = pos_args[0]; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_hw_i2c_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(machine_hw_i2c_mem_allowed_args), machine_hw_i2c_mem_allowed_args, args); +//--------------------------------------------- +uint8_t getMemAdrLen(int memlen, uint32_t addr) +{ + if ((memlen < 1) || (memlen > 4)) { + mp_raise_ValueError("Memory address length error, 1 - 4 allowed"); + } + uint8_t len = 1; + if (addr > 0xFF) len++; + if (addr > 0xFFFF) len++; + if (addr > 0xFFFFFF) len++; + if (memlen > len) len = memlen; + return len; +} +//----------------------------------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_addr, ARG_memaddr, ARG_n, ARG_memlen, ARG_stop }; + mp_machine_i2c_obj_t *self = pos_args[0]; + _checkMaster(self); + + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(mp_machine_i2c_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(mp_machine_i2c_mem_allowed_args), mp_machine_i2c_mem_allowed_args, args); + + _checkAddr(args[ARG_addr].u_int); + + // Get read length int n = mp_obj_get_int(args[ARG_n].u_obj); if (n > 0) { - // create the buffer to store data into + 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 vstr_t vstr; vstr_init_len(&vstr, n); - // do the transfer - //uint8_t addr = args[ARG_memaddr].u_int; - //hw_i2c_master_writeto(self, args[0].u_int, false, 0x0, &addr, 1, true); - //hw_i2c_master_readfrom(self, args[0].u_int, false, 0, (uint8_t*)vstr.buf, vstr.len); - hw_i2c_master_readfrom(self, args[ARG_addr].u_int, true, args[ARG_memaddr].u_int, (uint8_t *)vstr.buf, vstr.len); + // 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); + // Return read data as string return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } + // Return empty string return mp_const_empty_bytes; } -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_i2c_readfrom_mem_obj, 1, machine_hw_i2c_readfrom_mem); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_readfrom_mem_obj, 1, mp_machine_i2c_readfrom_mem); -//------------------------------------------------------------------------------------------------------------ -STATIC mp_obj_t machine_hw_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_buf }; - machine_hw_i2c_obj_t *self = pos_args[0]; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_hw_i2c_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(machine_hw_i2c_mem_allowed_args), machine_hw_i2c_mem_allowed_args, args); +//---------------------------------------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_memlen, ARG_stop }; + mp_machine_i2c_obj_t *self = pos_args[0]; + _checkMaster(self); - // get the buffer to store data into + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(mp_machine_i2c_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(mp_machine_i2c_mem_allowed_args), mp_machine_i2c_mem_allowed_args, args); + + _checkAddr(args[ARG_addr].u_int); + + // Get the output data buffer mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); if (bufinfo.len > 0) { - // do the transfer - hw_i2c_master_readfrom(self, args[ARG_addr].u_int, true, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len); + 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); } return mp_obj_new_int(bufinfo.len); } -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_i2c_readfrom_mem_into_obj, 1, machine_hw_i2c_readfrom_mem_into); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_readfrom_mem_into_obj, 1, mp_machine_i2c_readfrom_mem_into); -//------------------------------------------------------------------------------------------------------ -STATIC mp_obj_t machine_hw_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_buf }; - machine_hw_i2c_obj_t *self = pos_args[0]; - mp_arg_val_t args[MP_ARRAY_SIZE(machine_hw_i2c_mem_allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(machine_hw_i2c_mem_allowed_args), machine_hw_i2c_mem_allowed_args, args); +//---------------------------------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_memlen }; + mp_machine_i2c_obj_t *self = pos_args[0]; + _checkMaster(self); - // get the buffer to write the data from + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(mp_machine_i2c_mem_allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(mp_machine_i2c_mem_allowed_args), mp_machine_i2c_mem_allowed_args, args); + + _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); - // do the transfer - hw_i2c_master_writeto(self, args[ARG_addr].u_int, true, args[ARG_memaddr].u_int, 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); + // Transfer data from buffer + mp_i2c_master_write(self, args[ARG_addr].u_int, memlen, addr, bufinfo.buf, bufinfo.len, true); return mp_obj_new_int(bufinfo.len); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_i2c_writeto_mem_obj, 1, machine_hw_i2c_writeto_mem); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_i2c_writeto_mem_obj, 1, mp_machine_i2c_writeto_mem); //------------------------------------------------------- -STATIC mp_obj_t machine_hw_i2c_deinit(mp_obj_t self_in) { - machine_hw_i2c_obj_t *self = self_in; +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->speed > 0) { i2c_driver_delete(self->bus_id); - // invalidate the speed - self->speed = 0; + i2c_used[self->bus_id] = -1; + if (self->slave_data) free(self->slave_data); + self->slave_data = NULL; + + if ((self->mode == I2C_MODE_SLAVE) && (slave_mutex)) xSemaphoreGive(slave_mutex); } return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_i2c_deinit_obj, machine_hw_i2c_deinit); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_deinit_obj, mp_machine_i2c_deinit); -/* + +// ============================================================================================ +// ==== Low level MicroPython I2C commands ==================================================== +// ============================================================================================ + +//------------------------------------------------- +static void _checkBegin(mp_machine_i2c_obj_t *self) +{ + _checkMaster(self); + if (self->cmd == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C: command before begin!")); + } +} + +// Begin i2c transaction +//------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_begin(mp_obj_t self_in, mp_obj_t rxlen_in) { + mp_machine_i2c_obj_t *self = self_in; + _checkMaster(self); + + int rxbuflen = mp_obj_get_int(rxlen_in); + if ((rxbuflen < 0) || (rxbuflen > I2C_RX_MAX_BUFF_LEN)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Buffer length error")); + } + + if (self->cmd != NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C: 2nd begin before end not allowed!")); + } + + if (self->rx_data) free(self->rx_data); + self->rx_data = NULL; + if (rxbuflen) { + self->rx_data = malloc(rxbuflen); + if (self->rx_data == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Error allocating rx buffer")); + } + } + self->rx_buflen = rxbuflen; + self->rx_bufidx = 0; + + self->cmd = i2c_cmd_link_create(); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_i2c_begin_obj, mp_machine_i2c_begin); + +// Queue start command //------------------------------------------------------ -STATIC mp_obj_t machine_hw_i2c_start(mp_obj_t self_in) { - machine_hw_i2c_obj_t *self = self_in; +STATIC mp_obj_t mp_machine_i2c_start(mp_obj_t self_in) { + mp_machine_i2c_obj_t *self = self_in; - if (self->cmd == NULL) { - self->cmd = i2c_cmd_link_create(); - } + _checkBegin(self); + + // Queue start command if (i2c_master_start(self->cmd) != ESP_OK) { - i2c_cmd_link_delete(self->cmd); - self->cmd = NULL; - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Start command error")); } return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_i2c_start_obj, machine_hw_i2c_start); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_start_obj, mp_machine_i2c_start); +// Queue slave address +//------------------------------------------------------------------------------------------ +STATIC mp_obj_t mp_machine_i2c_address(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t rw_in) { + mp_machine_i2c_obj_t *self = self_in; + + _checkBegin(self); + + uint8_t slave_addr = mp_obj_get_int(addr_in); + uint8_t rw = mp_obj_get_int(rw_in) & 1; // 0 -> write, 1 -> read + + _checkAddr(slave_addr); + + // Queue slave address + if (i2c_master_write_byte(self->cmd, (slave_addr << 1) | rw, I2C_ACK_CHECK_EN) != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Address write error")); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_i2c_address_obj, mp_machine_i2c_address); + +// Queue stop command //----------------------------------------------------- -STATIC mp_obj_t machine_hw_i2c_stop(mp_obj_t self_in) { - machine_hw_i2c_obj_t *self = self_in; +STATIC mp_obj_t mp_machine_i2c_stop(mp_obj_t self_in) { + mp_machine_i2c_obj_t *self = self_in; + + _checkBegin(self); - if (self->cmd == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C: stop before start!")); - } if (i2c_master_stop(self->cmd) != ESP_OK) { - i2c_cmd_link_delete(self->cmd); - self->cmd = NULL; - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Stop command error")); } - i2c_cmd_link_delete(self->cmd); - self->cmd = NULL; return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_i2c_stop_obj, machine_hw_i2c_stop); -*/ +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_stop_obj, mp_machine_i2c_stop); + +//---------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_write_byte(mp_obj_t self_in, mp_obj_t val_in) { + mp_machine_i2c_obj_t *self = self_in; + + _checkBegin(self); + + uint8_t val = mp_obj_get_int(val_in); + + if (i2c_master_write_byte(self->cmd, val, I2C_ACK_CHECK_EN) != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Write error")); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_i2c_write_byte_obj, mp_machine_i2c_write_byte); + +//----------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_write_bytes(mp_obj_t self_in, mp_obj_t buf_in) { + mp_machine_i2c_obj_t *self = self_in; + + _checkBegin(self); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + + if (i2c_master_write(self->cmd, bufinfo.buf, bufinfo.len, I2C_ACK_CHECK_EN) != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Write error")); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_i2c_write_bytes_obj, mp_machine_i2c_write_bytes); + +//---------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_read_byte(mp_obj_t self_in) { + mp_machine_i2c_obj_t *self = self_in; + + _checkBegin(self); + + if ((self->rx_data == NULL) || ((self->rx_bufidx + 1) >= self->rx_buflen)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Rx buffer overflow")); + } + + if (i2c_master_read_byte(self->cmd, &(self->rx_data[self->rx_bufidx]), I2C_MASTER_NACK) != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Read error")); + } + self->rx_bufidx++; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_read_byte_obj, mp_machine_i2c_read_byte); + +//---------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_read_bytes(mp_obj_t self_in, mp_obj_t len_in) { + mp_machine_i2c_obj_t *self = self_in; + + _checkBegin(self); + + esp_err_t ret = ESP_OK; + int len = mp_obj_get_int(len_in); + if ((len < 1) || (len > self->rx_buflen)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Rx buffer overflow")); + } + if ((self->rx_data == NULL) || ((self->rx_bufidx + len) >= self->rx_buflen)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Rx buffer overflow")); + } + + if (len > 1) { + ret = i2c_master_read(self->cmd, &(self->rx_data[self->rx_bufidx]), len-1, I2C_MASTER_ACK); + } + if (ret == ESP_OK) ret = i2c_master_read_byte(self->cmd, &(self->rx_data[self->rx_bufidx + len - 1]), I2C_MASTER_NACK); + + if (ret != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Read error")); + } + self->rx_bufidx += len; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_i2c_read_bytes_obj, mp_machine_i2c_read_bytes); + +// End i2c transaction +//---------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_end(mp_obj_t self_in) { + mp_machine_i2c_obj_t *self = self_in; + + _checkBegin(self); + + esp_err_t res = i2c_master_cmd_begin(self->bus_id, self->cmd, (5000 / portTICK_RATE_MS)); + + i2c_cmd_link_delete(self->cmd); + self->cmd = NULL; + + mp_obj_t ret = mp_const_none; + if ((res == ESP_OK) && (self->rx_data) && (self->rx_bufidx > 0)) { + vstr_t vstr; + vstr_init_len(&vstr, self->rx_bufidx); + memcpy(vstr.buf, self->rx_data, self->rx_bufidx); + // Return read data as string + ret = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + } + + self->rx_buflen = 0; + self->rx_bufidx = 0; + if (self->rx_data) free(self->rx_data); + self->rx_data = NULL; + + if (res != ESP_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + } + return ret; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_i2c_end_obj, mp_machine_i2c_end); + + +// ============================================================================================ +// ==== I2C slave functions =================================================================== +// ============================================================================================ + + +//--------------------------------------------------------------------------- +STATIC mp_obj_t mp_machine_i2c_slave_write(mp_obj_t self_in, mp_obj_t buf_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); + + if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + + int res = i2c_slave_write_buffer(self->bus_id, bufinfo.buf, bufinfo.len, 500 / portTICK_PERIOD_MS); + + if (slave_mutex) xSemaphoreGive(slave_mutex); + + if (res < 0) return mp_const_false; + return mp_obj_new_int(res); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_i2c_slave_write_obj, mp_machine_i2c_slave_write); + +//----------------------------------------------------------------------------------------------- +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); + + 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")); + } + + if (slave_mutex) xSemaphoreTake(slave_mutex, I2C_SLAVE_MUTEX_TIMEOUT); + + memcpy(self->slave_data + addr, bufinfo.buf, bufinfo.len); + + if (slave_mutex) xSemaphoreGive(slave_mutex); + + return mp_const_none; +} +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_getdata(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t len_in) +{ + mp_machine_i2c_obj_t *self = self_in; + _checkSlave(self); + + int addr = mp_obj_get_int(addr_in); + int len = mp_obj_get_int(len_in); + + if (addr >= self->slave_buflen) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Address not in slave 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 = mp_obj_new_bytes(self->slave_data + addr, len); + + if (slave_mutex) xSemaphoreGive(slave_mutex); + + // 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) +{ + mp_machine_i2c_obj_t *self = self_in; + _checkSlave(self); + + 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 (slave_mutex) xSemaphoreTake(slave_mutex, 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 (slave_mutex) xSemaphoreGive(slave_mutex); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_i2c_slave_callback_obj, mp_machine_i2c_slave_callback); + //=================================================================== -STATIC const mp_rom_map_elem_t machine_hw_i2c_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&machine_hw_i2c_init_obj }, - { MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_hw_i2c_deinit_obj }, - { MP_ROM_QSTR(MP_QSTR_scan), (mp_obj_t)&machine_hw_i2c_scan_obj }, +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 }, - // standard bus operations - { MP_ROM_QSTR(MP_QSTR_readfrom), (mp_obj_t)&machine_hw_i2c_readfrom_obj }, - { MP_ROM_QSTR(MP_QSTR_readfrom_into), (mp_obj_t)&machine_hw_i2c_readfrom_into_obj }, - { MP_ROM_QSTR(MP_QSTR_writeto), (mp_obj_t)&machine_hw_i2c_writeto_obj }, + // Standard methods + { MP_ROM_QSTR(MP_QSTR_readfrom), (mp_obj_t)&mp_machine_i2c_readfrom_obj }, + { MP_ROM_QSTR(MP_QSTR_readfrom_into), (mp_obj_t)&mp_machine_i2c_readfrom_into_obj }, + { 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_callback), (mp_obj_t)&mp_machine_i2c_slave_callback_obj }, - // memory operations - { MP_ROM_QSTR(MP_QSTR_readfrom_mem), (mp_obj_t)&machine_hw_i2c_readfrom_mem_obj }, - { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), (mp_obj_t)&machine_hw_i2c_readfrom_mem_into_obj }, - { MP_ROM_QSTR(MP_QSTR_writeto_mem), (mp_obj_t)&machine_hw_i2c_writeto_mem_obj }, + // Memory methods + { MP_ROM_QSTR(MP_QSTR_readfrom_mem), (mp_obj_t)&mp_machine_i2c_readfrom_mem_obj }, + { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), (mp_obj_t)&mp_machine_i2c_readfrom_mem_into_obj }, + { MP_ROM_QSTR(MP_QSTR_writeto_mem), (mp_obj_t)&mp_machine_i2c_writeto_mem_obj }, + // Low level MicroPython I2C methods + { MP_ROM_QSTR(MP_QSTR_begin), (mp_obj_t)&mp_machine_i2c_begin_obj }, + { MP_ROM_QSTR(MP_QSTR_start), (mp_obj_t)&mp_machine_i2c_start_obj }, + { MP_ROM_QSTR(MP_QSTR_address), (mp_obj_t)&mp_machine_i2c_address_obj }, + { MP_ROM_QSTR(MP_QSTR_stop), (mp_obj_t)&mp_machine_i2c_stop_obj }, + { MP_ROM_QSTR(MP_QSTR_read_byte), (mp_obj_t)&mp_machine_i2c_read_byte_obj }, + { MP_ROM_QSTR(MP_QSTR_read_bytes), (mp_obj_t)&mp_machine_i2c_read_bytes_obj }, + { MP_ROM_QSTR(MP_QSTR_write_byte), (mp_obj_t)&mp_machine_i2c_write_byte_obj }, + { MP_ROM_QSTR(MP_QSTR_write_bytes), (mp_obj_t)&mp_machine_i2c_write_bytes_obj }, + { MP_ROM_QSTR(MP_QSTR_end), (mp_obj_t)&mp_machine_i2c_end_obj }, + + // Constants { MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(I2C_MODE_MASTER) }, + { 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) }, }; -STATIC MP_DEFINE_CONST_DICT(machine_hw_i2c_locals_dict, machine_hw_i2c_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mp_machine_i2c_locals_dict, mp_machine_i2c_locals_dict_table); //========================================= const mp_obj_type_t machine_hw_i2c_type = { { &mp_type_type }, .name = MP_QSTR_I2C, - .print = machine_hw_i2c_print, - .make_new = machine_hw_i2c_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_hw_i2c_locals_dict, + .print = mp_machine_i2c_print, + .make_new = mp_machine_i2c_make_new, + .locals_dict = (mp_obj_dict_t*)&mp_machine_i2c_locals_dict, }; diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c b/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c index 0de4390..fe10783 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.c @@ -1,9 +1,10 @@ /* - * 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 "Eric Poulsen" + * Copyright 2017-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,14 +33,13 @@ #include #include "esp_heap_caps.h" -#include "py/runtime.h" +//#include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" #include "modmachine.h" #include "machine_pin.h" -#include "driver/spi_master.h" -#include "driver/spi_master_utils.h" +#include "machine_hw_spi.h" /* * There are two SPI hosts on ESP32 available to the user, HSPI_HOST & VSPI_HOST @@ -49,85 +49,18 @@ * CS is handled by the driver using spi_device_select() / spi_device_deselect() functions */ -// SPI bus configuration is used by SPI and Display modules -// possible by some other modules as well -#if CONFIG_SPIRAM_SPEED_80M -static spi_bus_config_t HSPI_buscfg = {-1, -1, -1, -1, -1, 0}; -spi_bus_config_t *MPy_SPIbus[3] = {NULL, &HSPI_buscfg, NULL}; -#else -static spi_bus_config_t HSPI_buscfg = {-1, -1, -1, -1, -1, 0}; -static spi_bus_config_t VSPI_buscfg = {-1, -1, -1, -1, -1, 0}; -spi_bus_config_t *MPy_SPIbus[3] = {NULL, &HSPI_buscfg, &VSPI_buscfg}; -#endif -typedef struct _machine_hw_spi_obj_t { - mp_obj_base_t base; - spi_device_interface_config_t devcfg; - exspi_device_handle_t spi; - uint8_t host; - int8_t polarity; - int8_t phase; - int8_t firstbit; - int8_t duplex; - enum { - MACHINE_HW_SPI_STATE_NONE, - MACHINE_HW_SPI_STATE_INIT, - MACHINE_HW_SPI_STATE_DEINIT - } state; -} machine_hw_spi_obj_t; - -#ifdef CONFIG_MICROPY_USE_DISPLAY -extern uint8_t disp_used_spi_host; -#endif - -//----------------------------------------------------------------- -int checkSPIBUS(int8_t bus, int8_t mosi, uint8_t miso, uint8_t sck) +//-------------------------------------------------------------------- +STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self) { - #ifdef CONFIG_MICROPY_USE_DISPLAY - if ((disp_used_spi_host > 0) && (MPy_SPIbus[disp_used_spi_host]->mosi_io_num >= 0)) return -3; // bus used by display driver - #endif - - if (MPy_SPIbus[bus] == NULL) return -2; // bus not available - if (MPy_SPIbus[bus]->mosi_io_num < 0) return 1; // bus not configured, free to use - - if ((mosi != MPy_SPIbus[bus]->mosi_io_num) || - (miso != MPy_SPIbus[bus]->miso_io_num) || - (sck != MPy_SPIbus[bus]->sclk_io_num)) return -1; // requested pins different than configured - return 0; // bus already configured with the same pins -} - -//--------------------------------------------------------------------------------- -STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self, int freebus) -{ - spi_device_handle_t handle = self->spi.handle; - if (spi_bus_remove_device(handle) != ESP_OK) { + esp_err_t res = remove_extspi_device(&self->spi); + if (res != ESP_OK) { mp_raise_msg(&mp_type_OSError, "error removing spi device"); } - if (freebus) { - // Check if spi buss can be freed - spi_host_t *host=(spi_host_t*)handle->host; - int i; - for (i=0; idevice[i] != NULL) break; - } - - if (i == NO_CS) { - // no more devices attached to host, free bus - if (spi_bus_free(self->host) != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "error freeing spi host"); - } - gpio_pad_select_gpio(MPy_SPIbus[self->host]->miso_io_num); - gpio_pad_select_gpio(MPy_SPIbus[self->host]->mosi_io_num); - gpio_pad_select_gpio(MPy_SPIbus[self->host]->sclk_io_num); - MPy_SPIbus[self->host]->sclk_io_num = -1; - MPy_SPIbus[self->host]->mosi_io_num = -1; - MPy_SPIbus[self->host]->miso_io_num = -1; - } - } } -//--------------------------------------- -STATIC void machine_hw_spi_init_internal( +//-------------------------------- +void machine_hw_spi_init_internal( machine_hw_spi_obj_t *self, int8_t host, int32_t baudrate, @@ -139,157 +72,99 @@ STATIC void machine_hw_spi_init_internal( int8_t miso, int8_t cs, int8_t duplex, + uint8_t queue_size, uint8_t new) { - // if we're not initialized, then we're implicitly 'changed', since this is the init routine esp_err_t ret; - int bus_state = 0; - machine_hw_spi_obj_t old_self; - machine_hw_spi_obj_t *pold_self; - if (new) pold_self = self; - else { - memcpy(&old_self, self, sizeof(machine_hw_spi_obj_t)); - pold_self = &old_self; - } + self->state = MACHINE_HW_SPI_STATE_DEINIT; - if (((mosi < 0) && (MPy_SPIbus[self->host]->mosi_io_num <0)) || - ((miso < 0) && (MPy_SPIbus[self->host]->miso_io_num <0)) || - ((sck < 0) && (MPy_SPIbus[self->host]->sclk_io_num <0))) { - mp_raise_ValueError("Error, not all spi pins given"); + if ((baudrate <= 0) || (baudrate > 80000000)) { + mp_raise_ValueError("SPI baudrate must be >0 & <=80000000"); } - uint16_t changed = pold_self->state != MACHINE_HW_SPI_STATE_INIT; + // Host initialization + if ((host != HSPI_HOST) && (host != VSPI_HOST)) { + mp_raise_ValueError("SPI host must be either HSPI(1) or VSPI(2)"); + } + if ((SPIbus_configs[VSPI_HOST] == NULL) && (host == VSPI_HOST)) { + mp_raise_ValueError("SPI host must be HSPI(1), VSPI(2) used by SPIRAM"); + } - if (host > -1) { - // Host initialization or host change - #if CONFIG_SPIRAM_SPEED_80M - if (host != HSPI_HOST) { - mp_raise_ValueError("SPI host must be HSPI(1)"); + int used_spi = spi_host_used_by_sdspi(); + if ((used_spi != 0) && (used_spi == host)) { + // change spi host + if (host == VSPI_HOST) { + mp_raise_ValueError("SPI host must be HSPI(1), VSPI(2) used by SDCard driver"); } - #else - if ((host != HSPI_HOST) && (host != VSPI_HOST)) { - mp_raise_ValueError("SPI host must be either HSPI(1) or VSPI(2)"); - } - #endif - - bus_state = checkSPIBUS(host, mosi, miso, sck); - if (bus_state == -3) { - mp_raise_ValueError("SPI host already used by display driver"); - } - else if (bus_state == -1) { - mp_raise_ValueError("SPI host already used with different configuration"); - } - else if (bus_state == -2) { - mp_raise_ValueError("SPI host not available"); - } - if ((host != pold_self->host) || (bus_state != 0)) { - self->host = host; - changed |= 0x0004; + else { + mp_raise_ValueError("SPI host must be VSPI(2), HSPI(1) used by SDCard driver"); } } - if ((baudrate > 0) && (baudrate != pold_self->devcfg.clock_speed_hz)) { - // Speed changed - if ((baudrate <= 0) || (baudrate > 80000000)) { - mp_raise_ValueError("SPI baudrate must be >0 & <=80000000"); - } - self->devcfg.clock_speed_hz = baudrate; - changed |= 0x0008; - } + self->spi.spihost = host; + self->spi.buscfg = SPIbus_configs[self->spi.spihost]; - if ((polarity > -1) && (polarity != pold_self->polarity)) { - // Polarity changed - self->polarity = polarity & 1; - changed |= 0x0010; - } + // Init pins + 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); + gpio_set_direction(miso, GPIO_MODE_INPUT); + gpio_set_pull_mode(miso, GPIO_PULLUP_ONLY); + gpio_set_direction(mosi, GPIO_MODE_OUTPUT); + gpio_set_direction(sck, GPIO_MODE_OUTPUT); - if ((phase > -1) && (phase != pold_self->phase)) { - // Phase changed - self->phase = phase & 1; - changed |= 0x0020; - } + // Set configuration + self->polarity = polarity & 1; + self->phase = phase & 1; + self->firstbit = firstbit & 1; + self->duplex = duplex & 1; - if ((firstbit > -1) && (firstbit != pold_self->firstbit)) { - self->firstbit = firstbit & 1; - changed |= 0x0040; - } + self->spi.dma_channel = 1; + self->spi.curr_clock = baudrate; + self->spi.handle = NULL; + self->spi.dc = -1; + self->spi.selected = 0; + self->spi.cs = cs; - if ((cs > -1) && (cs != pold_self->spi.cs)) { - // Initialize CS - gpio_pad_select_gpio(cs); - gpio_set_direction(cs, GPIO_MODE_OUTPUT); - gpio_set_level(cs, 1); - self->spi.cs = cs; - changed |= 0x0400; - } + self->spi.buscfg->miso_io_num = miso; + self->spi.buscfg->mosi_io_num = mosi; + self->spi.buscfg->sclk_io_num = sck; + self->spi.buscfg->quadwp_io_num = -1; + self->spi.buscfg->quadhd_io_num = -1; + //self->spi.buscfg->max_transfer_sz = 6*1024; - if ((duplex > -1) && (duplex != pold_self->duplex)) { - // Duplex changed - self->duplex = duplex & 1; - changed |= 0x0800; - } - - if (!changed) return; // no configuration changes, return - - if (pold_self->state == MACHINE_HW_SPI_STATE_INIT) { - // Remove device from spi host - self->state = MACHINE_HW_SPI_STATE_DEINIT; - machine_hw_spi_deinit_internal(pold_self, 0); - } - - // Check if spi bus has to be initialized - if (MPy_SPIbus[self->host]->mosi_io_num < 0) { - // SPI bus not initialized - gpio_pad_select_gpio(miso); - gpio_pad_select_gpio(mosi); - gpio_pad_select_gpio(sck); - gpio_set_direction(miso, GPIO_MODE_INPUT); - gpio_set_pull_mode(miso, GPIO_PULLUP_ONLY); - gpio_set_direction(mosi, GPIO_MODE_OUTPUT); - gpio_set_direction(sck, GPIO_MODE_OUTPUT); - - MPy_SPIbus[self->host]->sclk_io_num = sck; - MPy_SPIbus[self->host]->mosi_io_num = mosi; - MPy_SPIbus[self->host]->miso_io_num = miso; - MPy_SPIbus[self->host]->quadwp_io_num = -1; - MPy_SPIbus[self->host]->quadhd_io_num = -1; - MPy_SPIbus[self->host]->max_transfer_sz = 4096; - // Initialize the spi bus - ret=spi_bus_initialize(host, MPy_SPIbus[self->host], 1); - if (ret != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "error initializing spi bus"); - return; - } - changed |= 0x1000; - } - - // No hw CS pin, we use software CS handling in this module - self->devcfg.spics_io_num = -1; - - self->devcfg.mode = self->phase | (self->polarity << 1); - self->devcfg.flags = ((self->firstbit == MICROPY_PY_MACHINE_SPI_LSB) ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0); - if (!self->duplex) self->devcfg.flags |= SPI_DEVICE_HALFDUPLEX; - self->devcfg.pre_cb = NULL; - self->devcfg.queue_size = 1; - - // Add device to spi bus - ret = spi_bus_add_device(self->host, &self->devcfg, &self->spi.handle); + self->spi.devcfg.clock_speed_hz = self->spi.curr_clock; + self->spi.devcfg.duty_cycle_pos = 128; + self->spi.devcfg.mode = self->phase | (self->polarity << 1); + self->spi.devcfg.spics_io_num = -1; + self->spi.devcfg.queue_size = queue_size; + self->spi.devcfg.flags = ((self->firstbit == MICROPY_PY_MACHINE_SPI_LSB) ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0); + if (!self->duplex) self->spi.devcfg.flags |= SPI_DEVICE_HALFDUPLEX; + self->spi.devcfg.pre_cb = NULL; + // ==== Initialize the SPI bus and attach the device ==== + ret = add_extspi_device(&self->spi); if (ret == ESP_OK) { ret = spi_device_select(&self->spi, 1); if (ret != ESP_OK) { + machine_hw_spi_deinit_internal(self); mp_raise_msg(&mp_type_OSError, "Error selecting device"); } ret = spi_device_deselect(&self->spi); if (ret != ESP_OK) { + machine_hw_spi_deinit_internal(self); mp_raise_msg(&mp_type_OSError, "Error deselecting device"); } self->state = MACHINE_HW_SPI_STATE_INIT; return; } - switch (ret) { + + switch (ret) { case ESP_ERR_INVALID_ARG: mp_raise_msg(&mp_type_OSError, "invalid configuration"); return; @@ -303,8 +178,20 @@ STATIC void machine_hw_spi_init_internal( mp_raise_msg(&mp_type_OSError, "no free slots"); return; default: - mp_raise_msg(&mp_type_OSError, "error initializing spi"); + { + char err[40]; + sprintf(err, "error initializing spi (%d)", ret); + mp_raise_msg(&mp_type_OSError, err); return; + } + } +} + +//---------------------------------------------- +STATIC void checkSPI(machine_hw_spi_obj_t *self) +{ + if (self->state != MACHINE_HW_SPI_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "SPI not initialized"); } } @@ -314,7 +201,7 @@ STATIC mp_obj_t machine_hw_spi_deinit(mp_obj_t self_in) machine_hw_spi_obj_t *self = self_in; if (self->state == MACHINE_HW_SPI_STATE_INIT) { self->state = MACHINE_HW_SPI_STATE_DEINIT; - machine_hw_spi_deinit_internal(self, 1); + machine_hw_spi_deinit_internal(self); } return mp_const_none; } @@ -324,50 +211,25 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_spi_deinit_obj, machine_hw_spi_deini STATIC void machine_hw_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->state == MACHINE_HW_SPI_STATE_DEINIT) { + mp_printf(print, "SPI( DEINITIALIZED )"); + return; + } char scs[16] = {'\0'}; if (self->spi.cs < 0) sprintf(scs, "Not used"); else sprintf(scs, "%d", self->spi.cs); mp_printf(print, "SPI( %s\n spihost=%s (%s)\n baudrate=%u, polarity=%u, phase=%u, firstbit=%s, duplex=%s\n Pins: sck=%d, mosi=%d, miso=%d, cs=%s\n )", (self->state == MACHINE_HW_SPI_STATE_INIT) ? "INITIALIZED" : "DEINITIALIZED", - (self->host == HSPI_HOST) ? "HSPI" : "VSPI", (MPy_SPIbus[self->host]->mosi_io_num < 0) ? "free" : "initialized", + (self->spi.spihost == HSPI_HOST) ? "HSPI" : "VSPI", (self->spi.buscfg->mosi_io_num < 0) ? "free" : "initialized", spi_get_speed(&self->spi), self->polarity, self->phase, (self->firstbit) ? "LSB" : "MSB", (self->duplex) ? "True" : "False", - MPy_SPIbus[self->host]->sclk_io_num, MPy_SPIbus[self->host]->mosi_io_num, MPy_SPIbus[self->host]->miso_io_num, scs); + self->spi.buscfg->sclk_io_num, self->spi.buscfg->mosi_io_num, self->spi.buscfg->miso_io_num, scs); } //------------------------------------------------------------------------------------------------ STATIC mp_obj_t machine_hw_spi_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - machine_hw_spi_obj_t *self = pos_args[0]; - - enum { ARG_spihost, ARG_baudrate, ARG_polarity, ARG_phase, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso, ARG_cs, ARG_duplex, ARG_bits }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_spihost, MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_duplex, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, - }; - - 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); - - int8_t sck=-1, mosi=-1, miso=-1, cs=-1; - - if (args[ARG_sck].u_obj != MP_OBJ_NULL) sck = machine_pin_get_gpio(args[ARG_sck].u_obj); - if (args[ARG_miso].u_obj != MP_OBJ_NULL) miso = machine_pin_get_gpio(args[ARG_miso].u_obj); - if (args[ARG_mosi].u_obj != MP_OBJ_NULL) mosi = machine_pin_get_gpio(args[ARG_mosi].u_obj); - if (args[ARG_cs].u_obj != MP_OBJ_NULL) cs = machine_pin_get_gpio(args[ARG_cs].u_obj); - - machine_hw_spi_init_internal(self, args[ARG_spihost].u_int, args[ARG_baudrate].u_int, - args[ARG_polarity].u_int, args[ARG_phase].u_int, - args[ARG_firstbit].u_int, sck, mosi, miso, cs, args[ARG_duplex].u_bool, 0); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_spi_init_obj, 0, machine_hw_spi_init); @@ -397,7 +259,7 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_ self->base.type = &machine_hw_spi_type; self->state = MACHINE_HW_SPI_STATE_NONE; - memset(&self->devcfg, 0, sizeof(spi_device_interface_config_t)); + memset(&self->spi.devcfg, 0, sizeof(spi_device_interface_config_t)); self->spi.cs = -1; self->spi.handle = NULL; @@ -416,6 +278,7 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_ machine_pin_get_gpio(args[ARG_miso].u_obj), cs, args[ARG_duplex].u_bool, + 1, 1); return MP_OBJ_FROM_PTR(self); @@ -425,6 +288,7 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_ STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { machine_hw_spi_obj_t *self = args[0]; + checkSPI(self); vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(args[1])); @@ -457,6 +321,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_mac STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) { machine_hw_spi_obj_t *self = args[0]; + checkSPI(self); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); @@ -487,6 +352,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { machine_hw_spi_obj_t *self = self_in; + checkSPI(self); + mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); @@ -509,6 +376,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write) STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf, mp_obj_t rd_buf) { machine_hw_spi_obj_t *self = self_in; + checkSPI(self); + mp_buffer_info_t src; mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); mp_buffer_info_t dest; @@ -532,6 +401,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_s 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) { machine_hw_spi_obj_t *self = pos_args[0]; + checkSPI(self); static const mp_arg_t allowed_args[] = { { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, @@ -586,6 +456,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_spi_read_from_mem_obj, 0, mp_machin STATIC mp_obj_t mp_machine_spi_select(mp_obj_t self_in) { machine_hw_spi_obj_t *self = self_in; + checkSPI(self); esp_err_t ret = spi_device_select(&self->spi, 0); @@ -598,6 +469,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_spi_select_obj, mp_machine_spi_selec STATIC mp_obj_t mp_machine_spi_deselect(mp_obj_t self_in) { machine_hw_spi_obj_t *self = self_in; + checkSPI(self); esp_err_t ret = spi_device_deselect(&self->spi); @@ -609,22 +481,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_machine_spi_deselect_obj, mp_machine_spi_des //================================================================ STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&machine_hw_spi_init_obj }, - { MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_hw_spi_deinit_obj }, - { MP_ROM_QSTR(MP_QSTR_read), (mp_obj_t)&mp_machine_spi_read_obj }, - { MP_ROM_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_machine_spi_readinto_obj }, - { MP_ROM_QSTR(MP_QSTR_readfrom_mem), (mp_obj_t)&mp_machine_spi_read_from_mem_obj }, - { MP_ROM_QSTR(MP_QSTR_write), (mp_obj_t)&mp_machine_spi_write_obj }, - { MP_ROM_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&mp_machine_spi_write_readinto_obj }, - { MP_ROM_QSTR(MP_QSTR_select), (mp_obj_t)&mp_machine_spi_select_obj }, - { MP_ROM_QSTR(MP_QSTR_deselect), (mp_obj_t)&mp_machine_spi_deselect_obj }, + { MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&machine_hw_spi_init_obj }, + { MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_hw_spi_deinit_obj }, + { MP_ROM_QSTR(MP_QSTR_read), (mp_obj_t)&mp_machine_spi_read_obj }, + { MP_ROM_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_machine_spi_readinto_obj }, + { MP_ROM_QSTR(MP_QSTR_readfrom_mem), (mp_obj_t)&mp_machine_spi_read_from_mem_obj }, + { MP_ROM_QSTR(MP_QSTR_write), (mp_obj_t)&mp_machine_spi_write_obj }, + { MP_ROM_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&mp_machine_spi_write_readinto_obj }, + { MP_ROM_QSTR(MP_QSTR_select), (mp_obj_t)&mp_machine_spi_select_obj }, + { MP_ROM_QSTR(MP_QSTR_deselect), (mp_obj_t)&mp_machine_spi_deselect_obj }, - { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB) }, - { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB) }, - { MP_ROM_QSTR(MP_QSTR_HSPI), MP_ROM_INT(HSPI_HOST) }, - #if !CONFIG_SPIRAM_SPEED_80M - { MP_ROM_QSTR(MP_QSTR_VSPI), MP_ROM_INT(VSPI_HOST) }, - #endif + { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_MSB) }, + { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(MICROPY_PY_MACHINE_SPI_LSB) }, + { MP_ROM_QSTR(MP_QSTR_HSPI), MP_ROM_INT(HSPI_HOST) }, + { MP_ROM_QSTR(MP_QSTR_VSPI), MP_ROM_INT(VSPI_HOST) }, }; MP_DEFINE_CONST_DICT(mp_machine_spi_locals_dict, machine_spi_locals_dict_table); diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.h b/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.h new file mode 100644 index 0000000..a793335 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/machine_hw_spi.h @@ -0,0 +1,68 @@ +/* + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * Copyright 2017-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 _MACHINE_HW_SPI_H_ +#define __MACHINE_HW_SPI_H_ + +#include "sdkconfig.h" + +#include "py/runtime.h" + +#include "driver/spi_master_utils.h" + +typedef struct _machine_hw_spi_obj_t { + mp_obj_base_t base; + //spi_device_interface_config_t devcfg; + exspi_device_handle_t spi; + //uint8_t host; + int8_t polarity; + int8_t phase; + int8_t firstbit; + int8_t duplex; + enum { + MACHINE_HW_SPI_STATE_NONE, + MACHINE_HW_SPI_STATE_INIT, + MACHINE_HW_SPI_STATE_DEINIT + } state; +} machine_hw_spi_obj_t; + +extern void machine_hw_spi_init_internal ( + machine_hw_spi_obj_t *self, + int8_t host, + int32_t baudrate, + int8_t polarity, + int8_t phase, + int8_t firstbit, + int8_t sck, + int8_t mosi, + int8_t miso, + int8_t cs, + int8_t duplex, + uint8_t queue_size, + uint8_t new); + +#endif diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c b/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c index 57e676c..3a24498 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_neopixel.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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 Boris Lovosevic (https://github.loboris) + * 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/esp32/machine_ow.c b/MicroPython_BUILD/components/micropython/esp32/machine_ow.c index fac9ae9..93f8ec4 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_ow.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_ow.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) 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/esp32/machine_pin.c b/MicroPython_BUILD/components/micropython/esp32/machine_pin.c index e6c4cc8..df1f081 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_pin.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_pin.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) 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 @@ -120,7 +121,7 @@ void machine_pins_deinit(void) { STATIC void IRAM_ATTR machine_pin_isr_handler(void *arg) { machine_pin_obj_t *self = arg; mp_obj_t handler = MP_STATE_PORT(machine_pin_irq_handler)[self->id]; - mp_sched_schedule(handler, MP_OBJ_FROM_PTR(self)); + mp_sched_schedule(handler, MP_OBJ_FROM_PTR(self), NULL); } gpio_num_t machine_pin_get_id(mp_obj_t pin_in) { diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_pin.h b/MicroPython_BUILD/components/micropython/esp32/machine_pin.h index 0b88d17..4ffa111 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_pin.h +++ b/MicroPython_BUILD/components/micropython/esp32/machine_pin.h @@ -1,3 +1,31 @@ +/* + * 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 + * 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 "driver/gpio.h" diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c b/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c index 324d3fd..643eba0 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_pwm.c @@ -1,5 +1,5 @@ /* - * This file is part of the Micro Python 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) * diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c index 9e3cb20..95ec4d2 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.c @@ -1,12 +1,12 @@ /* - * This file is part of the Micro Python 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) 2013, 2014 Damien P. George + * Copyright (c) 2013 2014 Damien P. George * Copyright (c) 2015 Daniel Campora * Copyright (c) 2017 "Eric Poulsen" - * Copyright (c) 2017 Boris Lovosevic + * 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 @@ -167,10 +167,16 @@ STATIC mp_obj_t mach_rtc_datetime(const mp_obj_t *args) { if (seconds == -1) seconds = 0; struct timeval now; - now.tv_sec = seconds; + + gettimeofday(&now, NULL); + uint64_t ticks_us = ((((uint64_t)now.tv_sec * 1000000) + (uint64_t)now.tv_usec) - getTicks_base()); + + now.tv_sec = seconds; now.tv_usec = 0; - settimeofday(&now, NULL); - mp_hal_ticks_base = now.tv_sec; + + settimeofday(&now, NULL); + // Set new base for ticks counting + setTicks_base((((uint64_t)now.tv_sec * 1000000) - ticks_us)); mach_rtc_set_seconds_since_epoch(seconds); @@ -240,43 +246,56 @@ void sntp_task (void *pvParameters) mach_rtc_obj_t *rtc = (mach_rtc_obj_t *)pvParameters; struct timeval tv; uint32_t ellapsed=0, start_time; + uint64_t ticks_us; + int check_interval = 100; - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); start_time = tv.tv_sec; + // get current ticks_us + ticks_us = ((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec) - getTicks_base()); + ESP_LOGD("SNTP_TASK", "start synchronization"); start_sntp(rtc->sntp_server_name); while (1) { - vTaskDelay(1000 / portTICK_PERIOD_MS); + vTaskDelay(check_interval / portTICK_PERIOD_MS); gettimeofday(&tv, NULL); + ticks_us += check_interval * 1000; + ellapsed += check_interval; if (sntp_is_synced) { sntp_stop(); + sntp_is_synced = false; + ESP_LOGD("SNTP_TASK", "time synchronized"); + // Set new base for ticks counting + setTicks_base((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec - ticks_us)); + if (xSemaphoreTake(sntp_mutex, 1000 / portTICK_PERIOD_MS) == pdTRUE) { rtc->synced = true; - // Update the tick base - mp_hal_ticks_base = tv.tv_sec; seconds_at_boot = tv.tv_sec; xSemaphoreGive(sntp_mutex); } - start_time = tv.tv_sec; - ellapsed = 0; // Terminate the task if periodic update is not requested - if (rtc->sntp_update_period == 0) break; + if (rtc->sntp_update_period <= 10) break; + // else prepare for next update + ESP_LOGD("SNTP_TASK", "next update in %d seconds", rtc->sntp_update_period); + start_time = tv.tv_sec; + ticks_us = ((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec) - getTicks_base()); + ellapsed = 0; + check_interval = 1000; } else { - if (xSemaphoreTake(sntp_mutex, 1000 / portTICK_PERIOD_MS) == pdTRUE) { - if (!rtc->synced) start_time = 0; - xSemaphoreGive(sntp_mutex); - } ellapsed = tv.tv_sec - start_time; if (ellapsed >= rtc->sntp_update_period) { // Update period expired, update time from server + check_interval = 100; start_time = tv.tv_sec; + ESP_LOGD("SNTP_TASK", "start synchronization"); start_sntp(rtc->sntp_server_name); } } } + // Terminate the task sntp_handle = NULL; vTaskDelete(NULL); } @@ -295,7 +314,7 @@ STATIC mp_obj_t mach_rtc_ntp_sync(size_t n_args, const mp_obj_t *pos_args, mp_ma int period = args[1].u_int; - if (period < 600) period = 0; + if (period < 300) period = 10; char srv_name[64]; sprintf(srv_name, "%s", DEFAULT_SNTP_SERVER); @@ -342,7 +361,7 @@ 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", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY+1, &sntp_handle) != pdPASS) { + if (xTaskCreate(&sntp_task, "SNTP_TASK", 2048, (void *)self, CONFIG_MICROPY_TASK_PRIORITY+1, &sntp_handle) != pdPASS) { mp_raise_msg(&mp_type_OSError, "Error creating SNTP task"); } } diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h index 1578663..7692f97 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h +++ b/MicroPython_BUILD/components/micropython/esp32/machine_rtc.h @@ -1,11 +1,11 @@ /* - * This file is part of the Micro Python 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) 2013, 2014 Damien P. George + * Copyright (c) 2013 2014 Damien P. George * Copyright (c) 2015 Daniel Campora - * Copyright (c) 2017 Boris Lovosevic + * 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/esp32/machine_timer.c b/MicroPython_BUILD/components/micropython/esp32/machine_timer.c index d39c421..2f599d3 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_timer.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_timer.c @@ -1,5 +1,5 @@ /* - * 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) * @@ -218,7 +218,7 @@ STATIC void machine_timer_isr(void *self_in) if (self->debug_pin >= 0) gpio_set_level(self->debug_pin, (self->event_num & 1)); self->event_num++; - if ((self->callback) && (mp_sched_schedule(self->callback, self))) self->cb_num++; + if ((self->callback) && (mp_sched_schedule(self->callback, self, NULL))) self->cb_num++; } //---------------------------------------------- @@ -245,7 +245,7 @@ STATIC void machine_ext_timer_isr(void *self_in) extmr->event_num++; if (extmr->counter == extmr->alarm) { // Schedule the callback execution - if ((extmr->callback) && (mp_sched_schedule(extmr->callback, extmr))) { + if ((extmr->callback) && (mp_sched_schedule(extmr->callback, extmr, NULL))) { extmr->cb_num++; self->cb_num++; } diff --git a/MicroPython_BUILD/components/micropython/esp32/machine_uart.c b/MicroPython_BUILD/components/micropython/esp32/machine_uart.c index e2074f1..000225f 100644 --- a/MicroPython_BUILD/components/micropython/esp32/machine_uart.c +++ b/MicroPython_BUILD/components/micropython/esp32/machine_uart.c @@ -1,9 +1,10 @@ /* - * 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) 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 @@ -138,6 +139,22 @@ int pattern_match(uint8_t *text, int text_length, uint8_t *pattern, int pattern_ return -1; } +//-------------------------------------------------------------------------------------------- +static void _sched_callback(mp_obj_t function, int uart, int type, int iarglen, uint8_t *sarg) +{ + 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, 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; + } + else { + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, iarglen, sarg, NULL)) return; + } + mp_sched_schedule(function, mp_const_none, carg); +} + //--------------------------------------------- static void uart_event_task(void *pvParameters) { @@ -169,22 +186,14 @@ static void uart_event_task(void *pvParameters) if (res) { // MPy buffer full if (self->error_cb) { - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_ERROR); - tuple[2] = mp_obj_new_int(UART_BUFFER_FULL); - mp_sched_schedule(self->error_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->error_cb, self->uart_num+1, UART_CB_TYPE_ERROR, UART_BUFFER_FULL, NULL); } } else { - if ((self->data_cb_size > 0) && (uart_buf[self->uart_num]->iput >= self->data_cb_size)) { + if ((self->data_cb) && (self->data_cb_size > 0) && (uart_buf[self->uart_num]->iput >= self->data_cb_size)) { // ** callback on data length received uart_buf_get(uart_buf[self->uart_num], dtmp, self->data_cb_size); - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_DATA); - tuple[2] = mp_obj_new_str((const char*)dtmp, self->data_cb_size, 0); - mp_sched_schedule(self->data_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->data_cb, self->uart_num+1, UART_CB_TYPE_DATA, self->data_cb_size, dtmp); } else if (self->pattern_cb) { // ** callback on pattern received @@ -192,11 +201,7 @@ static void uart_event_task(void *pvParameters) if (res >= 0) { // found, pull data, including pattern from buffer uart_buf_get(uart_buf[self->uart_num], dtmp, res+self->pattern_len); - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_PATTERN); - tuple[2] = mp_obj_new_str((const char*)dtmp, res, 0); - mp_sched_schedule(self->pattern_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->pattern_cb, self->uart_num+1, UART_CB_TYPE_PATTERN, res, dtmp); } } } @@ -211,11 +216,7 @@ static void uart_event_task(void *pvParameters) uart_flush_input(self->uart_num+1); xQueueReset(UART_QUEUE[self->uart_num]); if (self->error_cb) { - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_ERROR); - tuple[2] = mp_obj_new_int(UART_FIFO_OVF); - mp_sched_schedule(self->error_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->error_cb, self->uart_num+1, UART_CB_TYPE_ERROR, UART_FIFO_OVF, NULL); } break; //Event of UART ring buffer full @@ -225,41 +226,25 @@ static void uart_event_task(void *pvParameters) uart_flush_input(self->uart_num+1); xQueueReset(UART_QUEUE[self->uart_num]); if (self->error_cb) { - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_ERROR); - tuple[2] = mp_obj_new_int(UART_BUFFER_FULL); - mp_sched_schedule(self->error_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->error_cb, self->uart_num+1, UART_CB_TYPE_ERROR, UART_BUFFER_FULL, NULL); } break; //Event of UART RX break detected case UART_BREAK: if (self->error_cb) { - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_ERROR); - tuple[2] = mp_obj_new_int(UART_BREAK); - mp_sched_schedule(self->error_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->error_cb, self->uart_num+1, UART_CB_TYPE_ERROR, UART_BREAK, NULL); } break; //Event of UART parity check error case UART_PARITY_ERR: if (self->error_cb) { - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_ERROR); - tuple[2] = mp_obj_new_int(UART_PARITY_ERR); - mp_sched_schedule(self->error_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->error_cb, self->uart_num+1, UART_CB_TYPE_ERROR, UART_PARITY_ERR, NULL); } break; //Event of UART frame error case UART_FRAME_ERR: if (self->error_cb) { - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(self->uart_num+1); - tuple[1] = mp_obj_new_int(UART_CB_TYPE_ERROR); - tuple[2] = mp_obj_new_int(UART_FRAME_ERR); - mp_sched_schedule(self->error_cb, mp_obj_new_tuple(3, tuple)); + _sched_callback(self->error_cb, self->uart_num+1, UART_CB_TYPE_ERROR, UART_FRAME_ERR, NULL); } break; //Others @@ -267,6 +252,7 @@ static void uart_event_task(void *pvParameters) //ESP_LOGI(TAG, "uart event type: %d", event.type); break; } + if (uart_mutex) xSemaphoreGive(uart_mutex); } } @@ -540,7 +526,7 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, //Disable uart pattern detect function uart_disable_pattern_det_intr(uart_num); - //Create a task to handler UART event from ISR + //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]); return MP_OBJ_FROM_PTR(self); @@ -768,8 +754,8 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz if (uart_mutex) xSemaphoreTake(uart_mutex, 200 / portTICK_PERIOD_MS); if (uart_buf[self->uart_num]->iput < size) { if (uart_mutex) xSemaphoreGive(uart_mutex); - vTaskDelay(10 / portTICK_PERIOD_MS); - wait -= 10; + vTaskDelay(2 / portTICK_PERIOD_MS); + wait -= 2; mp_hal_reset_wdt(); continue; } diff --git a/MicroPython_BUILD/components/micropython/esp32/main.c b/MicroPython_BUILD/components/micropython/esp32/main.c index a5aeb0f..6ef4c5b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/main.c +++ b/MicroPython_BUILD/components/micropython/esp32/main.c @@ -1,14 +1,10 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ - * - * Development of the code in this file was sponsored by Microbric Pty Ltd + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 LoBo (https://github.com/loboris) * - * Copyright (c) 2017 Boris Lovosevic (External SPIRAM support) - * * 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 @@ -157,8 +153,8 @@ soft_reset: char sbuff[24] = { 0 }; gc_info_t info; gc_info(&info); - // set gc.threshold to 87.5% of usable heap - MP_STATE_MEM(gc_alloc_threshold) = ((info.total / 8) * 7) / MICROPY_BYTES_PER_GC_BLOCK; + // 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"); diff --git a/MicroPython_BUILD/components/micropython/esp32/modbluetooth.c b/MicroPython_BUILD/components/micropython/esp32/modbluetooth.c new file mode 100644 index 0000000..6b09ff2 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modbluetooth.c @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * 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" +extern const mp_obj_type_t btle_type; + +STATIC const mp_map_elem_t mp_module_bluetooth_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_bluetooth) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LE), (mp_obj_t)&btle_type }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_bluetooth_globals, mp_module_bluetooth_globals_table); + +const mp_obj_module_t mp_module_bluetooth = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_bluetooth_globals, +}; diff --git a/MicroPython_BUILD/components/micropython/esp32/modcurl.c b/MicroPython_BUILD/components/micropython/esp32/modcurl.c index 379398a..907ef90 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modcurl.c +++ b/MicroPython_BUILD/components/micropython/esp32/modcurl.c @@ -1,12 +1,9 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ - * - * Development of the code in this file was sponsored by Microbric Pty Ltd + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) 2013-2015 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/esp32/moddisplay.c b/MicroPython_BUILD/components/micropython/esp32/moddisplay.c index 169f310..75dbb79 100644 --- a/MicroPython_BUILD/components/micropython/esp32/moddisplay.c +++ b/MicroPython_BUILD/components/micropython/esp32/moddisplay.c @@ -1,12 +1,9 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ - * - * Development of the code in this file was sponsored by Microbric Pty Ltd + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) 2013-2015 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 @@ -27,10 +24,6 @@ * THE SOFTWARE. */ -#include "sdkconfig.h" - -#ifdef CONFIG_MICROPY_USE_DISPLAY - #include #include #include @@ -41,80 +34,87 @@ #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 "tft/spi_master_lobo.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" typedef struct _display_tft_obj_t { mp_obj_base_t base; - int type; - spi_lobo_device_handle_t spi; - spi_lobo_device_handle_t tsspi; - uint32_t spi_speed; - uint32_t spi_rdspeed; - int width; - int height; - uint8_t miso; - uint8_t mosi; - uint8_t clk; - uint8_t cs; - uint8_t dc; - int8_t tcs; - int8_t rst; - int8_t bckl; - uint8_t bckl_on; - uint8_t invrot; - uint8_t bgr; - uint8_t tp_type; + 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; -extern int checkSPIBUS(int8_t bus, int8_t mosi, uint8_t miso, uint8_t sck); - -STATIC display_tft_obj_t display_tft_obj; const mp_obj_type_t display_tft_type; 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 = (display_tft_obj_t*)&display_tft_obj; + 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->type = -1; self->spi = NULL; - self->tsspi = NULL; - self->spi_speed = 0; + 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 constant object - return (mp_obj_t)&display_tft_obj; + //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->spi) && (self->type >= 0)) { - char stype[16]; - if (self->type == DISP_TYPE_ILI9341) sprintf(stype, "ILI9341"); - else if (self->type == DISP_TYPE_ILI9488) sprintf(stype, "ILI9488"); - else if (self->type == DISP_TYPE_ST7789V) sprintf(stype, "ST7789V"); - - mp_printf(print, "TFT (%dx%d, Type=%s, Ready: %s, Clk=%u Hz, RdClk=%u Hz, Touch: %s)\n", - self->width, self->height, stype, ((self->spi) ? "yes" : "no"), self->spi_speed, self->spi_rdspeed, ((self->tsspi) ? "yes" : "no")); - mp_printf(print, "Pins (miso=%d, mosi=%d, clk=%d, cs=%d, dc=%d, reset=%d, backlight=%d)", self->miso, self->mosi, self->clk, self->cs, self->dc, self->rst, self->bckl); - if (self->tsspi) { - mp_printf(print, "\nTouch(Enabled, cs=%d)", self->tcs); + 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 { @@ -122,25 +122,26 @@ STATIC void display_tft_printinfo(const mp_print_t *print, mp_obj_t self_in, mp_ } } +/* + * 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->spi == NULL) return 1; - tft_disp_type = disp_dev->type; - pin_dc = disp_dev->dc; - pin_rst = disp_dev->rst; - pin_bckl = disp_dev->bckl; - bckl_on = disp_dev->bckl_on; - disp_spi = disp_dev->spi; - ts_spi = disp_dev->tsspi; - _width = disp_dev->width; - _height = disp_dev->height; - _invert_rot = disp_dev->invrot; - _rgb_bgr = disp_dev->bgr; - max_rdclock = disp_dev->spi_rdspeed; - tp_type = disp_dev->tp_type; - tp_calx = disp_dev->tp_calx; - tp_caly = disp_dev->tp_caly; + 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; } @@ -154,29 +155,54 @@ STATIC color_t intToColor(uint32_t cint) 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_rot, ARG_splash }; + 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 = LOBO_HSPI_HOST } }, + { 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 = DEFAULT_SPI_CLOCK } }, - { MP_QSTR_miso, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = PIN_NUM_MISO } }, - { MP_QSTR_mosi, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = PIN_NUM_MOSI } }, - { MP_QSTR_clk, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = PIN_NUM_CLK } }, - { MP_QSTR_cs, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = PIN_NUM_CS } }, - { MP_QSTR_dc, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = PIN_NUM_DC } }, + { 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 = 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_rot, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = PORTRAIT } }, + { 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)]; @@ -185,205 +211,111 @@ STATIC mp_obj_t display_tft_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ display_tft_obj_t *self = pos_args[0]; esp_err_t ret; - if (self->spi) { - // === deinitialize spi device(s) if it was initialized === - if (self->tsspi) { - ret = spi_lobo_bus_remove_device(self->tsspi); - self->tsspi = NULL; - ts_spi = NULL; - } - ret = spi_lobo_bus_remove_device(self->spi); - self->spi = NULL; - disp_spi = NULL; - self->type = -1; - self->spi_speed = 0; - } + // === deinitialize display spi device if it was initialized === + if (self->disp_spi->handle) spi_deinit_internal(self); // === Get arguments === - #if CONFIG_SPIRAM_SPEED_80M - if (args[ARG_host].u_int != LOBO_HSPI_HOST) { - mp_raise_msg(&mp_type_OSError, "Unsupported SPI host"); - } - #else - if ((args[ARG_host].u_int != LOBO_HSPI_HOST) && (args[ARG_host].u_int != LOBO_VSPI_HOST)) { - mp_raise_msg(&mp_type_OSError, "Unsupported SPI host"); - } - #endif - - int bus_state = checkSPIBUS(args[ARG_host].u_int, args[ARG_mosi].u_int, args[ARG_miso].u_int, args[ARG_clk].u_int); - if (bus_state != 1) { - mp_raise_ValueError("SPI host already used by SPI module with different configuration"); + 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_msg(&mp_type_OSError, "Unsupported display type"); + mp_raise_ValueError("Unsupported display type"); } - self->type = args[ARG_type].u_int; - self->tp_type = TOUCH_TYPE_NONE; - - self->width = args[ARG_width].u_int; // smaller dimension - self->height = args[ARG_height].u_int; // larger dimension - self->spi_rdspeed = 8000000; - if (args[ARG_invrot].u_int >= 0) self->invrot = args[ARG_invrot].u_int; - else { - if ((self->type == DISP_TYPE_ST7789V) || - (self->type == DISP_TYPE_ST7735) || - (self->type == DISP_TYPE_ST7735R) || - (self->type == DISP_TYPE_ST7735B)) self->invrot = 2; - else self->invrot = 0; + if ((args[ARG_cbits].u_int != 16) && (args[ARG_cbits].u_int != 24)) { + mp_raise_ValueError("Unsupported color bits"); } - if (args[ARG_bgr].u_bool) self->bgr = 8; - else self->bgr = 0; + self->dconfig.color_bits = args[ARG_cbits].u_int; - self->rst = args[ARG_rst].u_int; - self->bckl = args[ARG_bckl].u_int; - self->bckl_on = args[ARG_bcklon].u_int & 1; + self->dconfig.type = args[ARG_type].u_int; - self->miso = args[ARG_miso].u_int; - self->mosi = args[ARG_mosi].u_int; - self->clk = args[ARG_clk].u_int; - - self->cs = args[ARG_cs].u_int; - self->dc = args[ARG_dc].u_int; - - self->tcs = args[ARG_tcs].u_int; - - // === Configure pins === - // Route all used pins to GPIO control (some pins may initially be routed to other devices) - gpio_pad_select_gpio(self->cs); - gpio_pad_select_gpio(self->miso); - gpio_pad_select_gpio(self->mosi); - gpio_pad_select_gpio(self->clk); - gpio_pad_select_gpio(self->dc); - if (self->tcs >= 0) { - gpio_pad_select_gpio(self->tcs); - gpio_set_direction(self->tcs, GPIO_MODE_OUTPUT); - gpio_set_level(self->tcs, 1); - } - if (self->rst >= 0) { - gpio_pad_select_gpio(self->rst); - gpio_set_direction(self->rst, GPIO_MODE_OUTPUT); - gpio_set_level(self->rst, 0); - } - if (self->bckl >= 0) { - gpio_pad_select_gpio(self->bckl); - gpio_set_direction(self->bckl, GPIO_MODE_OUTPUT); - gpio_set_level(self->bckl, (self->bckl_on & 1) ^ 1); - } - - gpio_set_direction(self->miso, GPIO_MODE_INPUT); - gpio_set_pull_mode(self->miso, GPIO_PULLUP_ONLY); - gpio_set_direction(self->cs, GPIO_MODE_OUTPUT); - gpio_set_direction(self->mosi, GPIO_MODE_OUTPUT); - gpio_set_direction(self->clk, GPIO_MODE_OUTPUT); - gpio_set_direction(self->dc, GPIO_MODE_OUTPUT); - gpio_set_level(self->dc, 0); - gpio_set_level(self->cs, 1); - - // ==== CONFIGURE SPI DEVICES(s) ==================================================================================== - - spi_lobo_bus_config_t buscfg = { - .miso_io_num = self->miso, // set SPI MISO pin - .mosi_io_num = self->mosi, // set SPI MOSI pin - .sclk_io_num = self->clk, // set SPI CLK pin - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = 6*1024, - }; - spi_lobo_device_interface_config_t devcfg = { - .clock_speed_hz = 8000000, // Initial spi clock at 8 MHz - .mode = 0, // SPI mode 0 - .spics_io_num = -1, // we will use external CS pin - .spics_ext_io_num = self->cs, // external CS pin - .flags = LB_SPI_DEVICE_HALFDUPLEX, // ALWAYS SET to HALF DUPLEX MODE!! for display spi - }; - - // ==================================================================================================================== - - // ================================================================== - // ==== Initialize the SPI bus and attach the LCD to the SPI bus ==== - - ret=spi_lobo_bus_add_device(args[ARG_host].u_int, &buscfg, &devcfg, &self->spi); - if (ret != ESP_OK) { - self->spi = NULL; - mp_raise_msg(&mp_type_OSError, "error adding spi device"); - } - - // ==== Test display select/deselect ==== - ret = spi_lobo_device_select(self->spi, 1); - if (ret != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "error selecting spi display device"); - } - ret = spi_lobo_device_deselect(self->spi); - - ts_spi = NULL; - self->tsspi = NULL; if ((args[ARG_hastouch].u_int == TOUCH_TYPE_XPT2046) || (args[ARG_hastouch].u_int == TOUCH_TYPE_STMPE610)) { - if (self->tcs >= 0) { - // === If touch is used, add it to the bus === + 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; - self->tp_type = TOUCH_TYPE_XPT2046; - spi_lobo_device_interface_config_t tsdevcfg = { - .clock_speed_hz = 2500000, // Clock out at 2.5 MHz - .mode = 0, // SPI mode 0 - .spics_io_num = self->tcs, // Touch CS pin - .spics_ext_io_num = -1, // Not using the external CS - //.command_bits = 8, // 1 byte command - }; - if (args[ARG_hastouch].u_int == TOUCH_TYPE_STMPE610) { - tsdevcfg.clock_speed_hz = 1000000; // Clock out at 1 MHz - tsdevcfg.mode = 1; // SPI mode 1 - self->tp_type = TOUCH_TYPE_STMPE610; - self->tp_calx = TP_CALX_STMPE610; - self->tp_caly = TP_CALY_STMPE610; - } - ret=spi_lobo_bus_add_device(args[ARG_host].u_int, &buscfg, &tsdevcfg, &self->tsspi); - if (ret != ESP_OK) { - ts_spi = NULL; - self->tsspi = NULL; - self->tp_type = TOUCH_TYPE_NONE; - } - - // ==== Test select/deselect ==== - ret = spi_lobo_device_select(self->tsspi, 1); - if (ret != ESP_OK) { - ts_spi = NULL; - self->tsspi = NULL; - self->tp_type = TOUCH_TYPE_NONE; - } - spi_lobo_device_deselect(self->tsspi); - } - else { - mp_printf(&mp_plat_print, "Touch panel CS pin not specified, touch not enabled!\n"); - } + } + else { + self->tp_calx = TP_CALX_STMPE610; + self->tp_caly = TP_CALY_STMPE610; + } + self->dconfig.tcs = args[ARG_tcs].u_int; } - disp_used_spi_host = args[ARG_host].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 ==== - - setupDevice(self); - TFT_display_init(); - if (self->tp_type == TOUCH_TYPE_STMPE610) { - stmpe610_Init(); + 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->spi_speed = spi_lobo_set_speed(self->spi, args[ARG_speed].u_int); + self->dconfig.speed = spi_set_speed(self->disp_spi, args[ARG_speed].u_int); max_rdclock = find_rd_speed(); - self->spi_rdspeed = max_rdclock; + self->dconfig.rdspeed = max_rdclock; font_rotate = 0; text_wrap = 0; font_transparent = 0; font_forceFixed = 0; gray_scale = 0; - TFT_setRotation(args[ARG_rot].u_int & 3); - TFT_setGammaCurve(DEFAULT_GAMMA_CURVE); + 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) { @@ -396,12 +328,24 @@ STATIC mp_obj_t display_tft_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_ TFT_print("MicroPython", CENTER, (_height/2) + (fhight/2)); _fg = intToColor(iTFT_GREEN); } - bcklOn(); + + 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) { @@ -868,8 +812,8 @@ STATIC mp_obj_t display_tft_setFont(size_t n_args, const mp_obj_t *pos_args, mp_ 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; - if (args[3].u_int >= 0) font_forceFixed = args[3].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)); @@ -912,8 +856,8 @@ STATIC mp_obj_t display_tft_setRot(size_t n_args, const mp_obj_t *pos_args, mp_m if ((rot < 0) || (rot > 3)) rot = 0; TFT_setRotation(rot); - self->width = _width; - self->height = _height; + self->dconfig.width = _width; + self->dconfig.height = _height; return mp_const_none; } @@ -928,9 +872,10 @@ STATIC mp_obj_t display_tft_print(size_t n_args, const mp_obj_t *pos_args, mp_ma { 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_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 } }, + { 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; @@ -939,19 +884,31 @@ STATIC mp_obj_t display_tft_print(size_t n_args, const mp_obj_t *pos_args, mp_ma 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 = args[0].u_int; + 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[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 (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; } @@ -996,11 +953,11 @@ STATIC mp_obj_t display_tft_clearStringRect(size_t n_args, const mp_obj_t *pos_a 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[3].u_int >= 0) _bg = intToColor(args[3].u_int); TFT_clearStringRect(x, y, st); + _bg = old_bg; return mp_const_none; @@ -1080,11 +1037,13 @@ 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_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->tsspi == NULL) { + if (self->ts_spi->handle == NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Touch not configured")); } @@ -1095,8 +1054,49 @@ STATIC mp_obj_t display_tft_getTouch(size_t n_args, const mp_obj_t *pos_args, mp 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); @@ -1114,7 +1114,7 @@ STATIC mp_obj_t display_tft_compileFont(size_t n_args, const mp_obj_t *pos_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]); + //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)]; @@ -1257,131 +1257,312 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(display_tft_getWinSize_obj, 0, display_tft_get 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_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->tp_type == TOUCH_TYPE_NONE) { + 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->tp_type == TOUCH_TYPE_XPT2046) self->tp_calx = TP_CALX_XPT2046; + 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[0].u_int == 0) { - if (self->tp_type == TOUCH_TYPE_XPT2046) self->tp_caly = TP_CALY_XPT2046; + 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_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_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) }, - // 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_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) }, - { 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) }, + // 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_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_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_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_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_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_JPG), MP_ROM_INT(IMAGE_TYPE_JPG) }, - { MP_ROM_QSTR(MP_QSTR_BMP), MP_ROM_INT(IMAGE_TYPE_BMP) }, + { 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_HSPI), MP_ROM_INT(LOBO_HSPI_HOST) }, - { MP_ROM_QSTR(MP_QSTR_VSPI), MP_ROM_INT(LOBO_VSPI_HOST) }, + { 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_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) }, + { 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); @@ -1411,4 +1592,3 @@ const mp_obj_module_t mp_module_display = { .globals = (mp_obj_dict_t*)&display_module_globals, }; -#endif // CONFIG_MICROPY_USE_DISPLAY diff --git a/MicroPython_BUILD/components/micropython/esp32/modgsm.c b/MicroPython_BUILD/components/micropython/esp32/modgsm.c index 748e1c5..db81089 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modgsm.c +++ b/MicroPython_BUILD/components/micropython/esp32/modgsm.c @@ -1,9 +1,9 @@ /* - * This file is part of the LoBo MicroPython project, https://gitgub.com/loboris + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) LoBo + * 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/esp32/modmachine.c b/MicroPython_BUILD/components/micropython/esp32/modmachine.c index 87548de..5c59195 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmachine.c +++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.c @@ -1,5 +1,5 @@ /* - * 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 * @@ -7,6 +7,7 @@ * * Copyright (c) 2013-2015 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 @@ -498,6 +499,49 @@ STATIC mp_obj_t mod_machine_logto_esp () { } 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); + 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); + SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP_FORCE); + SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_POWER_UP); + ets_delay_us(100); + SET_PERI_REG_MASK(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_DUMP_OUT); + ets_delay_us(5); + //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); + + // (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; + + mp_obj_t tuple[2]; + + tuple[0] = mp_obj_new_int_from_uint(temper); + tuple[1] = mp_obj_new_float(ftemper); + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_tsens_obj, mod_machine_tsens); + +//-------------------------------------------------------------- +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); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_machine_stdin_disable_obj, mod_machine_stdin_disable); //=============================================================== STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { @@ -515,6 +559,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { 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) }, @@ -542,6 +587,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { 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) }, diff --git a/MicroPython_BUILD/components/micropython/esp32/modmachine.h b/MicroPython_BUILD/components/micropython/esp32/modmachine.h index 6027a6f..8fe4b6f 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmachine.h +++ b/MicroPython_BUILD/components/micropython/esp32/modmachine.h @@ -1,3 +1,33 @@ +/* + * 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-2015 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 + * 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_ESP32_MODMACHINE_H #define MICROPY_INCLUDED_ESP32_MODMACHINE_H diff --git a/MicroPython_BUILD/components/micropython/esp32/modmqtt.c b/MicroPython_BUILD/components/micropython/esp32/modmqtt.c index 5703991..a34108b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modmqtt.c +++ b/MicroPython_BUILD/components/micropython/esp32/modmqtt.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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 Boris Lovosevic (https://github.com/loboris) + * 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 @@ -83,7 +83,12 @@ STATIC void connected_cb(void *self, void *params) { mqtt_client *client = (mqtt_client *)self; - if (client->settings->mpy_connected_cb) mp_sched_schedule(client->settings->mpy_connected_cb, mp_obj_new_str(client->name, strlen(client->name), 0)); + if (client->settings->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); + } } //--------------------------------------------------- @@ -91,7 +96,12 @@ STATIC void disconnected_cb(void *self, void *params) { mqtt_client *client = (mqtt_client *)self; - if (client->settings->mpy_disconnected_cb) mp_sched_schedule(client->settings->mpy_disconnected_cb, mp_obj_new_str(client->name, strlen(client->name), 0)); + if (client->settings->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); + } } //------------------------------------------------- @@ -101,12 +111,16 @@ STATIC void subscribed_cb(void *self, void *params) const char *topic = (const char *)params; if (client->settings->mpy_subscribed_cb) { - mp_obj_t tuple[2]; - tuple[0] = mp_obj_new_str(client->name, strlen(client->name), 0); - if (topic) tuple[1] = mp_obj_new_str(topic, strlen(topic), 0); - else tuple[1] = mp_obj_new_str("?", 1, 0); - - mp_sched_schedule(client->settings->mpy_subscribed_cb, mp_obj_new_tuple(2, tuple)); + 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 (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); } } @@ -117,12 +131,16 @@ STATIC void unsubscribed_cb(void *self, void *params) const char *topic = (const char *)params; if (client->settings->mpy_unsubscribed_cb) { - mp_obj_t tuple[2]; - tuple[0] = mp_obj_new_str(client->name, strlen(client->name), 0); - if (topic) tuple[1] = mp_obj_new_str(topic, strlen(topic), 0); - else tuple[1] = mp_obj_new_str("?", 1, 0);; - - mp_sched_schedule(client->settings->mpy_unsubscribed_cb, mp_obj_new_tuple(2, tuple)); + 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 (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); } } @@ -133,11 +151,16 @@ STATIC void published_cb(void *self, void *params) const char *type = (const char *)params; if (client->settings->mpy_published_cb) { - mp_obj_t tuple[2]; - tuple[0] = mp_obj_new_str(client->name, strlen(client->name), 0); - if (type) tuple[1] = mp_obj_new_str(type, strlen(type), 0); - else tuple[1] = mp_obj_new_str("?", 1, 0); - mp_sched_schedule(client->settings->mpy_published_cb, mp_obj_new_tuple(2, tuple)); + 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; + } + 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); } } @@ -150,13 +173,13 @@ STATIC void data_cb(void *self, void *params) mqtt_event_data_t *event_data = (mqtt_event_data_t *)params; if (event_data->data_offset == 0) { - // First block of data + // *** 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) { - // more data will follow, allocate the data buffer and copy the first part + // === 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); @@ -176,27 +199,30 @@ STATIC void data_cb(void *self, void *params) } } else { - // all data received, we can schedule the callback function now - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_str(client->name, strlen(client->name), 0); - tuple[1] = mp_obj_new_str(event_data->topic, event_data->topic_length, 0); - tuple[2] = mp_obj_new_str(event_data->data, event_data->data_length, 0); - mp_sched_schedule(client->settings->mpy_data_cb, mp_obj_new_tuple(3, tuple)); + // === 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); } } else { if ((client->topicbuf) && (client->msgbuf)) { - // more payload data arrived, add to buffer + // === 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) { - // all data received, we can schedule the callback function now - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_str(client->name, strlen(client->name), 0); - tuple[1] = mp_obj_new_str((const char*)client->topicbuf, strlen((const char *)client->topicbuf), 0); - tuple[2] = mp_obj_new_str((const char*)client->msgbuf, event_data->data_total_length, 0); - mp_sched_schedule(client->settings->mpy_data_cb, mp_obj_new_tuple(3, tuple)); + // === 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); +freebufs: // Free the buffers free(client->msgbuf); free(client->topicbuf); @@ -205,7 +231,7 @@ STATIC void data_cb(void *self, void *params) } } else { - // more payload data arrived, but there is no data buffers ?? + // 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; @@ -441,7 +467,7 @@ 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) { mqtt_obj_t *self = self_in; - if (checkClient(self)) return mp_const_none; + if (checkClient(self)) return mp_const_false; const char *topic = mp_obj_str_get_str(topic_in); int wait = 2000; @@ -459,7 +485,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(mqtt_subscribe_obj, 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_none; + if (checkClient(self)) return mp_const_false; const char *topic = mp_obj_str_get_str(topic_in); int wait = 2000; @@ -477,7 +503,7 @@ 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) { mqtt_obj_t *self = self_in; - if (checkClient(self)) return mp_const_none; + if (checkClient(self)) return mp_const_false; size_t len; const char *topic = mp_obj_str_get_str(topic_in); diff --git a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c index 765fc57..2424de7 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modnetwork.c +++ b/MicroPython_BUILD/components/micropython/esp32/modnetwork.c @@ -1,5 +1,5 @@ /* - * 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 * and Mnemote Pty Ltd @@ -8,6 +8,7 @@ * * Copyright (c) 2016, 2017 Nick Moore @mnemote * Copyright (c) 2017 "Eric Poulsen" + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Based on esp8266/modnetwork.c which is Copyright (c) 2015 Paul Sokolovsky * And the ESP IDF example code which is Public Domain / CC0 @@ -152,15 +153,21 @@ static inline void esp_exceptions(esp_err_t e) { #define ESP_EXCEPTIONS(x) do { esp_exceptions(x); } while (0); +// global variables +bool wifi_sta_isconnected = false; +bool wifi_sta_has_ipaddress = false; +bool wifi_sta_changed_ipaddress = false; +bool wifi_ap_isconnected = false; + 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}; -//static wifi_config_t wifi_ap_config = {{{0}}}; -static wifi_config_t wifi_sta_config = {{{0}}}; +//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 reassociation. +// user, used for automatic reconnect. static bool wifi_sta_connected = false; static uint8_t _isConnected = 0; @@ -169,8 +176,6 @@ static mp_obj_t event_callback = NULL; static mp_obj_t probereq_callback = NULL; static QueueHandle_t wifi_mutex = NULL; -#ifdef INCLUDE_PROBEREQRECVED - static QueueHandle_t probereq_mutex = NULL; //------------------------------------------------------------------------ @@ -178,103 +183,156 @@ static void processPROBEREQRECVED(const uint8_t *frame, int len, int rssi) { if (probereq_callback != NULL) { if (probereq_mutex) xSemaphoreTake(probereq_mutex, 1000); - //mp_obj_t tuple[3]; - mp_obj_dict_t *dct = mp_obj_new_dict(0); - mp_obj_dict_store(dct, mp_obj_new_str("rssi", 4, false), mp_obj_new_int(rssi)); - mp_obj_dict_store(dct, mp_obj_new_str("len", 3, false), mp_obj_new_int(len)); - mp_obj_dict_store(dct, mp_obj_new_str("frame", 5, false), mp_obj_new_str((const char*)frame, len, false)); - //tuple[0] = mp_obj_new_int(SYSTEM_EVENT_AP_PROBEREQRECVED); - //tuple[1] = mp_obj_new_str("Receive probe request packet", 28, false); - //tuple[2] = dct; + mp_sched_carg_t *carg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) goto end; + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_INT, rssi, NULL, "rssi")) goto end; + if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_INT, len, NULL, "len")) goto end; + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_STR, len, frame, "frame")) goto end; - mp_sched_schedule(probereq_callback, dct); //mp_obj_new_tuple(3, tuple)); + mp_sched_schedule(probereq_callback, mp_const_none, carg); +end: if (probereq_mutex) xSemaphoreGive(probereq_mutex); } } -#endif - //------------------------------------------------------ static void processEvent_callback(system_event_t *event) { - if (event_callback == NULL) return; if (event->event_id >= SYSTEM_EVENT_MAX) return; - mp_obj_t tuple[3]; - tuple[0] = mp_obj_new_int(event->event_id); - tuple[1] = mp_obj_new_str(wifi_events[event->event_id], strlen(wifi_events[event->event_id]), false); - tuple[2] = mp_const_none; + mp_sched_carg_t *carg = NULL; + if (event_callback) { + carg = make_cargs(MP_SCHED_CTYPE_TUPLE); + if (carg == NULL) return; + if (!make_carg_entry(carg, 0, MP_SCHED_ENTRY_TYPE_INT, event->event_id, NULL, NULL)) return; + if (!make_carg_entry(carg, 1, MP_SCHED_ENTRY_TYPE_STR, strlen(wifi_events[event->event_id]), (const uint8_t *)wifi_events[event->event_id], NULL)) return; + } + switch (event->event_id) { case SYSTEM_EVENT_STA_CONNECTED: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_sta_connected_t *info = (system_event_sta_connected_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("ssid", 4, false), mp_obj_new_str((const char*)info->ssid, info->ssid_len, false)); - mp_obj_dict_store(dct, mp_obj_new_str("channel", 7, false), mp_obj_new_int(info->channel)); - tuple[2] = dct; + wifi_sta_isconnected = true; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_STR, info->ssid_len, info->ssid, "ssid")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_INT, info->channel, NULL, "channel")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } break; } case SYSTEM_EVENT_STA_DISCONNECTED: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_sta_disconnected_t *info = (system_event_sta_disconnected_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("ssid", 4, false), mp_obj_new_str((const char*)info->ssid, info->ssid_len, false)); - mp_obj_dict_store(dct, mp_obj_new_str("reason", 6, false), mp_obj_new_int(info->reason)); - tuple[2] = dct; + wifi_sta_isconnected = false; + wifi_sta_has_ipaddress = false; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_STR, info->ssid_len, info->ssid, "ssid")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_INT, info->reason, NULL, "reason")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } break; } + case SYSTEM_EVENT_AP_START: { + wifi_ap_isconnected = true; + break; + } + case SYSTEM_EVENT_AP_STOP: { + wifi_ap_isconnected = false; + break; + } case SYSTEM_EVENT_AP_STACONNECTED: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_ap_staconnected_t *info = (system_event_ap_staconnected_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("mac", 3, false), mp_obj_new_bytes(info->mac, 6)); - mp_obj_dict_store(dct, mp_obj_new_str("aid", 3, false), mp_obj_new_int(info->aid)); - tuple[2] = dct; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_BYTES, 6, info->mac, "mac")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_INT, info->aid, NULL, "aid")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } break; } case SYSTEM_EVENT_AP_STADISCONNECTED: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_ap_stadisconnected_t *info = (system_event_ap_stadisconnected_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("mac", 3, false), mp_obj_new_bytes(info->mac, 6)); - mp_obj_dict_store(dct, mp_obj_new_str("aid", 3, false), mp_obj_new_int(info->aid)); - tuple[2] = dct; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_BYTES, 6, info->mac, "mac")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_INT, info->aid, NULL, "aid")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } break; } case SYSTEM_EVENT_AP_PROBEREQRECVED: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_ap_probe_req_rx_t *info = (system_event_ap_probe_req_rx_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("rssi", 4, false), mp_obj_new_int(info->rssi)); - mp_obj_dict_store(dct, mp_obj_new_str("mac", 3, false), mp_obj_new_bytes(info->mac, 6)); - tuple[2] = dct; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_INT, info->rssi, NULL, "rssi")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_BYTES, 6, info->mac, "mac")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } break; } case SYSTEM_EVENT_STA_GOT_IP: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_sta_got_ip_t *info = (system_event_sta_got_ip_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("ip", 2, false), netutils_format_ipv4_addr((uint8_t*)&info->ip_info.ip, NETUTILS_BIG)); - mp_obj_dict_store(dct, mp_obj_new_str("changed", 7, false), mp_obj_new_bool(info->ip_changed)); - tuple[2] = dct; + wifi_sta_has_ipaddress = true; + wifi_sta_changed_ipaddress = info->ip_changed; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + char ip_str[16]; + mp_uint_t ip_len; + uint8_t *ip = (uint8_t*)&info->ip_info.ip; + ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_STR, ip_len, (const uint8_t *)ip_str, "ip")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_BOOL, info->ip_changed, NULL, "changed")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } + 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; } case SYSTEM_EVENT_SCAN_DONE: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_sta_scan_done_t *info = (system_event_sta_scan_done_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("status", 6, false), mp_obj_new_int(info->status)); - mp_obj_dict_store(dct, mp_obj_new_str("number", 6, false), mp_obj_new_int(info->number)); - mp_obj_dict_store(dct, mp_obj_new_str("scan_id", 7, false), mp_obj_new_int(info->scan_id)); - tuple[2] = dct; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_INT, info->status, NULL, "status")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_INT, info->number, NULL, "number")) break; + if (!make_carg_entry(darg, 2, MP_SCHED_ENTRY_TYPE_INT, info->scan_id, NULL, "scan_id")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } break; } case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: { - mp_obj_dict_t *dct = mp_obj_new_dict(0); system_event_sta_authmode_change_t *info = (system_event_sta_authmode_change_t *)&event->event_info; - mp_obj_dict_store(dct, mp_obj_new_str("old_mode", 8, false), mp_obj_new_int(info->old_mode)); - mp_obj_dict_store(dct, mp_obj_new_str("new_mode", 8, false), mp_obj_new_int(info->new_mode)); - tuple[2] = dct; + if (event_callback) { + mp_sched_carg_t *darg = make_cargs(MP_SCHED_CTYPE_DICT); + if (!carg) break; + if (!make_carg_entry(darg, 0, MP_SCHED_ENTRY_TYPE_INT, info->old_mode, NULL, "old_mode")) break; + if (!make_carg_entry(darg, 1, MP_SCHED_ENTRY_TYPE_INT, info->new_mode, NULL, "new_mode")) break; + if (!make_carg_entry_carg(carg, 2, darg)) break; + } break; } default: break; } - mp_sched_schedule(event_callback, mp_obj_new_tuple(3, tuple)); + if (carg) { + if (carg->n < 3) { + // the 3rd tuple item was not added, add it now + if (!make_carg_entry(carg, 2, MP_SCHED_ENTRY_TYPE_NONE, 0, NULL, NULL)) return; + } + mp_sched_schedule(event_callback, mp_const_none, carg); + } } // This function is called by the system-event task and so runs in a different @@ -337,7 +395,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) mdns_handle_system_event(ctx, event); #endif - // Handle events callback + // === Handle events callbacks === processEvent_callback(event); if (wifi_mutex) xSemaphoreGive(wifi_mutex); @@ -351,6 +409,7 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) } */ +//--------------------------------------------------- STATIC void require_if(mp_obj_t wlan_if, int if_no) { wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if); if (self->if_id != if_no) { @@ -358,6 +417,7 @@ 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) { @@ -381,9 +441,11 @@ STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) { } 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) { @@ -393,13 +455,13 @@ STATIC mp_obj_t esp_initialize() { ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) ); ESP_LOGD("modnetwork", "esp_event_loop_init done"); + // create mutex's if (wifi_mutex == NULL) wifi_mutex = xSemaphoreCreateMutex(); - - #ifdef INCLUDE_PROBEREQRECVED if (probereq_mutex == NULL) probereq_mutex = xSemaphoreCreateMutex(); + // add probe requests handler esp_wifi_set_sta_rx_probe_req(processPROBEREQRECVED); - #endif - initialized = 1; + + initialized = 1; } return mp_const_none; } @@ -409,6 +471,7 @@ 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]); @@ -424,11 +487,15 @@ STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) { return (mode & bit) ? mp_const_true : mp_const_false; } - STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active); +//---------------------------------------------------------------- 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; + mp_uint_t len; const char *p; if (n_args > 1) { @@ -439,6 +506,7 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) { 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) ); } + MP_THREAD_GIL_EXIT(); ESP_EXCEPTIONS( esp_wifi_connect() ); MP_THREAD_GIL_ENTER(); @@ -446,23 +514,23 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) { return mp_const_none; } - 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() ); 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) { return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_status_obj, esp_status); +//------------------------------------------ STATIC mp_obj_t esp_scan(mp_obj_t self_in) { // check that STA mode is active wifi_mode_t mode; @@ -498,9 +566,9 @@ STATIC mp_obj_t esp_scan(mp_obj_t self_in) { } return list; } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan); +//------------------------------------------------- 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) { @@ -516,6 +584,7 @@ STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected); +//----------------------------------------------------------------- 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]); tcpip_adapter_ip_info_t info; @@ -543,18 +612,20 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { // etc... uint32_t* m = (uint32_t*)&info.netmask; *m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1]))); - } else { + } + else { netutils_parse_ipv4_addr(items[1], (void*)&info.netmask, NETUTILS_BIG); } netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG); 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) { + if ((self->if_id == WIFI_IF_STA) || (self->if_id == ESP_IF_ETH)) { esp_err_t e = tcpip_adapter_dhcpc_stop(self->if_id); if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e); ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(self->if_id, &info)); ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info)); - } else if (self->if_id == WIFI_IF_AP) { + } + else if (self->if_id == WIFI_IF_AP) { esp_err_t e = tcpip_adapter_dhcps_stop(WIFI_IF_AP); if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e); ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(WIFI_IF_AP, &info)); @@ -564,9 +635,9 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) { return mp_const_none; } } - MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig); +//--------------------------------------------------------------------------------- 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) { mp_raise_TypeError("either pos or kw args are allowed"); @@ -646,9 +717,8 @@ 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 param"); + mp_raise_TypeError("can query only one parameter"); } int req_if = -1; @@ -691,8 +761,8 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs unknown: mp_raise_ValueError("unknown config param"); + return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config); //--------------------------------------------------------------- @@ -714,7 +784,6 @@ STATIC mp_obj_t esp_callback(size_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_callback_obj, 1, 2, esp_callback); -#ifdef INCLUDE_PROBEREQRECVED //------------------------------------------------------------------------ STATIC mp_obj_t esp_probereq_callback(size_t n_args, const mp_obj_t *args) { @@ -733,8 +802,9 @@ STATIC mp_obj_t esp_probereq_callback(size_t n_args, const mp_obj_t *args) return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_probereq_callback_obj, 1, 2, esp_probereq_callback); -#endif + +//======================================================== 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 }, @@ -745,13 +815,11 @@ STATIC const mp_map_elem_t wlan_if_locals_dict_table[] = { { 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 }, - #ifdef INCLUDE_PROBEREQRECVED { MP_OBJ_NEW_QSTR(MP_QSTR_probereqCB), (mp_obj_t)&esp_probereq_callback_obj }, - #endif }; - STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table); +//---------------------------------- const mp_obj_type_t wlan_if_type = { { &mp_type_type }, .name = MP_QSTR_WLAN, diff --git a/MicroPython_BUILD/components/micropython/esp32/modnetwork.h b/MicroPython_BUILD/components/micropython/esp32/modnetwork.h index 50801e9..028ea1b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modnetwork.h +++ b/MicroPython_BUILD/components/micropython/esp32/modnetwork.h @@ -1,9 +1,10 @@ /* - * 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 "Eric Poulsen" + * 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,8 +27,6 @@ #ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H #define MICROPY_INCLUDED_ESP32_MODNETWORK_H -//#define INCLUDE_PROBEREQRECVED - enum { PHY_LAN8720, PHY_TLK110 }; typedef struct _wlan_if_obj_t { @@ -35,13 +34,16 @@ typedef struct _wlan_if_obj_t { int if_id; } wlan_if_obj_t; -#ifdef INCLUDE_PROBEREQRECVED 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); -#endif extern const mp_obj_type_t wlan_if_type; +extern bool wifi_sta_isconnected; +extern bool wifi_sta_has_ipaddress; +extern bool wifi_sta_changed_ipaddress; +extern bool wifi_ap_isconnected; + #ifdef CONFIG_MICROPY_USE_ETHERNET MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj); #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/modota.c b/MicroPython_BUILD/components/micropython/esp32/modota.c index 409e25a..2adc7ab 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modota.c +++ b/MicroPython_BUILD/components/micropython/esp32/modota.c @@ -1,9 +1,9 @@ /* - * This file is part of the LoBo MicroPython project, https://gitgub.com/loboris + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) LoBo + * 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/esp32/modsocket.c b/MicroPython_BUILD/components/micropython/esp32/modsocket.c index 9385c07..e8891b9 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modsocket.c +++ b/MicroPython_BUILD/components/micropython/esp32/modsocket.c @@ -1,5 +1,5 @@ /* - * 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 * and Mnemote Pty Ltd @@ -11,6 +11,7 @@ * Based on extmod/modlwip.c * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Galen Hazelwood + * 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/esp32/modssh.c b/MicroPython_BUILD/components/micropython/esp32/modssh.c index 0eaf939..4b66b54 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modssh.c +++ b/MicroPython_BUILD/components/micropython/esp32/modssh.c @@ -1,12 +1,9 @@ /* - * This file is part of the MicroPython project, http://micropython.org/ - * - * Development of the code in this file was sponsored by Microbric Pty Ltd + * This file is part of the MicroPython ESP32 project, https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo * * The MIT License (MIT) * - * Copyright (c) 2013-2015 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/esp32/modules/ak8963.py b/MicroPython_BUILD/components/micropython/esp32/modules/ak8963.py new file mode 100644 index 0000000..7eb3af7 --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules/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(" 3000: + return (False, False) + utime.sleep_ms(10) + + xlist.remove(max(xlist)) + xlist.remove(min(xlist)) + ylist.remove(max(ylist)) + ylist.remove(min(ylist)) + return (sum(xlist) / len(xlist), sum(ylist) / len(ylist)) #---------------------------- def calibrate(self, x, y, i): self.drawCrossHair(x,y, self.tft.YELLOW) - self.rx[i], self.ry[i] = self.readCoordinates() + rx, ry = self.readCoordinates() + if rx == False: + return False + self.rx[i] = rx + self.ry[i] = ry self.drawCrossHair(x,y,self.tft.GREEN) + return True - #------------------------------------- - def tpcalib(self, tptype, save=False): - if tptype == self.tft.TOUCH_XPT: + # ------------------- + def calibError(self): + self.tft.clear() + self.tft.font(self.tft.FONT_Default, rotate=0, fixedwidth=False) + self.tft.text(self.tft.CENTER, self.tft.CENTER, "Calibration ERROR", self.tft.ORANGE) + print("Calibration ERROR.") + + #----------------------------- + def tpcalib(self, save=False): + if self.tft.getTouchType() == self.tft.TOUCH_XPT: self.tft.orient(display.TFT.LANDSCAPE) - if tptype == self.tft.TOUCH_STMPE: + elif self.tft.getTouchType() == self.tft.TOUCH_STMPE: self.tft.orient(display.TFT.PORTRAIT) else: - print("Wrong touch type, use tft.TOUCH_XPT or TOUCH_STMPE") + print("Touch not configured") return dispx, dispy = self.tft.screensize() @@ -75,18 +95,34 @@ class Calibrate: self.drawCrossHair(dispx//2, dispy-11, self.tft.WHITE) self.drawCrossHair(10, dispy-11, self.tft.WHITE) - self.calibrate(10, 10, 0) - self.calibrate(10, dispy//2, 1) - self.calibrate(10, dispy-11, 2) - self.calibrate(dispx//2, 10, 3) - self.calibrate(dispx//2, dispy-11, 4) - self.calibrate(dispx-11, 10, 5) - self.calibrate(dispx-11, dispy//2, 6) - self.calibrate(dispx-11, dispy-11, 7) + if not self.calibrate(10, 10, 0): + self.calibError() + return False + if not self.calibrate(10, dispy//2, 1): + self.calibError() + return False + if not self.calibrate(10, dispy-11, 2): + self.calibError() + return False + if not self.calibrate(dispx//2, 10, 3): + self.calibError() + return False + if not self.calibrate(dispx//2, dispy-11, 4): + self.calibError() + return False + if not self.calibrate(dispx-11, 10, 5): + self.calibError() + return False + if not self.calibrate(dispx-11, dispy//2, 6): + self.calibError() + return False + if not self.calibrate(dispx-11, dispy-11, 7): + self.calibError() + return False - px = abs((((self.rx[3]+self.rx[4]+self.rx[7]) / 3) - ((self.rx[0]+self.rx[0]+self.rx[2]) / 3)) / (dispy-20)) # LANDSCAPE - clx = (((self.rx[0]+self.rx[1]+self.rx[2])/3)) # LANDSCAPE - crx = (((self.rx[5]+self.rx[6]+self.rx[7])/3)) # LANDSCAPE + px = abs((((self.rx[3]+self.rx[4]+self.rx[7]) / 3) - ((self.rx[0]+self.rx[0]+self.rx[2]) / 3)) / (dispy-20)) + clx = (((self.rx[0]+self.rx[1]+self.rx[2])/3)) + crx = (((self.rx[5]+self.rx[6]+self.rx[7])/3)) if (clx < crx): clx = clx - (px*10) @@ -95,9 +131,9 @@ class Calibrate: clx = clx + (px*10) crx = crx - (px*10) - py = abs((((self.ry[0]+self.ry[3]+self.ry[5])/3) - ((self.ry[2]+self.ry[4]+self.ry[7])/3))/(dispx-20)) # LANDSCAPE - cty = (((self.ry[0]+self.ry[3]+self.ry[5])/3)) # LANDSCAPE - cby = (((self.ry[2]+self.ry[4]+self.ry[7])/3)) # LANDSCAPE + py = abs((((self.ry[0]+self.ry[3]+self.ry[5])/3) - ((self.ry[2]+self.ry[4]+self.ry[7])/3))/(dispx-20)) + cty = (((self.ry[0]+self.ry[3]+self.ry[5])/3)) + cby = (((self.ry[2]+self.ry[4]+self.ry[7])/3)) if (cty < cby): cty = cty - (py*10) @@ -111,14 +147,15 @@ class Calibrate: self.tft.clear() self.tft.font(self.tft.FONT_Default, rotate=0, fixedwidth=False) - self.tft.text(self.tft.CENTER, self.tft.CENTER, "Calibration completed") + self.tft.text(self.tft.CENTER, self.tft.CENTER, "Calibration completed\n") if save: self.tft.setCalib(calx, caly) machine.nvs_setint("tpcalibX", calx) machine.nvs_setint("tpcalibY", caly) + self.tft.text(self.tft.CENTER, self.tft.LAST_Y, "Saved to NVS", self.tft.ORANGE) print("Calibration completed and saved to NVS memory.") else: print("Calibration completed.") - print("X:", math.ceil(clx), math.ceil(crx), "Y:", math.ceil(cty), math.ceil(cby)) + print("X = ({},{}) Y = ({},{})".format(math.ceil(clx), math.ceil(crx), math.ceil(cty), math.ceil(cby))) return calx, caly diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/README.md b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/README.md index 3962eb5..8d00a5f 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/README.md +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/README.md @@ -40,7 +40,7 @@ uint8_t vera18[] PROGMEM = to: ``` -unsigned char vera18[] = +const unsigned char vera18[] = ``` The font name (**vera18** here) will be different for different font, you can change it to any other name. diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/UbuntuMono-B.ttf b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/UbuntuMono-B.ttf new file mode 100644 index 0000000..7bd6665 Binary files /dev/null and b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/UbuntuMono-B.ttf differ diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/ubuntu_mono.c b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/ubuntu_mono.c new file mode 100644 index 0000000..89de2be --- /dev/null +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/font_tool/ubuntu_mono.c @@ -0,0 +1,635 @@ +// This comes with no warranty, implied or otherwise + +// This data structure was designed to support Proportional fonts +// on Arduinos. It can however handle any ttf font that has been converted +// using the conversion program. These could be fixed width or proportional +// fonts. Individual characters do not have to be multiples of 8 bits wide. +// Any width is fine and does not need to be fixed. + +// The data bits are packed to minimize data requirements, but the tradeoff +// is that a header is required per character. + +// ubuntu_mono.c +// Point Size : 14 +// Memory usage : 2963 bytes +// # characters : 225 + +// Header Format (to make Arduino UTFT Compatible): +// ------------------------------------------------ +// Character Width (Used as a marker to indicate use this format. i.e.: = 0x00) +// Character Height +// First Character (Reserved. 0x00) +// Number Of Characters (Reserved. 0x00) + + +const unsigned char tft_ubuntu_mono[] = +{ +0x00, 0x0D, 0x00, 0x00, + +// Individual Character Format: +// ---------------------------- +// Character Code +// Adjusted Y Offset +// Width +// Height +// xOffset +// xDelta (the distance to move the cursor. Effective width of the character.) +// Data[n] + +// NOTE: You can remove any of these characters if they are not needed in +// your application. The first character number in each Glyph indicates +// the ASCII character code. Therefore, these do not have to be sequential. +// Just remove all the content for a particular character to save space. + +// ' ' +0x20,0x0D,0x00,0x00,0x00,0x07, + +// '!' +0x21,0x04,0x02,0x09,0x03,0x07, +0xFF,0xF3,0xC0, +// '"' +0x22,0x03,0x05,0x04,0x00,0x07, +0xDE,0xF7,0xB0, +// '#' +0x23,0x04,0x07,0x09,0x00,0x07, +0x14,0x2B,0xFF,0xF2,0x9F,0xFF,0xA8,0x50, +// '$' +0x24,0x03,0x06,0x0B,0x00,0x07, +0x31,0xEF,0xF0,0xF1,0xE1,0xC3,0xFD,0xC3,0x00, +// '%' +0x25,0x04,0x07,0x09,0x00,0x07, +0x45,0x52,0xA3,0x82,0x04,0x92,0xA5,0x8C, +// '&' +0x26,0x04,0x08,0x09,0x00,0x07, +0x30,0x78,0x48,0x70,0x74,0xDC,0xCC,0xFC,0x7E, +// ''' +0x27,0x03,0x02,0x04,0x01,0x07, +0xFF, +// '(' +0x28,0x03,0x05,0x0C,0x01,0x07, +0x19,0x98,0xCC,0x63,0x18,0x63,0x0C,0x30, +// ')' +0x29,0x03,0x05,0x0C,0x01,0x07, +0xC3,0x0C,0x61,0x8C,0x63,0x31,0x98,0x80, +// '*' +0x2A,0x04,0x05,0x05,0x01,0x07, +0x25,0x7E,0x47,0x00, +// '+' +0x2B,0x06,0x06,0x06,0x00,0x07, +0x30,0xCF,0xFF,0x30,0xC0, +// ',' +0x2C,0x0A,0x03,0x05,0x02,0x07, +0xFD,0x88, +// '-' +0x2D,0x09,0x04,0x02,0x02,0x07, +0xFF, +// '.' +0x2E,0x0A,0x03,0x03,0x02,0x07, +0xFF,0x80, +// '/' +0x2F,0x03,0x06,0x0C,0x00,0x07, +0x0C,0x31,0x86,0x18,0xC3,0x0C,0x31,0x86,0x18, +// '0' +0x30,0x04,0x06,0x09,0x00,0x07, +0x79,0xEC,0xFF,0xFF,0x3C,0xDE,0x78, +// '1' +0x31,0x04,0x06,0x09,0x00,0x07, +0x31,0xCF,0x0C,0x30,0xC3,0x3F,0xFC, +// '2' +0x32,0x04,0x06,0x09,0x00,0x07, +0x39,0xF0,0xC3,0x18,0xC2,0x1F,0x7C, +// '3' +0x33,0x04,0x05,0x09,0x01,0x07, +0x77,0xC6,0xE7,0x0C,0x7F,0xF0, +// '4' +0x34,0x04,0x07,0x09,0x00,0x07, +0x0C,0x38,0xF3,0x6C,0xDF,0xFF,0x86,0x0C, +// '5' +0x35,0x04,0x06,0x09,0x00,0x07, +0x7D,0xF6,0x1E,0x7C,0x30,0xFF,0xF8, +// '6' +0x36,0x04,0x06,0x09,0x00,0x07, +0x1D,0xF6,0x3C,0xFF,0x3C,0xFF,0x78, +// '7' +0x37,0x04,0x06,0x09,0x00,0x07, +0xFF,0xF0,0xC6,0x30,0xC3,0x18,0x60, +// '8' +0x38,0x04,0x06,0x09,0x00,0x07, +0x7B,0xFC,0xF3,0x7B,0x7C,0xFF,0x78, +// '9' +0x39,0x04,0x05,0x09,0x01,0x07, +0x77,0xF7,0xBF,0xBC,0xEE,0x60, +// ':' +0x3A,0x06,0x03,0x07,0x02,0x07, +0xFF,0x8F,0xF8, +// ';' +0x3B,0x06,0x03,0x09,0x02,0x07, +0xFF,0x8F,0xD8,0x80, +// '<' +0x3C,0x03,0x06,0x09,0x00,0x07, +0x04,0x73,0xDC,0x61,0xC3,0xC7,0x04, +// '=' +0x3D,0x07,0x05,0x05,0x01,0x07, +0xFF,0xC1,0xFF,0x80, +// '>' +0x3E,0x03,0x05,0x09,0x01,0x07, +0x86,0x3C,0x71,0x9F,0xD8,0x80, +// '?' +0x3F,0x04,0x05,0x09,0x01,0x07, +0x77,0xC6,0x33,0x30,0x0C,0x60, +// '@' +0x40,0x04,0x07,0x0B,0x00,0x07, +0x3C,0x87,0x7D,0xFB,0x36,0xED,0xDF,0xDE,0x80,0xF0, +// 'A' +0x41,0x04,0x07,0x09,0x00,0x07, +0x38,0x70,0xE1,0x66,0xCF,0x9F,0x63,0xC6, +// 'B' +0x42,0x04,0x06,0x09,0x00,0x07, +0xFB,0xFC,0xFE,0xFF,0x3C,0xFF,0xF8, +// 'C' +0x43,0x04,0x06,0x09,0x00,0x07, +0x39,0xFE,0x70,0xC3,0x0E,0x5F,0x38, +// 'D' +0x44,0x04,0x06,0x09,0x00,0x07, +0xF3,0xED,0xF3,0xCF,0x3D,0xFE,0xF0, +// 'E' +0x45,0x04,0x05,0x09,0x01,0x07, +0xFF,0xF1,0xEF,0x63,0x1F,0xF8, +// 'F' +0x46,0x04,0x05,0x09,0x01,0x07, +0xFF,0xF1,0x8F,0xFF,0x18,0xC0, +// 'G' +0x47,0x04,0x06,0x09,0x00,0x07, +0x3D,0xFE,0x30,0xCF,0x3E,0xDF,0x3C, +// 'H' +0x48,0x04,0x06,0x09,0x00,0x07, +0xCF,0x3C,0xFF,0xFF,0x3C,0xF3,0xCC, +// 'I' +0x49,0x04,0x06,0x09,0x00,0x07, +0xFF,0xF3,0x0C,0x30,0xC3,0x3F,0xFC, +// 'J' +0x4A,0x04,0x05,0x09,0x01,0x07, +0xFF,0xC6,0x31,0x8C,0x7F,0x70, +// 'K' +0x4B,0x04,0x06,0x09,0x01,0x07, +0xCF,0x6D,0xBC,0xF3,0xCD,0xB6,0xCC, +// 'L' +0x4C,0x04,0x05,0x09,0x00,0x07, +0xC6,0x31,0x8C,0x63,0x1F,0xF8, +// 'M' +0x4D,0x04,0x06,0x09,0x01,0x07, +0xCB,0x2F,0xBF,0xFF,0xFC,0xF3,0xCC, +// 'N' +0x4E,0x04,0x06,0x09,0x00,0x07, +0xCF,0x3E,0xFB,0xDF,0x7D,0xF3,0xCC, +// 'O' +0x4F,0x04,0x06,0x09,0x00,0x07, +0x79,0xEC,0xF3,0xCF,0x3C,0xDE,0x78, +// 'P' +0x50,0x04,0x06,0x09,0x00,0x07, +0xFB,0xFC,0xF3,0xFF,0xEC,0x30,0xC0, +// 'Q' +0x51,0x04,0x06,0x0B,0x00,0x07, +0x79,0xEC,0xF3,0xCF,0x3C,0xDE,0x78,0xF0,0xC0, +// 'R' +0x52,0x04,0x06,0x09,0x00,0x07, +0xFB,0xFC,0xF3,0xFF,0xCD,0xB6,0xCC, +// 'S' +0x53,0x04,0x06,0x09,0x00,0x07, +0x7F,0xFC,0x3C,0x78,0x78,0xFF,0x78, +// 'T' +0x54,0x04,0x06,0x09,0x00,0x07, +0xFF,0xF3,0x0C,0x30,0xC3,0x0C,0x30, +// 'U' +0x55,0x04,0x06,0x09,0x00,0x07, +0xCF,0x3C,0xF3,0xCF,0x3C,0xFF,0x78, +// 'V' +0x56,0x04,0x06,0x09,0x00,0x07, +0xCF,0x3C,0xD2,0x49,0xE7,0x8C,0x30, +// 'W' +0x57,0x04,0x06,0x09,0x00,0x07, +0xCF,0x3C,0xFF,0xFF,0xFF,0xF3,0xCC, +// 'X' +0x58,0x04,0x07,0x09,0x00,0x07, +0xC6,0xD9,0xF1,0xC3,0x87,0x1B,0x36,0xC6, +// 'Y' +0x59,0x04,0x06,0x09,0x00,0x07, +0xCF,0x36,0x9E,0x30,0xC3,0x0C,0x30, +// 'Z' +0x5A,0x04,0x05,0x09,0x00,0x07, +0xFF,0xC4,0x62,0x21,0x1F,0xF8, +// '[' +0x5B,0x03,0x04,0x0C,0x02,0x07, +0xFF,0xCC,0xCC,0xCC,0xCC,0xFF, +// '\' +0x5C,0x03,0x05,0x0C,0x01,0x07, +0xC6,0x18,0xC6,0x30,0xC6,0x31,0x86,0x30, +// ']' +0x5D,0x03,0x04,0x0C,0x01,0x07, +0xFF,0x33,0x33,0x33,0x33,0xFF, +// '^' +0x5E,0x04,0x07,0x05,0x00,0x07, +0x38,0x71,0xB3,0x64,0x40, +// '_' +0x5F,0x0D,0x07,0x02,0x00,0x07, +0xFF,0xFC, +// '`' +0x60,0x03,0x03,0x02,0x02,0x07, +0xCC, +// 'a' +0x61,0x06,0x06,0x07,0x00,0x07, +0x79,0xF0,0xDF,0xCF,0xF7,0xC0, +// 'b' +0x62,0x03,0x06,0x0A,0x00,0x07, +0xC3,0x0C,0x3E,0xFF,0x3C,0xF3,0xFB,0xC0, +// 'c' +0x63,0x06,0x06,0x07,0x00,0x07, +0x3D,0xFE,0x30,0xC1,0xF3,0xC0, +// 'd' +0x64,0x03,0x06,0x0A,0x00,0x07, +0x0C,0x30,0xDF,0xFF,0x3C,0xF3,0x7D,0xF0, +// 'e' +0x65,0x06,0x07,0x07,0x00,0x07, +0x38,0xFB,0x37,0xEC,0x0F,0x8F,0x00, +// 'f' +0x66,0x03,0x07,0x0A,0x00,0x07, +0x1E,0x7C,0xC7,0xEF,0xC6,0x0C,0x18,0x30,0x60, +// 'g' +0x67,0x06,0x06,0x09,0x00,0x07, +0x7F,0xFC,0xF3,0xFD,0xF0,0xFF,0xF8, +// 'h' +0x68,0x03,0x06,0x0A,0x00,0x07, +0xC3,0x0C,0x3E,0xFF,0x3C,0xF3,0xCF,0x30, +// 'i' +0x69,0x03,0x07,0x0A,0x00,0x07, +0x30,0x60,0x07,0x8F,0x06,0x0C,0x18,0x3C,0x38, +// 'j' +0x6A,0x03,0x06,0x0C,0xFF,0x07, +0x18,0x60,0x1F,0x7C,0x30,0xC3,0x0D,0x37,0xDE, +// 'k' +0x6B,0x03,0x07,0x0A,0x00,0x07, +0xC1,0x83,0x06,0x6D,0x9E,0x3C,0x6C,0xCD,0x8C, +// 'l' +0x6C,0x03,0x06,0x0A,0x00,0x07, +0xF3,0xC3,0x0C,0x30,0xC3,0x0C,0x3C,0x70, +// 'm' +0x6D,0x06,0x07,0x07,0x00,0x07, +0xFD,0xFF,0x5E,0xBC,0x78,0xF1,0x80, +// 'n' +0x6E,0x06,0x06,0x07,0x00,0x07, +0xFB,0xFC,0xF3,0xCF,0x3C,0xC0, +// 'o' +0x6F,0x06,0x06,0x07,0x00,0x07, +0x79,0xEC,0xF3,0xCD,0xE7,0x80, +// 'p' +0x70,0x06,0x06,0x09,0x00,0x07, +0xF3,0xEC,0xF3,0xCF,0xFF,0xB0,0xC0, +// 'q' +0x71,0x06,0x06,0x09,0x00,0x07, +0x3D,0xFC,0xF3,0xCF,0xF7,0xC3,0x0C, +// 'r' +0x72,0x06,0x05,0x07,0x00,0x07, +0xFF,0xF1,0x8C,0x63,0x00, +// 's' +0x73,0x06,0x05,0x07,0x00,0x07, +0x7F,0xF0,0xE1,0xFF,0xC0, +// 't' +0x74,0x04,0x07,0x09,0x00,0x07, +0x30,0x63,0xFF,0xF3,0x06,0x0C,0x1F,0x1E, +// 'u' +0x75,0x06,0x06,0x07,0x00,0x07, +0xCF,0x3C,0xF3,0xCF,0xF7,0xC0, +// 'v' +0x76,0x06,0x06,0x07,0x00,0x07, +0xCD,0x34,0x9E,0x78,0xC3,0x00, +// 'w' +0x77,0x06,0x07,0x07,0x00,0x07, +0xC7,0xAF,0x5F,0xF6,0xCD,0x9B,0x00, +// 'x' +0x78,0x06,0x07,0x07,0x00,0x07, +0xE6,0xD8,0xE1,0xC3,0xCD,0xB1,0x80, +// 'y' +0x79,0x06,0x07,0x09,0x00,0x07, +0x66,0xCC,0xD1,0xE3,0xC3,0x06,0x08,0xE0, +// 'z' +0x7A,0x06,0x05,0x07,0x00,0x07, +0xFF,0xCC,0x44,0x7F,0xE0, +// '{' +0x7B,0x03,0x06,0x0C,0x01,0x07, +0x1C,0xF3,0x0C,0x33,0x8E,0x0C,0x30,0xC3,0xC7, +// '|' +0x7C,0x03,0x02,0x0C,0x03,0x07, +0xFF,0xFF,0xFF, +// '}' +0x7D,0x03,0x05,0x0C,0x01,0x07, +0xC7,0x18,0xC6,0x1C,0xEC,0x63,0x39,0x80, +// '~' +0x7E,0x08,0x07,0x03,0x00,0x07, +0x77,0xFF,0x70, +// '' +0x7F,0x02,0x06,0x0B,0x01,0x07, +0xFE,0x18,0x61,0x86,0x18,0x61,0x86,0x1F,0xC0, +// '' +0x80,0x02,0x06,0x0B,0x01,0x07, +0xFE,0x18,0x61,0x86,0x18,0x61,0x86,0x1F,0xC0, +// '' +0x81,0x02,0x06,0x0B,0x01,0x07, +0xFE,0x18,0x61,0x86,0x18,0x61,0x86,0x1F,0xC0, +// '' +0x82,0x02,0x06,0x0B,0x01,0x07, +0xFE,0x18,0x61,0x86,0x18,0x61,0x86,0x1F,0xC0, +// '' +0x84,0x02,0x06,0x0B,0x01,0x07, +0xFE,0x18,0x61,0x86,0x18,0x61,0x86,0x1F,0xC0, +// '' +0xA0,0x0D,0x00,0x00,0x00,0x07, + +// '' +0xA1,0x06,0x02,0x09,0x03,0x07, +0xF3,0xFF,0xC0, +// '' +0xA2,0x04,0x06,0x0B,0x00,0x07, +0x18,0x63,0xDF,0xC3,0x0C,0x1F,0x3C,0x61,0x80, +// '' +0xA3,0x04,0x05,0x09,0x01,0x07, +0x3B,0xD8,0xCF,0x79,0x8F,0x78, +// '' +0xA4,0x06,0x07,0x06,0x00,0x07, +0x44,0xF9,0x32,0x67,0xC8,0x80, +// '' +0xA5,0x04,0x07,0x09,0x00,0x07, +0xC6,0xD8,0xA1,0xC7,0xC2,0x1F,0x08,0x10, +// '' +0xA6,0x03,0x02,0x0C,0x03,0x08, +0xFF,0xC3,0xFF, +// '' +0xA7,0x04,0x05,0x0A,0x01,0x07, +0x7F,0xF1,0xED,0xED,0xE3,0xFF,0x80, +// '' +0xA8,0x03,0x05,0x02,0x01,0x07, +0xDE,0xC0, +// '' +0xA9,0x06,0x07,0x07,0x00,0x07, +0x38,0x8A,0x6D,0x19,0xA8,0x8E,0x00, +// '' +0xAA,0x04,0x05,0x05,0x01,0x07, +0xF0,0x5F,0x17,0x80, +// '' +0xAB,0x06,0x07,0x06,0x00,0x07, +0x22,0xCF,0x36,0x66,0x64,0x40, +// '' +0xAC,0x08,0x05,0x05,0x01,0x07, +0xFF,0xC2,0x10,0x80, +// '' +0xAD,0x09,0x04,0x02,0x02,0x07, +0xFF, +// '' +0xAE,0x06,0x07,0x07,0x00,0x07, +0x38,0x8A,0xED,0xDA,0xA8,0x8E,0x00, +// '' +0xAF,0x04,0x04,0x01,0x02,0x07, +0xF0, +// '' +0xB0,0x03,0x04,0x04,0x02,0x07, +0x69,0x96, +// '' +0xB1,0x04,0x06,0x09,0x01,0x07, +0x30,0xCF,0xFF,0x30,0xC0,0x3F,0xFC, +// '' +0xB2,0x04,0x03,0x05,0x02,0x07, +0xF5,0xCE, +// '' +0xB3,0x04,0x04,0x05,0x02,0x07, +0xEA,0x62,0xE0, +// '' +0xB4,0x03,0x03,0x02,0x02,0x07, +0x78, +// '' +0xB5,0x06,0x05,0x09,0x01,0x07, +0xDE,0xF7,0xBD,0xFF,0xF8,0xC0, +// '' +0xB6,0x04,0x07,0x0B,0x00,0x07, +0x7F,0xFF,0xDF,0xB7,0x66,0xCD,0x9B,0x36,0x6C,0xD8, +// '' +0xB7,0x07,0x03,0x03,0x02,0x07, +0xFF,0x80, +// '' +0xB8,0x0D,0x03,0x02,0x02,0x07, +0x3C, +// '' +0xB9,0x04,0x03,0x05,0x02,0x07, +0x59,0x2E, +// '' +0xBA,0x04,0x05,0x07,0x01,0x07, +0x77,0xE7,0x39,0xFD,0xC0, +// '' +0xBB,0x06,0x07,0x06,0x01,0x07, +0x90,0xB1,0xB3,0x65,0x92,0x00, +// '' +0xBC,0x04,0x07,0x09,0x00,0x07, +0x44,0x91,0x22,0x82,0x05,0x93,0x2F,0x84, +// '' +0xBD,0x04,0x07,0x09,0x00,0x07, +0x45,0x91,0x22,0x81,0x04,0xC8,0xA2,0x4E, +// '' +0xBE,0x04,0x07,0x09,0x00,0x07, +0xE4,0xC8,0xA7,0x41,0x02,0x8B,0x27,0x44, +// '' +0xBF,0x06,0x05,0x09,0x00,0x07, +0x31,0x80,0x66,0x63,0x3F,0x70, +// '' +0xC0,0x01,0x07,0x0C,0x00,0x07, +0x30,0x30,0x01,0xC3,0x87,0x0B,0x36,0x7C,0xFB,0x1E,0x30, +// '' +0xC1,0x01,0x07,0x0C,0x00,0x07, +0x18,0x60,0x01,0xC3,0x87,0x0B,0x36,0x7C,0xFB,0x1E,0x30, +// '' +0xC2,0x00,0x07,0x0D,0x00,0x07, +0x10,0x70,0xA0,0x03,0x87,0x0E,0x16,0x6C,0xF9,0xF6,0x3C,0x60, +// '' +0xC3,0x01,0x07,0x0C,0x00,0x07, +0x24,0xB0,0x01,0xC3,0x87,0x0B,0x36,0x7C,0xFB,0x1E,0x30, +// '' +0xC4,0x01,0x07,0x0C,0x00,0x07, +0x6C,0xD8,0x01,0xC3,0x87,0x0B,0x36,0x7C,0xFB,0x1E,0x30, +// '' +0xC5,0x01,0x07,0x0C,0x00,0x07, +0x00,0x70,0xA1,0xC3,0x87,0x0A,0x36,0x7C,0xFB,0x1E,0x30, +// '' +0xC6,0x04,0x07,0x09,0x00,0x07, +0x1E,0x7C,0xE1,0x66,0xCF,0x1E,0x67,0xCE, +// '' +0xC7,0x04,0x07,0x0B,0x00,0x07, +0x3C,0xFF,0x8E,0x0C,0x18,0x38,0x3F,0x3C,0x10,0xE0, +// '' +0xC8,0x01,0x05,0x0C,0x01,0x07, +0x61,0x81,0xFF,0xE3,0xDE,0xC6,0x3F,0xF0, +// '' +0xC9,0x01,0x05,0x0C,0x01,0x07, +0x33,0x01,0xFF,0xE3,0xDE,0xC6,0x3F,0xF0, +// '' +0xCA,0x00,0x05,0x0D,0x01,0x07, +0x23,0x94,0x0F,0xFF,0x1E,0xF6,0x31,0xFF,0x80, +// '' +0xCB,0x01,0x05,0x0C,0x01,0x07, +0xDE,0xC1,0xFF,0xE3,0xDE,0xC6,0x3F,0xF0, +// '' +0xCC,0x01,0x06,0x0C,0x00,0x07, +0x60,0xC0,0x3F,0xFC,0xC3,0x0C,0x30,0xCF,0xFF, +// '' +0xCD,0x01,0x06,0x0C,0x00,0x07, +0x31,0x80,0x3F,0xFC,0xC3,0x0C,0x30,0xCF,0xFF, +// '' +0xCE,0x00,0x06,0x0D,0x00,0x07, +0x21,0xC5,0x00,0xFF,0xF3,0x0C,0x30,0xC3,0x3F,0xFC, +// '' +0xCF,0x01,0x06,0x0C,0x00,0x07, +0x6D,0xB0,0x3F,0xFC,0xC3,0x0C,0x30,0xCF,0xFF, +// '' +0xD0,0x04,0x07,0x09,0x00,0x07, +0x78,0xF9,0xBB,0x3F,0x6C,0xDB,0xBE,0x78, +// '' +0xD1,0x01,0x06,0x0C,0x00,0x07, +0x25,0x60,0x33,0xCF,0xBE,0xF7,0xDF,0x7C,0xF3, +// '' +0xD2,0x01,0x06,0x0C,0x00,0x07, +0x60,0xC0,0x1E,0x7B,0x3C,0xF3,0xCF,0x37,0x9E, +// '' +0xD3,0x01,0x06,0x0C,0x00,0x07, +0x31,0x80,0x1E,0x7B,0x3C,0xF3,0xCF,0x37,0x9E, +// '' +0xD4,0x00,0x06,0x0D,0x00,0x07, +0x10,0xE2,0x80,0x79,0xEC,0xF3,0xCF,0x3C,0xDE,0x78, +// '' +0xD5,0x01,0x06,0x0C,0x00,0x07, +0x25,0x60,0x1E,0x7B,0x3C,0xF3,0xCF,0x37,0x9E, +// '' +0xD6,0x01,0x06,0x0C,0x00,0x07, +0x6D,0xB0,0x1E,0x7B,0x3C,0xF3,0xCF,0x37,0x9E, +// '' +0xD7,0x07,0x05,0x06,0x01,0x07, +0x8B,0x9C,0xE9,0x80, +// '' +0xD8,0x04,0x07,0x0A,0x00,0x07, +0x3C,0xFB,0x3E,0xFD,0x7E,0xFB,0xBE,0x78,0x80, +// '' +0xD9,0x01,0x06,0x0C,0x00,0x07, +0x60,0xC0,0x33,0xCF,0x3C,0xF3,0xCF,0x3F,0xDE, +// '' +0xDA,0x01,0x06,0x0C,0x00,0x07, +0x18,0xC0,0x33,0xCF,0x3C,0xF3,0xCF,0x3F,0xDE, +// '' +0xDB,0x00,0x06,0x0D,0x00,0x07, +0x10,0xE2,0x80,0xCF,0x3C,0xF3,0xCF,0x3C,0xFF,0x78, +// '' +0xDC,0x01,0x06,0x0C,0x00,0x07, +0x6D,0xB0,0x33,0xCF,0x3C,0xF3,0xCF,0x3F,0xDE, +// '' +0xDD,0x01,0x06,0x0C,0x00,0x07, +0x18,0xC0,0x33,0xCD,0xA7,0x8C,0x30,0xC3,0x0C, +// '' +0xDE,0x04,0x06,0x09,0x00,0x07, +0xC3,0xEF,0xF3,0xCF,0xFF,0xB0,0xC0, +// '' +0xDF,0x03,0x07,0x0A,0x00,0x07, +0x79,0xFB,0x36,0x6D,0x9B,0x33,0x63,0xDF,0xB8, +// '' +0xE0,0x03,0x06,0x0A,0x00,0x07, +0x30,0x60,0x1E,0x7C,0x37,0xF3,0xFD,0xF0, +// '' +0xE1,0x03,0x06,0x0A,0x00,0x07, +0x18,0xC0,0x1E,0x7C,0x37,0xF3,0xFD,0xF0, +// '' +0xE2,0x02,0x06,0x0B,0x00,0x07, +0x10,0xE2,0x80,0x79,0xF0,0xDF,0xCF,0xF7,0xC0, +// '' +0xE3,0x03,0x06,0x0A,0x00,0x07, +0x25,0x60,0x1E,0x7C,0x37,0xF3,0xFD,0xF0, +// '' +0xE4,0x03,0x06,0x0A,0x00,0x07, +0x6D,0xB0,0x1E,0x7C,0x37,0xF3,0xFD,0xF0, +// '' +0xE5,0x02,0x06,0x0B,0x00,0x07, +0x38,0xA3,0x80,0x79,0xF0,0xDF,0xCF,0xF7,0xC0, +// '' +0xE6,0x06,0x08,0x07,0x00,0x07, +0x7C,0x7E,0x1A,0x7E,0xD8,0xFE,0x7E, +// '' +0xE7,0x06,0x06,0x09,0x00,0x07, +0x3D,0xFE,0x30,0xC1,0xF3,0xC6,0x38, +// '' +0xE8,0x03,0x07,0x0A,0x00,0x07, +0x60,0x60,0x01,0xC7,0xD9,0xBF,0x60,0x7C,0x78, +// '' +0xE9,0x03,0x07,0x0A,0x00,0x07, +0x18,0x60,0x01,0xC7,0xD9,0xBF,0x60,0x7C,0x78, +// '' +0xEA,0x02,0x07,0x0B,0x00,0x07, +0x10,0x70,0xA0,0x03,0x8F,0xB3,0x7E,0xC0,0xF8,0xF0, +// '' +0xEB,0x03,0x07,0x0A,0x00,0x07, +0x6C,0xD8,0x01,0xC7,0xD9,0xBF,0x60,0x7C,0x78, +// '' +0xEC,0x03,0x06,0x0A,0x01,0x07, +0x60,0xC0,0x3C,0xF0,0xC3,0x0C,0x3C,0x70, +// '' +0xED,0x03,0x06,0x0A,0x01,0x07, +0x31,0x80,0x3C,0xF0,0xC3,0x0C,0x3C,0x70, +// '' +0xEE,0x02,0x06,0x0B,0x01,0x07, +0x21,0xC5,0x00,0xF3,0xC3,0x0C,0x30,0xF1,0xC0, +// '' +0xEF,0x03,0x06,0x0A,0x01,0x07, +0xDB,0x60,0x3C,0xF0,0xC3,0x0C,0x3C,0x70, +// '' +0xF0,0x03,0x06,0x0A,0x01,0x07, +0x21,0xF7,0x83,0x7F,0xFC,0xF3,0xF9,0xE0, +// '' +0xF1,0x03,0x06,0x0A,0x00,0x07, +0x4A,0xC0,0x3E,0xFF,0x3C,0xF3,0xCF,0x30, +// '' +0xF2,0x03,0x06,0x0A,0x00,0x07, +0x60,0xC0,0x1E,0x7B,0x3C,0xF3,0x79,0xE0, +// '' +0xF3,0x03,0x06,0x0A,0x00,0x07, +0x18,0xC0,0x1E,0x7B,0x3C,0xF3,0x79,0xE0, +// '' +0xF4,0x02,0x06,0x0B,0x00,0x07, +0x21,0xC5,0x00,0x79,0xEC,0xF3,0xCD,0xE7,0x80, +// '' +0xF5,0x03,0x06,0x0A,0x00,0x07, +0x25,0x60,0x1E,0x7B,0x3C,0xF3,0x79,0xE0, +// '' +0xF6,0x03,0x06,0x0A,0x00,0x07, +0x6D,0xB0,0x1E,0x7B,0x3C,0xF3,0x79,0xE0, +// '' +0xF7,0x06,0x05,0x07,0x01,0x07, +0x31,0x81,0xF0,0x18,0xC0, +// '' +0xF8,0x05,0x07,0x09,0x00,0x07, +0x00,0x7D,0xF6,0x7D,0x7C,0xDF,0x3E,0x00, +// '' +0xF9,0x03,0x06,0x0A,0x00,0x07, +0x60,0xC0,0x33,0xCF,0x3C,0xF3,0xFD,0xF0, +// '' +0xFA,0x03,0x06,0x0A,0x00,0x07, +0x18,0xC0,0x33,0xCF,0x3C,0xF3,0xFD,0xF0, +// '' +0xFB,0x02,0x06,0x0B,0x00,0x07, +0x10,0xE2,0x80,0xCF,0x3C,0xF3,0xCF,0xF7,0xC0, +// '' +0xFC,0x03,0x06,0x0A,0x00,0x07, +0x6D,0xB0,0x33,0xCF,0x3C,0xF3,0xFD,0xF0, +// '' +0xFD,0x03,0x07,0x0C,0x00,0x07, +0x18,0x60,0x03,0x36,0x66,0x8F,0x1E,0x18,0x30,0x47,0x00, +// '' +0xFE,0x03,0x06,0x0C,0x00,0x07, +0xC3,0x0C,0x3E,0xFB,0x3C,0xF3,0xFF,0xEC,0x30, +// '' +0xFF,0x03,0x07,0x0C,0x00,0x07, +0x6C,0xD8,0x03,0x36,0x66,0x8F,0x1E,0x18,0x30,0x47,0x00, + +// Terminator +0xFF +}; diff --git a/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/tftdemo.py b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/tftdemo.py index 4e8e15b..64a635b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/tftdemo.py +++ b/MicroPython_BUILD/components/micropython/esp32/modules_examples/tft/tftdemo.py @@ -5,20 +5,20 @@ Date: 08/10/2017 """ -import machine, display, time, math +import machine, display, time, _thread, math tft = display.TFT() # --- Select correct configuration --- # ESP32-WROVER-KIT v3: -tft.init(tft.ST7789, rst_pin=18, backl_pin=5, miso=25, mosi=23, clk=19, cs=22, dc=21) +#tft.init(tft.ST7789, rst_pin=18, backl_pin=5, miso=25, mosi=23, clk=19, cs=22, dc=21) # Adafruit TFT FeatherWing: #tft.init(tft.ILI9341, width=240, height=320, miso=19, mosi=18, clk=5, cs=15, dc=33, bgr=True, hastouch=tft.TOUCH_STMPE, tcs=32) # M5Stack: -#tft.init(tft.ILI9341, width=240, height=320, rst_pin=33, backl_pin=32, miso=19, mosi=23, clk=18, cs=14, dc=27, bgr=True, backl_on=1, invrot=3) +tft.init(tft.M5STACK, width=240, height=320, rst_pin=33, backl_pin=32, miso=19, mosi=23, clk=18, cs=14, dc=27, bgr=True, backl_on=1) # Some others... #tft.init(tft.ILI9341, width=240, height=320, miso=19,mosi=23,clk=18,cs=5,dc=26,tcs=27,hastouch=True, bgr=True) @@ -38,8 +38,8 @@ def testt(): time.sleep_ms(50) -maxx = 240 -maxy = 320 +maxx = 320 +maxy = 240 miny = 12 touch = False @@ -208,17 +208,18 @@ def circleSimple(): tx = "CIRCLE" header(tx, True) - x = 110 - y = 160 - r = 110 - z = 0 - while z < 12: + x = maxx // 2 + y = (maxy-miny) // 2 + (miny // 2) + if x > y: + r = y - miny + else: + r = x - miny + while r > 0: color = machine.random(0xFFFFFF) fill = machine.random(0xFFFFFF) tft.circle(x,y,r,color,fill) r -= 10 x += 10 - z += 1 # Display random ellipses #----------------------------------- @@ -301,3 +302,47 @@ def roundrectDemo(sec=5, dofill=False): if touched(): break tft.resetwin() + +# Fisplay all demos +#-------------------------------------- +def fullDemo(sec=5, rot=tft.LANDSCAPE): + tft.orient(rot) + dispFont(sec) + time.sleep(0.1) + fontDemo(sec, rot=False) + time.sleep(0.1) + fontDemo(sec, rot=True) + time.sleep(0.1) + lineDemo(sec) + time.sleep(0.1) + circleDemo(sec, dofill=False) + time.sleep(0.1) + circleDemo(sec, dofill=True) + time.sleep(0.1) + circleSimple() + time.sleep(0.1) + time.sleep(sec) + time.sleep(0.1) + ellipseDemo(sec, dofill=False) + time.sleep(0.1) + ellipseDemo(sec, dofill=True) + time.sleep(0.1) + rectDemo(sec, dofill=False) + time.sleep(0.1) + rectDemo(sec, dofill=True) + time.sleep(0.1) + roundrectDemo(sec, dofill=False) + time.sleep(0.1) + roundrectDemo(sec, dofill=True) + time.sleep(0.1) + +# Run demo in thread +def dispDemo_th(): + while True: + fullDemo(rot=tft.LANDSCAPE) + fullDemo(rot=tft.PORTRAIT) + fullDemo(rot=tft.LANDSCAPE_FLIP) + fullDemo(rot=tft.PORTRAIT_FLIP) + +# dispth=_thread.start_new_thread("TFTDemo", dispDemo_th, ()) + diff --git a/MicroPython_BUILD/components/micropython/esp32/moduos.c b/MicroPython_BUILD/components/micropython/esp32/moduos.c index 3dd92f7..ed96d20 100644 --- a/MicroPython_BUILD/components/micropython/esp32/moduos.c +++ b/MicroPython_BUILD/components/micropython/esp32/moduos.c @@ -1,5 +1,5 @@ /* - * 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 * @@ -7,6 +7,7 @@ * * Copyright (c) 2015 Josef Gajdusek * 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 @@ -40,6 +41,7 @@ #include "extmod/vfs.h" #include "mpversion.h" #include "extmod/vfs_native.h" +#include "machine_pin.h" //extern const mp_obj_type_t mp_fat_vfs_type; @@ -130,31 +132,76 @@ STATIC mp_obj_t os_umount_sdcard(void) } 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_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); + + int mode = args[0].u_int; + if ((mode < 1) || (mode > 3)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported sdcard mode")); + } + if (mode == 1) { + int clk = machine_pin_get_gpio(args[1].u_obj); + int mosi = machine_pin_get_gpio(args[2].u_obj); + int miso = machine_pin_get_gpio(args[3].u_obj); + int cs = machine_pin_get_gpio(args[4].u_obj); + + if (native_vfs_mounted[VFS_NATIVE_TYPE_SDCARD]) os_umount_sdcard(); + sdcard_config.clk = clk; + sdcard_config.mosi = mosi; + sdcard_config.miso = miso; + sdcard_config.cs = cs; + sdcard_config.mode = mode; + } + else { + if (native_vfs_mounted[VFS_NATIVE_TYPE_SDCARD]) os_umount_sdcard(); + sdcard_config.mode = mode; + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(os_sdcard_config_obj, 0, os_sdcard_config); + //========================================================== STATIC const mp_rom_map_elem_t os_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, - { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, - { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, + { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) }, + { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) }, #if MICROPY_PY_OS_DUPTERM - { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, - { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, + { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) }, + { MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) }, #endif #if MICROPY_VFS - { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, - { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, - { 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_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) }, - { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, - //{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, - { 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_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, + { 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_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) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, + //{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, + { 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) }, + // Constants + { MP_ROM_QSTR(MP_QSTR_SDMODE_SPI), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_SDMODE_1LINE), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_SDMODE_4LINE), MP_ROM_INT(3) }, #endif }; diff --git a/MicroPython_BUILD/components/micropython/esp32/modutime.c b/MicroPython_BUILD/components/micropython/esp32/modutime.c index 5c7f461..71c1ab9 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modutime.c +++ b/MicroPython_BUILD/components/micropython/esp32/modutime.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) 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 @@ -176,15 +177,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(time_mktime_obj, 1, time_mktime); //------------------------------------- STATIC mp_obj_t time_ticks_base(void) { - long ticks_base = 0; - if (sntp_mutex) { - if (xSemaphoreTake(sntp_mutex, 1000 / portTICK_PERIOD_MS) == pdTRUE) { - ticks_base = mp_hal_ticks_base; - xSemaphoreGive(sntp_mutex); - } - } - else ticks_base = mp_hal_ticks_base; - return mp_obj_new_int(ticks_base); + return mp_obj_new_int_from_ull(getTicks_base()); } MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_base_obj, time_ticks_base); diff --git a/MicroPython_BUILD/components/micropython/esp32/modymodem.c b/MicroPython_BUILD/components/micropython/esp32/modymodem.c index 45b7ab6..b9928c7 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modymodem.c +++ b/MicroPython_BUILD/components/micropython/esp32/modymodem.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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) 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/esp32/modymodem.h b/MicroPython_BUILD/components/micropython/esp32/modymodem.h index a204d0c..0b29e9a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/modymodem.h +++ b/MicroPython_BUILD/components/micropython/esp32/modymodem.h @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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) 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/esp32/mpconfigport.h b/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h index 71407cf..8a211cd 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpconfigport.h @@ -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. + */ + // Options to control how MicroPython is built for this port, // overriding defaults in py/mpconfig.h. @@ -255,6 +281,13 @@ extern const struct _mp_obj_module_t mp_module_ota; #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 }, \ @@ -268,6 +301,7 @@ extern const struct _mp_obj_module_t mp_module_ota; BUILTIN_MODULE_SSH \ BUILTIN_MODULE_GSM \ BUILTIN_MODULE_OTA \ + BUILTIN_MODULE_BLUETOOTH \ #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ { MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \ @@ -340,7 +374,7 @@ typedef long mp_off_t; // 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_PY_SYS_PLATFORM "esp32" #define MICROPY_TIMEZONE CONFIG_MICROPY_TIMEZONE diff --git a/MicroPython_BUILD/components/micropython/esp32/mphalport.c b/MicroPython_BUILD/components/micropython/esp32/mphalport.c index d9dd488..37f1dc1 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mphalport.c +++ b/MicroPython_BUILD/components/micropython/esp32/mphalport.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) 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 @@ -51,7 +52,17 @@ #endif uint32_t mp_hal_wdg_rst_tmo = 0; -long mp_hal_ticks_base = 0; +uint64_t mp_hal_ticks_base = 0; + +static bool stdin_disable = false; +static char stdin_enable_pattern[16] = ""; + +//-------------------------------- +void disableStdin(const char *pat) +{ + snprintf(stdin_enable_pattern, 15, "%s", pat); + stdin_disable = true; +} //--------------------- void mp_hal_reset_wdt() @@ -91,6 +102,8 @@ int mp_hal_stdin_rx_chr(uint32_t timeout) { uint64_t wait_end = mp_hal_ticks_ms() + timeout; int c = -1; + char pattern[16]; + uint8_t pattern_idx = 0; for (;;) { #ifdef CONFIG_MICROPY_USE_TASK_WDT @@ -129,6 +142,18 @@ int mp_hal_stdin_rx_chr(uint32_t timeout) return -1; } #endif + + if (stdin_disable) { + if (strlen(stdin_enable_pattern) > 0) { + // Check stdin enable pattern + 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; + } + } + return -1; + } return c; } @@ -237,10 +262,10 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) { #endif } -//------------------ -long getTicks_base() +//---------------------- +uint64_t getTicks_base() { - long ticks_base = 0; + uint64_t ticks_base = 0; if (sntp_mutex) { if (xSemaphoreTake(sntp_mutex, 1000 / portTICK_PERIOD_MS) == pdTRUE) { ticks_base = mp_hal_ticks_base; @@ -251,20 +276,30 @@ long getTicks_base() return ticks_base; } +//------------------------------------- +void setTicks_base(uint64_t ticks_base) +{ + if (sntp_mutex) { + if (xSemaphoreTake(sntp_mutex, 1000 / portTICK_PERIOD_MS) == pdTRUE) { + mp_hal_ticks_base = ticks_base; + xSemaphoreGive(sntp_mutex); + } + } + else mp_hal_ticks_base = ticks_base; +} + //------------------------------ uint64_t mp_hal_ticks_ms(void) { struct timeval tv; gettimeofday(&tv, NULL); - long sec = tv.tv_sec - getTicks_base(); - return ((uint64_t)sec * 1000) + ((uint64_t)tv.tv_usec / 1000); + return ((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec) - getTicks_base()) / 1000; } //------------------------------ uint64_t mp_hal_ticks_us(void) { struct timeval tv; gettimeofday(&tv, NULL); - long sec = tv.tv_sec - getTicks_base(); - return ((uint64_t)sec * 1000000) + (uint64_t)tv.tv_usec; + return ((((uint64_t)tv.tv_sec * 1000000) + (uint64_t)tv.tv_usec) - getTicks_base()); } /* @@ -286,13 +321,13 @@ int mp_hal_delay_ms(uint32_t ms) esp_task_wdt_reset(); #endif - if (ms <= 10) { - // For delays up to 10 ms we use blocking delay + if (ms <= 2) { + // For delays up to 2 ms we use blocking delay ets_delay_us(ms * 1000); return ms; } - long tticks_base = getTicks_base(); + uint64_t tticks_base = getTicks_base(); struct timeval tv; gettimeofday(&tv, NULL); uint32_t tstart = ((uint32_t)tv.tv_sec * 1000) + ((uint32_t)tv.tv_usec / 1000); diff --git a/MicroPython_BUILD/components/micropython/esp32/mphalport.h b/MicroPython_BUILD/components/micropython/esp32/mphalport.h index 02e6aa0..c3eb687 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mphalport.h +++ b/MicroPython_BUILD/components/micropython/esp32/mphalport.h @@ -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) 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,7 +36,11 @@ extern ringbuf_t stdin_ringbuf; extern uint32_t mp_hal_wdg_rst_tmo; -extern long mp_hal_ticks_base; + +uint64_t getTicks_base(); +void setTicks_base(uint64_t ticks_base); + +void disableStdin(const char *pat); void mp_hal_set_wdt_tmo(); void mp_hal_reset_wdt(); diff --git a/MicroPython_BUILD/components/micropython/esp32/mpsleep.c b/MicroPython_BUILD/components/micropython/esp32/mpsleep.c index affc5ab..57cfc3e 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpsleep.c +++ b/MicroPython_BUILD/components/micropython/esp32/mpsleep.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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) 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/esp32/mpsleep.h b/MicroPython_BUILD/components/micropython/esp32/mpsleep.h index 06cf5b1..96318f1 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpsleep.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpsleep.h @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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) 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/esp32/mpthreadport.c b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c index 33ceccf..273d6f6 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c +++ b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.c @@ -1,16 +1,9 @@ /* - * This file is based on 'modthreadport' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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 @@ -47,6 +40,7 @@ #include "py/mpthread.h" #include "py/mphal.h" #include "mpthreadport.h" +#include "modnetwork.h" #if defined(CONFIG_MICROPY_USE_TELNET) || defined(CONFIG_MICROPY_USE_FTPSERVER) #include "tcpip_adapter.h" @@ -648,6 +642,7 @@ int mp_thread_status(TaskHandle_t id) { int mp_thread_list(thread_list_t *list) { int num = 0; + mp_thread_mutex_lock(&thread_mutex, 1); for (thread_t *th = thread; th != NULL; th = th->next) { @@ -723,8 +718,13 @@ static int _check_wifi() 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; } #endif diff --git a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h index 78b27e0..79a148a 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpthreadport.h @@ -1,16 +1,10 @@ /* - * This file is based on 'modthreadport' from Pycom Limited. - * - * Author: LoBo, https://loboris@github.com, loboris@gmail.com - * Copyright (c) 2017, LoBo - */ - -/* - * 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) 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/esp32/mpversion.h b/MicroPython_BUILD/components/micropython/esp32/mpversion.h index 9d557d7..ad9b97b 100644 --- a/MicroPython_BUILD/components/micropython/esp32/mpversion.h +++ b/MicroPython_BUILD/components/micropython/esp32/mpversion.h @@ -1,8 +1,33 @@ -// MicroPython version info -#define MICROPY_GIT_TAG "ESP32_LoBo_v3.1.18" -#define MICROPY_GIT_HASH "gdaa8cfa8" -#define MICROPY_BUILD_DATE "2017-02-07" +/* + * 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. + */ + +#define MICROPY_GIT_TAG "ESP32_LoBo_v3.1.20" +#define MICROPY_GIT_HASH "g6acb38af" +#define MICROPY_BUILD_DATE "2017-02-28" #define MICROPY_VERSION_MAJOR (3) #define MICROPY_VERSION_MINOR (1) -#define MICROPY_VERSION_MICRO (18) -#define MICROPY_VERSION_STRING "3.1.18" +#define MICROPY_VERSION_MICRO (20) +#define MICROPY_VERSION_STRING "3.1.20" diff --git a/MicroPython_BUILD/components/micropython/esp32/network_mdns.c b/MicroPython_BUILD/components/micropython/esp32/network_mdns.c index b33e9a9..c77aa30 100644 --- a/MicroPython_BUILD/components/micropython/esp32/network_mdns.c +++ b/MicroPython_BUILD/components/micropython/esp32/network_mdns.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 "Boris Lovosevic" + * Copyright (c) 2018 LoBo (https://github.com/loboris) * * Based on the ESP IDF example code which is Public Domain / CC0 * diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native.c b/MicroPython_BUILD/components/micropython/extmod/vfs_native.c index 4c02754..a76180a 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs_native.c +++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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) 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 @@ -29,8 +29,6 @@ * * Modified by LoBo (https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo) * - * Added support for SD Card and some changes to make it work (hopefully) better - * */ #include "py/mpconfig.h" @@ -104,6 +102,21 @@ STATIC const byte fresult_to_errno_table[20] = { STATIC const char *TAG = "vfs_native"; +sdcard_config_t sdcard_config = { + CONFIG_SDCARD_MODE, +#if CONFIG_SDCARD_MODE == 1 + CONFIG_SDCARD_CLK, + CONFIG_SDCARD_MOSI, + CONFIG_SDCARD_MISO, + CONFIG_SDCARD_CS +#else + -1, + -1, + -1, + -1 +#endif +}; + bool native_vfs_mounted[2] = {false, false}; STATIC sdmmc_card_t *sdmmc_card; @@ -674,40 +687,48 @@ STATIC void sdcard_print_info(const sdmmc_card_t* card, int mode) //------------------------- static void _sdcard_mount() { - mp_int_t card_mode = 3; + esp_err_t ret; - // Configure sdmmc interface - #if defined(CONFIG_SDCARD_MODE1) - // Use SPI SD mode + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = false, + .max_files = CONFIG_MICROPY_FATFS_MAX_OPEN_FILES + }; + + // Configure sdmmc interface + if (sdcard_config.mode == 1) { + // Use SPI mode sdmmc_host_t host = SDSPI_HOST_DEFAULT(); sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); - //host.slot = VSPI_HOST; - gpio_pad_select_gpio(CONFIG_SDCARD_MISO); - gpio_pad_select_gpio(CONFIG_SDCARD_MOSI); - gpio_pad_select_gpio(CONFIG_SDCARD_CLK); - gpio_pad_select_gpio(CONFIG_SDCARD_CS); - gpio_set_direction(CONFIG_SDCARD_MISO, GPIO_MODE_INPUT); - gpio_set_pull_mode(CONFIG_SDCARD_MISO, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(CONFIG_SDCARD_CLK, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(CONFIG_SDCARD_MOSI, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(CONFIG_SDCARD_CS, GPIO_PULLUP_ONLY); - slot_config.gpio_miso = CONFIG_SDCARD_MISO; - slot_config.gpio_mosi = CONFIG_SDCARD_MOSI; - slot_config.gpio_sck = CONFIG_SDCARD_CLK; - slot_config.gpio_cs = CONFIG_SDCARD_CS; - card_mode = 1; - #else + host.slot = VSPI_HOST; + + 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); + slot_config.gpio_miso = sdcard_config.miso; + slot_config.gpio_mosi = sdcard_config.mosi; + slot_config.gpio_sck = sdcard_config.clk; + slot_config.gpio_cs = sdcard_config.cs; + ret = esp_vfs_fat_sdmmc_mount(VFS_NATIVE_SDCARD_MOUNT_POINT, &host, &slot_config, &mount_config, &sdmmc_card); + } + else { sdmmc_host_t host = SDMMC_HOST_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - #if defined(CONFIG_SDCARD_MODE2) + if (sdcard_config.mode == 1) { // 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); host.flags = SDMMC_HOST_FLAG_1BIT; slot_config.width = 1; - card_mode = 2; - #else + } + else { // Use 4-line SD mode gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); gpio_set_pull_mode(14, GPIO_PULLUP_ONLY); @@ -715,16 +736,10 @@ static void _sdcard_mount() gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); - card_mode = 3; - #endif - #endif + } + ret = esp_vfs_fat_sdmmc_mount(VFS_NATIVE_SDCARD_MOUNT_POINT, &host, &slot_config, &mount_config, &sdmmc_card); + } - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = CONFIG_MICROPY_FATFS_MAX_OPEN_FILES - }; - - esp_err_t ret = esp_vfs_fat_sdmmc_mount(VFS_NATIVE_SDCARD_MOUNT_POINT, &host, &slot_config, &mount_config, &sdmmc_card); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount filesystem on SDcard."); @@ -741,13 +756,12 @@ static void _sdcard_mount() else { ESP_LOGE(TAG, "Failed to initialize SDcard (%d).", ret); } - #if defined(CONFIG_SDCARD_MODE1) - sdspi_host_deinit(); - #endif - mp_raise_OSError(MP_EIO); + if (sdcard_config.mode == 1) sdspi_host_deinit(); + + mp_raise_OSError(MP_EIO); } ESP_LOGV(TAG, "SDCard FATFS mounted."); - sdcard_print_info(sdmmc_card, card_mode); + sdcard_print_info(sdmmc_card, sdcard_config.mode); native_vfs_mounted[VFS_NATIVE_TYPE_SDCARD] = true; } @@ -862,9 +876,7 @@ STATIC mp_obj_t native_vfs_umount(mp_obj_t self_in) { if ((self->device == VFS_NATIVE_TYPE_SDCARD) && (native_vfs_mounted[self->device])) { esp_err_t ret = esp_vfs_fat_sdmmc_unmount(); - #if defined(CONFIG_SDCARD_MODE1) - sdspi_host_deinit(); - #endif + if (sdcard_config.mode == 1) sdspi_host_deinit(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to unmount filesystem on SDcard (%d).", ret); mp_raise_OSError(MP_EIO); @@ -898,22 +910,24 @@ int internalUmount() return res; } -//----------------- -int externalUmount() +//------------------- +void externalUmount() { - int res = 0; if (native_vfs_mounted[VFS_NATIVE_TYPE_SDCARD]) { esp_vfs_fat_sdmmc_unmount(); - if (res) res = 0; - #if defined(CONFIG_SDCARD_MODE1) - sdspi_host_deinit(); - #endif + if (sdcard_config.mode == 1) sdspi_host_deinit(); native_vfs_mounted[VFS_NATIVE_TYPE_SDCARD] = false; } - - return res; } +//------------------------------------- +bool file_noton_spi_sdcard(char *fname) +{ + if (sdcard_config.mode == 1) { + if (strstr(fname, VFS_NATIVE_SDCARD_MOUNT_POINT)) return false; + } + return true; +} //------------------------------------- int mount_vfs(int type, char *chdir_to) diff --git a/MicroPython_BUILD/components/micropython/extmod/vfs_native.h b/MicroPython_BUILD/components/micropython/extmod/vfs_native.h index eaafeae..569aa4e 100644 --- a/MicroPython_BUILD/components/micropython/extmod/vfs_native.h +++ b/MicroPython_BUILD/components/micropython/extmod/vfs_native.h @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python 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) 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 @@ -29,48 +29,10 @@ * * Modified by LoBo (https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo) * - * Added support for SD Card and some changes to make it work better - * */ // ======== CD Card support =========================================================================== -/* - * Using SDCard with sdmmc driver connection: - -ESP32 pin | SD card pin | SPI pin | Notes ---------------|----------------|---------|------------ - | SD uSD | | ---------------|----------------|---------|------------ -GPIO14 (MTMS) | CLK 5 5 | SCK | 10k pullup in SD mode -GPIO15 (MTDO) | CMD 2 3 | MOSI | 10k pullup, both in SD and SPI modes -GPIO2 | D0 7 7 | MISO | 10k pullup in SD mode, pull low to go into download mode (see note below!) -GPIO4 | D1 8 8 | N/C | not used in 1-line SD mode; 10k pullup in 4-line SD mode -GPIO12 (MTDI) | D2 9 1 | N/C | not used in 1-line SD mode; 10k pullup in 4-line SD mode (see note below!) -GPIO13 (MTCK) | D3 1 2 | CS | not used in 1-line SD mode, but card's D3 pin must have a 10k pullup -N/C | CD | | optional, not used -N/C | WP | | optional, not used -VDD 3.3V | VSS 4 4 | -GND GND | GND 3&6 6 | - -SDcard pinout uSDcard pinout - Contacts view - _________________ 1 2 3 4 5 6 7 8 -| | _______________ -| | |# # # # # # # #| -| | | | -| | | | -| | / | -| | / | -| | |_ | -| | | | -| #| / | -|# # # # # # # # / | | -|_______________/ | | - 8 7 6 5 4 3 2 1 9 |_________________| - - */ - #include "py/lexer.h" #include "py/obj.h" #include "py/objint.h" @@ -93,7 +55,16 @@ typedef struct _fs_user_mount_t { mp_int_t device; } fs_user_mount_t; +typedef struct _sdcard_config_t { + uint8_t mode; + int8_t clk; + int8_t mosi; + int8_t miso; + int8_t cs; +} sdcard_config_t; + extern const mp_obj_type_t mp_native_vfs_type; +extern sdcard_config_t sdcard_config; bool native_vfs_mounted[2]; @@ -108,6 +79,8 @@ MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); //MP_DECLARE_CONST_FUN_OBJ_2(native_vfs_chdir_obj); int internalUmount(); -int externalUmount(); +void externalUmount(); + +bool file_noton_spi_sdcard(char *fname); mp_obj_t native_vfs_ilistdir2(struct _fs_user_mount_t *vfs, const char *path, bool is_str_type); diff --git a/MicroPython_BUILD/components/micropython/py/modmicropython.c b/MicroPython_BUILD/components/micropython/py/modmicropython.c index 2aac53a..4ce503f 100644 --- a/MicroPython_BUILD/components/micropython/py/modmicropython.c +++ b/MicroPython_BUILD/components/micropython/py/modmicropython.c @@ -140,7 +140,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd #if MICROPY_ENABLE_SCHEDULER STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) { - if (!mp_sched_schedule(function, arg)) { + if (!mp_sched_schedule(function, arg, NULL)) { mp_raise_msg(&mp_type_RuntimeError, "schedule stack full"); } return mp_const_none; diff --git a/MicroPython_BUILD/components/micropython/py/modsys.c b/MicroPython_BUILD/components/micropython/py/modsys.c index 84a4eb0..01cd433 100644 --- a/MicroPython_BUILD/components/micropython/py/modsys.c +++ b/MicroPython_BUILD/components/micropython/py/modsys.c @@ -37,7 +37,7 @@ #if MICROPY_PY_SYS -#include "genhdr/mpversion.h" +#include "esp32/mpversion.h" // defined per port; type of these is irrelevant, just need pointer extern struct _mp_dummy_t mp_sys_stdin_obj; diff --git a/MicroPython_BUILD/components/micropython/py/modthread.c b/MicroPython_BUILD/components/micropython/py/modthread.c index 8a832f2..60f225a 100644 --- a/MicroPython_BUILD/components/micropython/py/modthread.c +++ b/MicroPython_BUILD/components/micropython/py/modthread.c @@ -411,6 +411,9 @@ STATIC mp_obj_t mod_thread_getSelfname() { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_getSelfname_obj, mod_thread_getSelfname); +extern TaskHandle_t TelnetTaskHandle; +extern TaskHandle_t FtpTaskHandle; + //----------------------------------------------------------------------- STATIC mp_obj_t mod_thread_list(mp_uint_t n_args, const mp_obj_t *args) { int prn = 1, n = 0; @@ -441,11 +444,22 @@ 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); + 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)); + } + 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)); + } return mp_const_none; } else { + int services = 0; + if (TelnetTaskHandle) services++; + if (FtpTaskHandle) services++; mp_obj_t thr_info[6]; - mp_obj_t tuple[num]; + mp_obj_t tuple[num+services]; for (n=0; nid); @@ -459,6 +473,26 @@ 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); + 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[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++; + } + 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[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++; + } return mp_obj_new_tuple(n, tuple); } @@ -554,9 +588,9 @@ STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_STATUS), MP_ROM_INT(THREAD_NOTIFY_STATUS) }, { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(THREAD_STATUS_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_SUSPENDED), MP_ROM_INT(THREAD_STATUS_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_WAITING), MP_ROM_INT(THREAD_STATUS_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_TERMINATED), MP_ROM_INT(THREAD_STATUS_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_SUSPENDED), MP_ROM_INT(THREAD_STATUS_SUSPENDED) }, + { MP_ROM_QSTR(MP_QSTR_WAITING), MP_ROM_INT(THREAD_STATUS_WAITING) }, + { MP_ROM_QSTR(MP_QSTR_TERMINATED), MP_ROM_INT(THREAD_STATUS_TERMINATED) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_thread_globals, mp_module_thread_globals_table); diff --git a/MicroPython_BUILD/components/micropython/py/mpstate.h b/MicroPython_BUILD/components/micropython/py/mpstate.h index 18b6772..826f453 100644 --- a/MicroPython_BUILD/components/micropython/py/mpstate.h +++ b/MicroPython_BUILD/components/micropython/py/mpstate.h @@ -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 @@ -58,6 +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; } mp_sched_item_t; // This structure hold information about the memory allocation system. diff --git a/MicroPython_BUILD/components/micropython/py/runtime.h b/MicroPython_BUILD/components/micropython/py/runtime.h index 9c1921c..b27c237 100644 --- a/MicroPython_BUILD/components/micropython/py/runtime.h +++ b/MicroPython_BUILD/components/micropython/py/runtime.h @@ -56,6 +56,41 @@ typedef struct _mp_arg_t { mp_arg_val_t defval; } mp_arg_t; +#if MICROPY_ENABLE_SCHEDULER +//-------------------------- + +#define MP_SCHED_CTYPE_MAX_ITEMS 4 + +#define MP_SCHED_CTYPE_NONE 0 +#define MP_SCHED_CTYPE_SINGLE 1 +#define MP_SCHED_CTYPE_TUPLE 2 +#define MP_SCHED_CTYPE_DICT 3 + +#define MP_SCHED_ENTRY_TYPE_NONE 0 +#define MP_SCHED_ENTRY_TYPE_INT 1 +#define MP_SCHED_ENTRY_TYPE_BOOL 2 +#define MP_SCHED_ENTRY_TYPE_FLOAT 3 +#define MP_SCHED_ENTRY_TYPE_STR 4 +#define MP_SCHED_ENTRY_TYPE_BYTES 5 +#define MP_SCHED_ENTRY_TYPE_CARG 6 + +typedef struct _mp_sched_carg_t { + uint8_t type; + uint8_t n; + void *entry[MP_SCHED_CTYPE_MAX_ITEMS]; +} mp_sched_carg_t; + +typedef struct _mp_sched_carg_entry_t { + uint8_t type; + int ival; + float fval; + uint8_t *sval; + char key[16]; + mp_sched_carg_t *carg; +} mp_sched_carg_entry_t; + +#endif + // Tables mapping operator enums to qstrs, defined in objtype.c extern const byte mp_unary_op_method_name[]; extern const byte mp_binary_op_method_name[]; @@ -67,10 +102,17 @@ void mp_handle_pending(void); void mp_handle_pending_tail(mp_uint_t atomic_state); #if MICROPY_ENABLE_SCHEDULER + void mp_sched_lock(void); void mp_sched_unlock(void); static inline unsigned int mp_sched_num_pending(void) { return MP_STATE_VM(sched_sp); } -bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg); +bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg, void *carg); + +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); +mp_sched_carg_t *make_cargs(int type); +mp_sched_carg_t *make_carg_entry_carg(mp_sched_carg_t *carg, int idx, mp_sched_carg_t *darg); + #endif // extra printing method specifically for mp_obj_t's which are integral type diff --git a/MicroPython_BUILD/components/micropython/py/scheduler.c b/MicroPython_BUILD/components/micropython/py/scheduler.c index 30851a4..d4cbd3b 100644 --- a/MicroPython_BUILD/components/micropython/py/scheduler.c +++ b/MicroPython_BUILD/components/micropython/py/scheduler.c @@ -1,9 +1,10 @@ /* - * 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 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 @@ -25,6 +26,7 @@ */ #include +#include #include "py/runtime.h" @@ -47,20 +49,206 @@ void mp_handle_pending(void) { } } +//----------------------------------- +void free_carg(mp_sched_carg_t *carg) +{ + for (int i=0; ientry[i]) { + if (carg->type == MP_SCHED_ENTRY_TYPE_CARG) { + free_carg((mp_sched_carg_t *)carg->entry[i]); + } + else { + mp_sched_carg_entry_t *entry = (mp_sched_carg_entry_t *)carg->entry[i]; + if (entry->sval) { + free(entry->sval); + entry->sval = NULL; + } + } + free(carg->entry[i]); + } + } + free(carg); + carg = NULL; +} + +//--------------------------------------------------------------------------------------------------------------------------- +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 (carg->entry[idx] == NULL) { + free_carg(carg); + return NULL; + } + + mp_sched_carg_entry_t *entry = (mp_sched_carg_entry_t *)carg->entry[idx]; + + entry->type = type; + if (key) sprintf(entry->key, key); + + if (sval) { + entry->ival = val; + entry->sval = malloc(val); + if (entry->sval == NULL) { + free_carg(carg); + return NULL; + } + memcpy(entry->sval, sval, val); + } + else { + entry->ival = val; + } + carg->n++; + return carg; +} + +//------------------------------------------------------------------------------------------ +mp_sched_carg_t *make_carg_entry_carg(mp_sched_carg_t *carg, int idx, mp_sched_carg_t *darg) +{ + carg->entry[idx] = calloc(sizeof(mp_sched_carg_entry_t), 1); + if (carg->entry[idx] == NULL) { + free_carg(carg); + return NULL; + } + + mp_sched_carg_entry_t *entry = (mp_sched_carg_entry_t *)carg->entry[idx]; + entry->type = MP_SCHED_ENTRY_TYPE_CARG; + entry->carg = darg; + carg->n++; + return carg; +} + +//----------------------------------- +mp_sched_carg_t *make_cargs(int type) +{ + // Create scheduler function arguments + mp_sched_carg_t *carg = calloc(sizeof(mp_sched_carg_t), 1); + if (carg == NULL) return NULL; + + carg->type = type; + carg->n = 0; + return carg; +} + +//------------------------------------------------------------------ +static mp_obj_t make_arg_from_carg(mp_sched_carg_t *carg, int level) +{ + mp_obj_t arg = mp_const_none; + 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_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)); + } + 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)); + } + 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)); + } + 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)); + } + 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)); + } + 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); + } + } + arg = dct; + } + else if (carg->type == MP_SCHED_CTYPE_TUPLE) { + //tuple + mp_obj_t tuple[carg->n]; + for (int i = 0; i < carg->n; i++) { + mp_sched_carg_entry_t *entry = (mp_sched_carg_entry_t *)carg->entry[i]; + if (entry->type == MP_SCHED_ENTRY_TYPE_INT) { + tuple[i] = mp_obj_new_int(entry->ival); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_BOOL) { + tuple[i] = mp_obj_new_bool(entry->ival); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_FLOAT) { + tuple[i] = mp_obj_new_float(entry->fval); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) { + tuple[i] = mp_obj_new_str((const char*)entry->sval, entry->ival, false); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) { + tuple[i] = mp_obj_new_bytes((const byte*)entry->sval, entry->ival); + } + else if ((level == 0) && (entry->type == MP_SCHED_ENTRY_TYPE_CARG) && (entry->carg)) { + tuple[i] = make_arg_from_carg(entry->carg, 1); + } + else tuple[i] = mp_const_none; + } + arg = mp_obj_new_tuple(carg->n, tuple); + } + else { + // Simple type, single entry + mp_sched_carg_entry_t *entry = (mp_sched_carg_entry_t *)carg->entry[0]; + if (entry->type == MP_SCHED_ENTRY_TYPE_INT) { + arg = mp_obj_new_int(entry->ival); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_BOOL) { + arg = mp_obj_new_bool(entry->ival); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_FLOAT) { + arg = mp_obj_new_float(entry->fval); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_STR) { + arg = mp_obj_new_str((const char*)entry->sval, entry->ival, false); + } + else if (entry->type == MP_SCHED_ENTRY_TYPE_BYTES) { + arg = mp_obj_new_bytes((const byte*)entry->sval, entry->ival); + } + } + free_carg(carg); + return arg; +} + // This function should only be called be 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) { - mp_sched_item_t item = MP_STATE_VM(sched_stack)[--MP_STATE_VM(sched_sp)]; + // Get scheduled item, decrease stack counter + //mp_sched_item_t item = MP_STATE_VM(sched_stack)[--MP_STATE_VM(sched_sp)]; + + // get the first scheduled item from stack + mp_sched_item_t item = MP_STATE_VM(sched_stack)[0]; + // Move other items + MP_STATE_VM(sched_sp)--; + int i = 0; + while (i < MP_STATE_VM(sched_sp)) { + memcpy(&(MP_STATE_VM(sched_stack)[i]), &(MP_STATE_VM(sched_stack)[i+1]), sizeof(mp_sched_item_t)); + i++; + } + + 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); + } + else arg = item.arg; MICROPY_END_ATOMIC_SECTION(atomic_state); - mp_call_function_1_protected(item.func, item.arg); + mp_call_function_1_protected(item.func, arg); } else { MICROPY_END_ATOMIC_SECTION(atomic_state); } mp_sched_unlock(); } +//------------------------ void mp_sched_lock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); if (MP_STATE_VM(sched_state) < 0) { @@ -71,6 +259,7 @@ void mp_sched_lock(void) { MICROPY_END_ATOMIC_SECTION(atomic_state); } +//-------------------------- void mp_sched_unlock(void) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); if (++MP_STATE_VM(sched_state) == 0) { @@ -84,7 +273,8 @@ void mp_sched_unlock(void) { MICROPY_END_ATOMIC_SECTION(atomic_state); } -bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) { +//------------------------------------------------------------------- +bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg, void *carg) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); bool ret; if (MP_STATE_VM(sched_sp) < MICROPY_SCHEDULER_DEPTH) { @@ -93,6 +283,7 @@ bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) { } MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].func = function; MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].arg = arg; + MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].carg = carg; ++MP_STATE_VM(sched_sp); ret = true; } else { @@ -106,6 +297,7 @@ bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) { #else // MICROPY_ENABLE_SCHEDULER // A variant of this is inlined in the VM at the pending exception check +//---------------------------- void mp_handle_pending(void) { if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); diff --git a/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32.zip index 7f1377e..527f705 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 2eeee59..a00a0f9 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 8d0680c..067b421 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 a174509..09628ee 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 dc18108..87fb3da 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_ota.zip b/MicroPython_BUILD/firmware/MicroPython_LoBo_esp32_psram_ota.zip index bc88162..06e4cc2 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 ac750bf..e909600 100644 --- a/MicroPython_BUILD/firmware/README.md +++ b/MicroPython_BUILD/firmware/README.md @@ -12,7 +12,7 @@ Available firmwares: |**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_psram_all** | MicroPython, single partition layout, 4MB Flash, ALL modules included | +|**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 | diff --git a/MicroPython_BUILD/firmware/esp32/MicroPython.bin b/MicroPython_BUILD/firmware/esp32/MicroPython.bin index 512cf88..be4c956 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 afc8a05..762dfdc 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/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32/partitions_mpy.bin index 279eb6f..0f2a28e 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/sdkconfig b/MicroPython_BUILD/firmware/esp32/sdkconfig index 85f679d..f3c5703 100644 --- a/MicroPython_BUILD/firmware/esp32/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32/sdkconfig @@ -171,6 +171,7 @@ 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_MD5=y # # Compiler options @@ -318,6 +319,13 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20 # 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 + # # Ethernet # @@ -420,6 +428,7 @@ CONFIG_LOG_COLORS=y # LWIP # CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y @@ -596,6 +605,7 @@ 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 diff --git a/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_all/MicroPython.bin index 446ca81..ca6f0c6 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 f725753..d51b4cd 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/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_all/partitions_mpy.bin index a08bf12..f37f3bf 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/sdkconfig b/MicroPython_BUILD/firmware/esp32_all/sdkconfig index 074da3b..7d0197f 100644 --- a/MicroPython_BUILD/firmware/esp32_all/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_all/sdkconfig @@ -174,6 +174,7 @@ 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_MD5=y # # Compiler options @@ -321,6 +322,13 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20 # 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 + # # Ethernet # @@ -423,6 +431,7 @@ CONFIG_LOG_COLORS=y # LWIP # CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y @@ -599,6 +608,7 @@ 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 diff --git a/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_ota/MicroPython.bin index 8f41d63..3075bfd 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 3c80b3a..a30c943 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/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_ota/partitions_mpy.bin index f6e93f0..92f62ab 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/sdkconfig b/MicroPython_BUILD/firmware/esp32_ota/sdkconfig index 2b32b4f..108b67c 100644 --- a/MicroPython_BUILD/firmware/esp32_ota/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_ota/sdkconfig @@ -172,6 +172,7 @@ 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_MD5=y # # Compiler options @@ -319,6 +320,13 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20 # 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 + # # Ethernet # @@ -421,6 +429,7 @@ CONFIG_LOG_COLORS=y # LWIP # CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y @@ -597,6 +606,7 @@ 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 diff --git a/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram/MicroPython.bin index e348919..3f6e1b5 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 70ea418..4544dfb 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/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_psram/partitions_mpy.bin index ab44025..4d9423a 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/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram/sdkconfig index 3bcb621..4942e39 100644 --- a/MicroPython_BUILD/firmware/esp32_psram/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_psram/sdkconfig @@ -171,6 +171,7 @@ 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_MD5=y # # Compiler options @@ -225,6 +226,7 @@ CONFIG_SPIRAM_SUPPORT=y # SPI RAM config # CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND= CONFIG_SPIRAM_USE_MEMMAP= CONFIG_SPIRAM_USE_CAPS_ALLOC= CONFIG_SPIRAM_USE_MALLOC=y @@ -334,6 +336,13 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20 # 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 + # # Ethernet # @@ -436,6 +445,7 @@ CONFIG_LOG_COLORS=y # LWIP # CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y @@ -612,6 +622,7 @@ 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 diff --git a/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_all/MicroPython.bin index e3ac928..30c1184 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 68bcb75..6f30b9b 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/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_psram_all/partitions_mpy.bin index 729baf4..7c7197a 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/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig index b3748dd..c289551 100644 --- a/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_psram_all/sdkconfig @@ -174,6 +174,7 @@ 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_MD5=y # # Compiler options @@ -228,6 +229,7 @@ CONFIG_SPIRAM_SUPPORT=y # SPI RAM config # CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND= CONFIG_SPIRAM_USE_MEMMAP= CONFIG_SPIRAM_USE_CAPS_ALLOC= CONFIG_SPIRAM_USE_MALLOC=y @@ -337,6 +339,13 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20 # 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 + # # Ethernet # @@ -439,6 +448,7 @@ CONFIG_LOG_COLORS=y # LWIP # CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y @@ -615,6 +625,7 @@ 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 diff --git a/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/MicroPython.bin index f9ef822..bd69c1b 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 17469b0..cea4be6 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/partitions_mpy.bin b/MicroPython_BUILD/firmware/esp32_psram_ota/partitions_mpy.bin index abf0568..5db33c3 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/sdkconfig b/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig index 1290bf2..42fbd45 100644 --- a/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig +++ b/MicroPython_BUILD/firmware/esp32_psram_ota/sdkconfig @@ -172,6 +172,7 @@ 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_MD5=y # # Compiler options @@ -226,6 +227,7 @@ CONFIG_SPIRAM_SUPPORT=y # SPI RAM config # CONFIG_SPIRAM_BOOT_INIT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND= CONFIG_SPIRAM_USE_MEMMAP= CONFIG_SPIRAM_USE_CAPS_ALLOC= CONFIG_SPIRAM_USE_MALLOC=y @@ -335,6 +337,13 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20 # 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 + # # Ethernet # @@ -437,6 +446,7 @@ CONFIG_LOG_COLORS=y # LWIP # CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= CONFIG_LWIP_MAX_SOCKETS=8 CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y @@ -613,6 +623,7 @@ 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 diff --git a/Tools/esp-idf.tar.xz b/Tools/esp-idf.tar.xz index 2191104..b18fa6f 100644 Binary files a/Tools/esp-idf.tar.xz and b/Tools/esp-idf.tar.xz differ