commit 4868978856197437023ffda9b2ec5c0805ca17c4 Author: Pavel Brychta Date: Thu Jul 7 08:53:01 2022 +0200 Jen ulozeni kopie z githubu diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd727b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +.DS_Store +.vscode +components/arduino/ +components/esp-dl/ +components/esp-sr/ +components/esp32-camera/ +components/esp_littlefs/ +components/esp-rainmaker/ +components/esp-dsp/ +esp-idf/ +out/ +build/ +dist/ +env.sh +sdkconfig +sdkconfig.old +version.txt +components/arduino_tinyusb/tinyusb/ +dependencies.lock +tools/esptool/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7f99bc0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,37 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS ${CMAKE_SOURCE_DIR}/components/esp-rainmaker/components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(arduino-lib-builder) + +idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION) + +add_custom_command( + OUTPUT "idf_libs" + COMMAND ${CMAKE_SOURCE_DIR}/tools/copy-libs.sh ${IDF_TARGET} "${CONFIG_LIB_BUILDER_FLASHMODE}" "${CONFIG_SPIRAM_MODE_OCT}" "${CONFIG_IDF_TARGET_ARCH_XTENSA}" + DEPENDS ${elf} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM +) +add_custom_target(idf-libs DEPENDS "idf_libs") + +add_custom_command( + OUTPUT "copy_bootloader" + COMMAND ${CMAKE_SOURCE_DIR}/tools/copy-bootloader.sh ${IDF_TARGET} "${CONFIG_LIB_BUILDER_FLASHMODE}" "${CONFIG_LIB_BUILDER_FLASHFREQ}" + DEPENDS bootloader + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM +) +add_custom_target(copy-bootloader DEPENDS "copy_bootloader") + +add_custom_command( + OUTPUT "mem_variant" + COMMAND ${CMAKE_SOURCE_DIR}/tools/copy-mem-variant.sh ${IDF_TARGET} "${CONFIG_LIB_BUILDER_FLASHMODE}" "${CONFIG_SPIRAM_MODE_OCT}" + DEPENDS ${elf} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM +) +add_custom_target(mem-variant DEPENDS "mem_variant") diff --git a/README.md b/README.md new file mode 100644 index 0000000..b14b38f --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# ESP32 Arduino Lib Builder [![Build Status](https://travis-ci.org/espressif/esp32-arduino-lib-builder.svg?branch=master)](https://travis-ci.org/espressif/esp32-arduino-lib-builder) + +This repository contains the scripts that produce the libraries included with esp32-arduino. + +Tested on Ubuntu (32 and 64 bit), Raspberry Pi and MacOS. + +### Build on Ubuntu and Raspberry Pi +```bash +sudo apt-get install git wget curl libssl-dev libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache +sudo pip install --upgrade pip +git clone https://github.com/espressif/esp32-arduino-lib-builder +cd esp32-arduino-lib-builder +./build.sh +``` diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..bae71a5 --- /dev/null +++ b/build.sh @@ -0,0 +1,192 @@ +#!/bin/bash + +if ! [ -x "$(command -v python)" ]; then + echo "ERROR: python is not installed! Please install python first." + exit 1 +fi + +if ! [ -x "$(command -v git)" ]; then + echo "ERROR: git is not installed! Please install git first." + exit 1 +fi + +TARGET="all" +BUILD_TYPE="all" +SKIP_ENV=0 +COPY_OUT=0 +DEPLOY_OUT=0 + +function print_help() { + echo "Usage: build.sh [-s] [-A ] [-I ] [-i ] [-c ] [-t ] [-b ] [config ...]" + echo " -s Skip installing/updating of ESP-IDF and all components" + echo " -A Set which branch of arduino-esp32 to be used for compilation" + echo " -I Set which branch of ESP-IDF to be used for compilation" + echo " -i Set which commit of ESP-IDF to be used for compilation" + echo " -d Deploy the build to github arduino-esp32" + echo " -c Set the arduino-esp32 folder to copy the result to. ex. '$HOME/Arduino/hardware/espressif/esp32'" + echo " -t Set the build target(chip). ex. 'esp32s3'" + echo " -b Set the build type. ex. 'build' to build the project and prepare for uploading to a board" + echo " ... Specify additional configs to be applied. ex. 'qio 80m' to compile for QIO Flash@80MHz. Requires -b" + exit 1 +} + +while getopts ":A:I:i:c:t:b:sd" opt; do + case ${opt} in + s ) + SKIP_ENV=1 + ;; + d ) + DEPLOY_OUT=1 + ;; + c ) + export ESP32_ARDUINO="$OPTARG" + COPY_OUT=1 + ;; + A ) + export AR_BRANCH="$OPTARG" + ;; + I ) + export IDF_BRANCH="$OPTARG" + ;; + i ) + export IDF_COMMIT="$OPTARG" + ;; + t ) + TARGET=$OPTARG + ;; + b ) + b=$OPTARG + if [ "$b" != "build" ] && + [ "$b" != "menuconfig" ] && + [ "$b" != "idf_libs" ] && + [ "$b" != "copy_bootloader" ] && + [ "$b" != "mem_variant" ]; then + print_help + fi + BUILD_TYPE="$b" + ;; + \? ) + echo "Invalid option: -$OPTARG" 1>&2 + print_help + ;; + : ) + echo "Invalid option: -$OPTARG requires an argument" 1>&2 + print_help + ;; + esac +done +shift $((OPTIND -1)) +CONFIGS=$@ + +if [ $SKIP_ENV -eq 0 ]; then + echo "* Installing/Updating ESP-IDF and all components..." + # update components from git + ./tools/update-components.sh + if [ $? -ne 0 ]; then exit 1; fi + + # install esp-idf + source ./tools/install-esp-idf.sh + if [ $? -ne 0 ]; then exit 1; fi +else + source ./tools/config.sh +fi + +if [ "$BUILD_TYPE" != "all" ]; then + if [ "$TARGET" = "all" ]; then + echo "ERROR: You need to specify target for non-default builds" + print_help + fi + configs="configs/defconfig.common;configs/defconfig.$TARGET" + + # Target Features Configs + for target_json in `jq -c '.targets[]' configs/builds.json`; do + target=$(echo "$target_json" | jq -c '.target' | tr -d '"') + if [ "$TARGET" == "$target" ]; then + for defconf in `echo "$target_json" | jq -c '.features[]' | tr -d '"'`; do + configs="$configs;configs/defconfig.$defconf" + done + fi + done + + # Configs From Arguments + for conf in $CONFIGS; do + configs="$configs;configs/defconfig.$conf" + done + + echo "idf.py -DIDF_TARGET=\"$TARGET\" -DSDKCONFIG_DEFAULTS=\"$configs\" $BUILD_TYPE" + rm -rf build sdkconfig + idf.py -DIDF_TARGET="$TARGET" -DSDKCONFIG_DEFAULTS="$configs" $BUILD_TYPE + if [ $? -ne 0 ]; then exit 1; fi + exit 0 +fi + +rm -rf build sdkconfig out + +echo $(git -C $AR_COMPS/arduino describe --all --long) > version.txt + +#targets_count=`jq -c '.targets[] | length' configs/builds.json` +for target_json in `jq -c '.targets[]' configs/builds.json`; do + target=$(echo "$target_json" | jq -c '.target' | tr -d '"') + + if [ "$TARGET" != "all" ] && [ "$TARGET" != "$target" ]; then + echo "* Skipping Target: $target" + continue + fi + + echo "* Target: $target" + + # Build Main Configs List + main_configs="configs/defconfig.common;configs/defconfig.$target" + for defconf in `echo "$target_json" | jq -c '.features[]' | tr -d '"'`; do + main_configs="$main_configs;configs/defconfig.$defconf" + done + + # Build IDF Libs + idf_libs_configs="$main_configs" + for defconf in `echo "$target_json" | jq -c '.idf_libs[]' | tr -d '"'`; do + idf_libs_configs="$idf_libs_configs;configs/defconfig.$defconf" + done + echo "* Build IDF-Libs: $idf_libs_configs" + rm -rf build sdkconfig + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" idf_libs + if [ $? -ne 0 ]; then exit 1; fi + + # Build Bootloaders + for boot_conf in `echo "$target_json" | jq -c '.bootloaders[]'`; do + bootloader_configs="$main_configs" + for defconf in `echo "$boot_conf" | jq -c '.[]' | tr -d '"'`; do + bootloader_configs="$bootloader_configs;configs/defconfig.$defconf"; + done + echo "* Build BootLoader: $bootloader_configs" + rm -rf build sdkconfig + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$bootloader_configs" copy_bootloader + if [ $? -ne 0 ]; then exit 1; fi + done + + # Build Memory Variants + for mem_conf in `echo "$target_json" | jq -c '.mem_variants[]'`; do + mem_configs="$main_configs" + for defconf in `echo "$mem_conf" | jq -c '.[]' | tr -d '"'`; do + mem_configs="$mem_configs;configs/defconfig.$defconf"; + done + echo "* Build Memory Variant: $mem_configs" + rm -rf build sdkconfig + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$mem_configs" mem_variant + if [ $? -ne 0 ]; then exit 1; fi + done +done + +# archive the build +if [ "$BUILD_TYPE" = "all" ]; then + ./tools/archive-build.sh + if [ $? -ne 0 ]; then exit 1; fi +fi + +# copy everything to arduino-esp32 installation +if [ $COPY_OUT -eq 1 ] && [ -d "$ESP32_ARDUINO" ]; then + ./tools/copy-to-arduino.sh +fi + +if [ $DEPLOY_OUT -eq 1 ]; then + ./tools/push-to-arduino.sh +fi diff --git a/components/arduino_tinyusb/CMakeLists.txt b/components/arduino_tinyusb/CMakeLists.txt new file mode 100755 index 0000000..041eeec --- /dev/null +++ b/components/arduino_tinyusb/CMakeLists.txt @@ -0,0 +1,62 @@ +idf_component_register(REQUIRES esp_rom freertos soc PRIV_REQUIRES arduino main) + +if(CONFIG_TINYUSB_ENABLED) + + ### variables ### + ################# + # if(IDF_TARGET STREQUAL "esp32s2") + set(compile_options + "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + "-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DEBUG_LEVEL}" + "-Wno-type-limits" # needed for the vanila tinyusb with turned off classes + ) + # elseif(IDF_TARGET STREQUAL "esp32s3") + # set(compile_options + # "-DCFG_TUSB_MCU=OPT_MCU_ESP32S2" + # "-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DEBUG_LEVEL}" + # "-Wno-type-limits" # needed for the vanila tinyusb with turned off classes + # ) + # endif() + idf_component_get_property(FREERTOS_ORIG_INCLUDE_PATH freertos + ORIG_INCLUDE_PATH) + set(includes_private + # tusb: + "${COMPONENT_DIR}/tinyusb/hw/bsp/" + "${COMPONENT_DIR}/tinyusb/src/" + "${COMPONENT_DIR}/tinyusb/src/device" + ) + + set(includes_public + # tusb: + "${FREERTOS_ORIG_INCLUDE_PATH}" + "${COMPONENT_DIR}/tinyusb/src/" + # espressif: + "${COMPONENT_DIR}/include") + set(srcs + # espressif: + "${COMPONENT_DIR}/src/dcd_esp32sx.c" + # tusb: + #"${COMPONENT_DIR}/tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c" + "${COMPONENT_DIR}/tinyusb/src/class/cdc/cdc_device.c" + "${COMPONENT_DIR}/tinyusb/src/class/hid/hid_device.c" + "${COMPONENT_DIR}/tinyusb/src/class/midi/midi_device.c" + "${COMPONENT_DIR}/tinyusb/src/class/msc/msc_device.c" + "${COMPONENT_DIR}/tinyusb/src/class/video/video_device.c" + "${COMPONENT_DIR}/tinyusb/src/class/dfu/dfu_rt_device.c" + "${COMPONENT_DIR}/tinyusb/src/class/vendor/vendor_device.c" + "${COMPONENT_DIR}/tinyusb/src/common/tusb_fifo.c" + "${COMPONENT_DIR}/tinyusb/src/device/usbd_control.c" + "${COMPONENT_DIR}/tinyusb/src/device/usbd.c" + "${COMPONENT_DIR}/tinyusb/src/tusb.c") + + ### tinyusb lib ### + ################### + add_library(arduino_tinyusb STATIC ${srcs}) + target_include_directories( + arduino_tinyusb + PUBLIC ${includes_public} + PRIVATE ${includes_private}) + target_compile_options(arduino_tinyusb PRIVATE ${compile_options}) + target_link_libraries(${COMPONENT_TARGET} INTERFACE arduino_tinyusb) + +endif() diff --git a/components/arduino_tinyusb/Kconfig.projbuild b/components/arduino_tinyusb/Kconfig.projbuild new file mode 100755 index 0000000..a6abd4d --- /dev/null +++ b/components/arduino_tinyusb/Kconfig.projbuild @@ -0,0 +1,218 @@ +menu "Arduino TinyUSB" + + config TINYUSB_ENABLED + bool "Enable TinyUSB driver" + default y + depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + select FREERTOS_SUPPORT_STATIC_ALLOCATION + select FREERTOS_USE_AUTHENTIC_INCLUDE_PATHS + help + Adds support for TinyUSB + + menu "Serial (CDC) driver" + depends on TINYUSB_ENABLED + + config TINYUSB_CDC_ENABLED + bool "Enable USB Serial (CDC) TinyUSB driver" + default y + help + Enable USB Serial (CDC) TinyUSB driver. + + config TINYUSB_DESC_CDC_STRING + string "CDC Device String" + default "Espressif CDC Device" + depends on TINYUSB_CDC_ENABLED + help + Specify name of the CDC device + + config TINYUSB_CDC_RX_BUFSIZE + int "CDC FIFO size of RX" + default 64 + depends on TINYUSB_CDC_ENABLED + help + CDC FIFO size of RX + + config TINYUSB_CDC_TX_BUFSIZE + int "CDC FIFO size of TX" + default 64 + depends on TINYUSB_CDC_ENABLED + help + CDC FIFO size of TX + + endmenu + + menu "Mass Storage (MSC) driver" + depends on TINYUSB_ENABLED + + config TINYUSB_MSC_ENABLED + bool "Enable USB Mass Storage (MSC) TinyUSB driver" + default y + help + Enable USB Mass Storage (MSC) TinyUSB driver. + + config TINYUSB_DESC_MSC_STRING + string "MSC Device String" + default "Espressif MSC Device" + depends on TINYUSB_MSC_ENABLED + help + Specify name of the MSC device + + config TINYUSB_MSC_BUFSIZE + int "MSC Buffer size" + range 512 4096 + default 4096 + depends on TINYUSB_MSC_ENABLED + help + MSC Buffer size + + endmenu + + menu "Human Interface (HID) driver" + depends on TINYUSB_ENABLED + + config TINYUSB_HID_ENABLED + bool "Enable USB Human Interface (HID) TinyUSB driver" + default y + help + Enable USB Human Interface (HID) TinyUSB driver. + + config TINYUSB_DESC_HID_STRING + string "HID Device String" + default "Espressif HID Device" + depends on TINYUSB_HID_ENABLED + help + Specify name of the HID device + + config TINYUSB_HID_BUFSIZE + int "HID Buffer size" + default 64 + depends on TINYUSB_HID_ENABLED + help + HID Buffer size. Should be sufficient to hold ID (if any) + Data + + endmenu + + menu "MIDI driver" + depends on TINYUSB_ENABLED + + config TINYUSB_MIDI_ENABLED + bool "Enable USB MIDI TinyUSB driver" + default y + help + Enable USB MIDI TinyUSB driver. + + config TINYUSB_DESC_MIDI_STRING + string "MIDI Device String" + default "Espressif MIDI Device" + depends on TINYUSB_MIDI_ENABLED + help + Specify name of the MIDI device + + config TINYUSB_MIDI_RX_BUFSIZE + int "MIDI FIFO size of RX" + default 64 + depends on TINYUSB_MIDI_ENABLED + help + MIDI FIFO size of RX + + config TINYUSB_MIDI_TX_BUFSIZE + int "MIDI FIFO size of TX" + default 64 + depends on TINYUSB_MIDI_ENABLED + help + MIDI FIFO size of TX + + endmenu + + menu "VIDEO driver" + depends on TINYUSB_ENABLED + + config TINYUSB_VIDEO_ENABLED + bool "Enable USB VIDEO TinyUSB driver" + default y + help + Enable USB VIDEO TinyUSB driver. + + config TINYUSB_DESC_VIDEO_STRING + string "VIDEO Device String" + default "Espressif VIDEO Device" + depends on TINYUSB_VIDEO_ENABLED + help + Specify name of the VIDEO device + + config TINYUSB_VIDEO_STREAMING_BUFSIZE + int "VIDEO streaming endpoint size" + range 0 64 + default 64 + depends on TINYUSB_VIDEO_ENABLED + help + VIDEO streaming endpoint size + + config TINYUSB_VIDEO_STREAMING_IFS + int "Number of VIDEO streaming interfaces" + range 1 3 + default 1 + depends on TINYUSB_VIDEO_ENABLED + help + The number of VIDEO streaming interfaces + endmenu + + menu "DFU Runtime driver" + depends on TINYUSB_ENABLED + + config TINYUSB_DFU_RT_ENABLED + bool "Enable USB DFU Runtime TinyUSB driver" + default y + help + Enable USB DFU Runtime TinyUSB driver. + + config TINYUSB_DESC_DFU_RT_STRING + string "DFU_RT Device String" + default "Espressif DFU_RT Device" + depends on TINYUSB_DFU_RT_ENABLED + help + Specify name of the DFU_RT device + + endmenu + + menu "VENDOR driver" + depends on TINYUSB_ENABLED + + config TINYUSB_VENDOR_ENABLED + bool "Enable USB VENDOR TinyUSB driver" + default y + help + Enable USB VENDOR TinyUSB driver. + + config TINYUSB_DESC_VENDOR_STRING + string "VENDOR Device String" + default "Espressif VENDOR Device" + depends on TINYUSB_VENDOR_ENABLED + help + Specify name of the VENDOR device + + config TINYUSB_VENDOR_RX_BUFSIZE + int "VENDOR FIFO size of RX" + default 64 + depends on TINYUSB_VENDOR_ENABLED + help + VENDOR FIFO size of RX + + config TINYUSB_VENDOR_TX_BUFSIZE + int "VENDOR FIFO size of TX" + default 64 + depends on TINYUSB_VENDOR_ENABLED + help + VENDOR FIFO size of TX + + endmenu + + config TINYUSB_DEBUG_LEVEL + int "TinyUSB log level (0-3)" + default 0 + range 0 3 + depends on TINYUSB_ENABLED + help + Define amount of log output from TinyUSB + +endmenu diff --git a/components/arduino_tinyusb/include/tusb_config.h b/components/arduino_tinyusb/include/tusb_config.h new file mode 100755 index 0000000..a5a0afd --- /dev/null +++ b/components/arduino_tinyusb/include/tusb_config.h @@ -0,0 +1,135 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org), + * Additions Copyright (c) 2020, Espressif Systems (Shanghai) PTE LTD + * + * 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 "tusb_option.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* */ +/* KCONFIG */ +/* */ + +#ifndef CONFIG_TINYUSB_CDC_ENABLED +# define CONFIG_TINYUSB_CDC_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_MSC_ENABLED +# define CONFIG_TINYUSB_MSC_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_HID_ENABLED +# define CONFIG_TINYUSB_HID_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_MIDI_ENABLED +# define CONFIG_TINYUSB_MIDI_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_VIDEO_ENABLED +# define CONFIG_TINYUSB_VIDEO_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED +# define CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_DFU_RT_ENABLED +# define CONFIG_TINYUSB_DFU_RT_ENABLED 0 +#endif + +#ifndef CONFIG_TINYUSB_VENDOR_ENABLED +# define CONFIG_TINYUSB_VENDOR_ENABLED 0 +#endif + +/* */ +/* COMMON CONFIGURATION */ +/* */ + +#define CFG_TUSB_MCU OPT_MCU_ESP32S2 +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#define CFG_TUSB_OS OPT_OS_FREERTOS + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +# define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +# define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) +#endif + +/* */ +/* DRIVER CONFIGURATION */ +/* */ + +#define CFG_TUD_MAINTASK_SIZE 4096 +#define CFG_TUD_ENDOINT0_SIZE 64 + +// Enabled Drivers +#define CFG_TUD_CDC CONFIG_TINYUSB_CDC_ENABLED +#define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED +#define CFG_TUD_HID CONFIG_TINYUSB_HID_ENABLED +#define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_ENABLED +#define CFG_TUD_VIDEO CONFIG_TINYUSB_VIDEO_ENABLED +#define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED +#define CFG_TUD_DFU_RUNTIME CONFIG_TINYUSB_DFU_RT_ENABLED +#define CFG_TUD_VENDOR CONFIG_TINYUSB_VENDOR_ENABLED + +// CDC FIFO size of TX and RX +#define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE +#define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE + +// MSC Buffer size of Device Mass storage: +#define CFG_TUD_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE + +// HID buffer size Should be sufficient to hold ID (if any) + Data +#define CFG_TUD_HID_BUFSIZE CONFIG_TINYUSB_HID_BUFSIZE + +// MIDI FIFO size of TX and RX +#define CFG_TUD_MIDI_RX_BUFSIZE CONFIG_TINYUSB_MIDI_RX_BUFSIZE +#define CFG_TUD_MIDI_TX_BUFSIZE CONFIG_TINYUSB_MIDI_TX_BUFSIZE + +// The number of video streaming interfaces and endpoint size +#define CFG_TUD_VIDEO_STREAMING CONFIG_TINYUSB_VIDEO_STREAMING_IFS +#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE CONFIG_TINYUSB_VIDEO_STREAMING_BUFSIZE + +// VENDOR FIFO size of TX and RX +#define CFG_TUD_VENDOR_RX_BUFSIZE CONFIG_TINYUSB_VENDOR_RX_BUFSIZE +#define CFG_TUD_VENDOR_TX_BUFSIZE CONFIG_TINYUSB_VENDOR_TX_BUFSIZE + +#ifdef __cplusplus +} +#endif diff --git a/components/arduino_tinyusb/src/dcd_esp32sx.c b/components/arduino_tinyusb/src/dcd_esp32sx.c new file mode 100755 index 0000000..048b44e --- /dev/null +++ b/components/arduino_tinyusb/src/dcd_esp32sx.c @@ -0,0 +1,923 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft, 2019 William D. Jones for Adafruit Industries + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * Additions Copyright (c) 2020, Espressif Systems (Shanghai) Co. Ltd. + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (((CFG_TUSB_MCU == OPT_MCU_ESP32S2) || (CFG_TUSB_MCU == OPT_MCU_ESP32S3)) && TUSB_OPT_DEVICE_ENABLED) + +// Espressif +#include "driver/periph_ctrl.h" +#include "freertos/xtensa_api.h" +#include "esp_intr_alloc.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "soc/dport_reg.h" +#include "soc/gpio_sig_map.h" +#include "soc/usb_periph.h" + +#include "device/dcd.h" + +// Max number of bi-directional endpoints including EP0 +// Note: ESP32S2 specs say there are only up to 5 IN active endpoints include EP0 +// We should probably prohibit enabling Endpoint IN > 4 (not done yet) +#define EP_MAX USB_OUT_EP_NUM + +// FIFO size in bytes +#define EP_FIFO_SIZE 1024 + +// Max number of IN EP FIFOs +#define EP_FIFO_NUM 5 + +typedef struct { + uint8_t *buffer; + // tu_fifo_t * ff; // TODO support dcd_edpt_xfer_fifo API + uint16_t total_len; + uint16_t queued_len; + uint16_t max_size; + bool short_packet; +} xfer_ctl_t; + +static const char *TAG = "TUSB:DCD"; +static intr_handle_t usb_ih; + + +static uint32_t _setup_packet[2]; + +#define XFER_CTL_BASE(_ep, _dir) &xfer_status[_ep][_dir] +static xfer_ctl_t xfer_status[EP_MAX][2]; + +// Keep count of how many FIFOs are in use +static uint8_t _allocated_fifos = 1; //FIFO0 is always in use + +// Will either return an unused FIFO number, or 0 if all are used. +static uint8_t get_free_fifo(void) +{ + if (_allocated_fifos < EP_FIFO_NUM) return _allocated_fifos++; + return 0; +} + +// Setup the control endpoint 0. +static void bus_reset(void) +{ + for (int ep_num = 0; ep_num < USB_OUT_EP_NUM; ep_num++) { + USB0.out_ep_reg[ep_num].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + // clear device address + USB0.dcfg &= ~USB_DEVADDR_M; + + USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk = USB_SETUPMSK_M | USB_XFERCOMPLMSK; + USB0.diepmsk = USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M /*| USB_INTKNTXFEMPMSK_M*/; + + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): + // - Each EP IN needs at least max packet size, 16 words is sufficient for EP0 IN + // + // - All EP OUT shared a unique OUT FIFO which uses + // * 10 locations in hardware for setup packets + setup control words (up to 3 setup packets). + // * 2 locations for OUT endpoint control words. + // * 16 for largest packet size of 64 bytes. ( TODO Highspeed is 512 bytes) + // * 1 location for global NAK (not required/used here). + // * It is recommended to allocate 2 times the largest packet size, therefore + // Recommended value = 10 + 1 + 2 x (16+2) = 47 --> Let's make it 52 + USB0.grstctl |= 0x10 << USB_TXFNUM_S; // fifo 0x10, + USB0.grstctl |= USB_TXFFLSH_M; // Flush fifo + USB0.grxfsiz = 52; + + // Control IN uses FIFO 0 with 64 bytes ( 16 32-bit word ) + USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); + + // Ready to receive SETUP packet + USB0.out_ep_reg[0].doeptsiz |= USB_SUPCNT0_M; + + USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; +} + +static void enum_done_processing(void) +{ + ESP_EARLY_LOGV(TAG, "dcd_int_handler - Speed enumeration done! Sending DCD_EVENT_BUS_RESET then"); + // On current silicon on the Full Speed core, speed is fixed to Full Speed. + // However, keep for debugging and in case Low Speed is ever supported. + uint32_t enum_spd = (USB0.dsts >> USB_ENUMSPD_S) & (USB_ENUMSPD_V); + + // Maximum packet size for EP 0 is set for both directions by writing DIEPCTL + if (enum_spd == 0x03) { // Full-Speed (PHY on 48 MHz) + USB0.in_ep_reg[0].diepctl &= ~USB_D_MPS0_V; // 64 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + } else { + USB0.in_ep_reg[0].diepctl |= USB_D_MPS0_V; // 8 bytes + USB0.in_ep_reg[0].diepctl &= ~USB_D_STALL0_M; // clear Stall + xfer_status[0][TUSB_DIR_OUT].max_size = 8; + xfer_status[0][TUSB_DIR_IN].max_size = 8; + } +} + + +/*------------------------------------------------------------------*/ +/* Controller API + *------------------------------------------------------------------*/ +void dcd_init(uint8_t rhport) +{ + ESP_LOGV(TAG, "DCD init - Start"); + + bool did_persist = (USB_WRAP.date.val & (1 << 31)) != 0; + + if (did_persist) { + //Clear persistence of USB peripheral through reset + USB_WRAP.date.val = 0; + } else { + // A. Disconnect + ESP_LOGV(TAG, "DCD init - Soft DISCONNECT and Setting up"); + USB0.dctl |= USB_SFTDISCON_M; // Soft disconnect + + // B. Programming DCFG + /* If USB host misbehaves during status portion of control xfer + (non zero-length packet), send STALL back and discard. Full speed. */ + USB0.dcfg |= USB_NZSTSOUTHSHK_M | // NonZero .... STALL + (3 << 0); // dev speed: fullspeed 1.1 on 48 mhz // TODO no value in usb_reg.h (IDF-1476) + } + + USB0.gahbcfg |= USB_NPTXFEMPLVL_M | USB_GLBLLNTRMSK_M; // Global interruptions ON + USB0.gusbcfg |= USB_FORCEDEVMODE_M; // force devmode + USB0.gotgctl &= ~(USB_BVALIDOVVAL_M | USB_BVALIDOVEN_M | USB_VBVALIDOVVAL_M); //no overrides + + // C. Setting SNAKs, then connect + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + USB0.out_ep_reg[n].doepctl |= USB_DO_SNAK0_M; // DOEPCTL0_SNAK + } + + if (!did_persist) { + // D. Interruption masking + USB0.gintmsk = 0; //mask all + USB0.gotgint = ~0U; //clear OTG ints + USB0.gintsts = ~0U; //clear pending ints + } + + USB0.gintmsk = USB_OTGINTMSK_M | + USB_MODEMISMSK_M | + USB_RXFLVIMSK_M | + USB_ERLYSUSPMSK_M | + USB_USBSUSPMSK_M | + USB_USBRSTMSK_M | + USB_ENUMDONEMSK_M | + USB_RESETDETMSK_M | + USB_DISCONNINTMSK_M; // host most only + if (did_persist) { + USB0.grstctl &= ~USB_TXFNUM_M; + USB0.grstctl |= 0x10 << USB_TXFNUM_S; + USB0.grstctl |= USB_TXFFLSH; + USB0.grxfsiz = 52; + + for (int n = 0; n < USB_IN_EP_NUM; n++) { + USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M | USB_D_TXFEMP0_M; + USB0.in_ep_reg[n].diepctl &= ~USB_D_STALL0_M; // clear Stall + USB0.in_ep_reg[n].diepctl |= USB_D_CNAK0 | USB_D_EPENA0; // clear NAK + } + USB0.dtknqr4_fifoemptymsk &= ~(0x7F); + + USB0.gnptxfsiz = (16 << USB_NPTXFDEP_S) | (USB0.grxfsiz & 0x0000ffffUL); + + USB0.daintmsk |= USB_OUTEPMSK0_M | USB_INEPMSK0_M; + USB0.doepmsk |= USB_SETUP0 | USB_XFERCOMPLMSK; + USB0.diepmsk |= USB_TIMEOUTMSK_M | USB_DI_XFERCOMPLMSK_M;//USB_INEPNAKEFFMSK + + USB0.gintmsk |= USB_IEPINTMSK_M | USB_OEPINTMSK_M; + USB0.gotgint = ~0; //clear OTG ints + USB0.gintsts = ~0; //clear pending ints + enum_done_processing(); + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + tusb_control_request_t request = { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, + .bRequest = TUSB_REQ_SET_CONFIGURATION, + .wValue = 1, + .wIndex = 0, + .wLength = 0 + }; + dcd_event_setup_received(0, (uint8_t *)&request, true); + } else { + dcd_connect(rhport); + } +} + +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + ESP_LOGV(TAG, "DCD init - Set address : %u", dev_addr); + USB0.dcfg |= ((dev_addr & USB_DEVADDR_V) << USB_DEVADDR_S); + // Response with status after changing device address + dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + + // set remote wakeup + USB0.dctl |= USB_RMTWKUPSIG_M; + + // enable SOF to detect bus resume + USB0.gintsts = USB_SOF_M; + USB0.gintmsk |= USB_SOFMSK_M; + + // Per specs: remote wakeup signal bit must be clear within 1-15ms + vTaskDelay(pdMS_TO_TICKS(1)); + + USB0.dctl &= ~USB_RMTWKUPSIG_M; +} + +// connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void) rhport; + USB0.dctl &= ~USB_SFTDISCON_M; +} + +// disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void) rhport; + USB0.dctl |= USB_SFTDISCON_M; +} + +/*------------------------------------------------------------------*/ +/* DCD Endpoint port + *------------------------------------------------------------------*/ + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_edpt) +{ + ESP_LOGV(TAG, "DCD endpoint opened"); + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(desc_edpt->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(desc_edpt->bEndpointAddress); + + TU_ASSERT(epnum < EP_MAX); + + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, dir); + xfer->max_size = tu_edpt_packet_size(desc_edpt); + + if (dir == TUSB_DIR_OUT) { + out_ep[epnum].doepctl &= ~(USB_D_EPTYPE0_M | USB_D_MPS0_M); + out_ep[epnum].doepctl |= USB_USBACTEP1_M | + desc_edpt->bmAttributes.xfer << USB_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? USB_DO_SETD0PID1_M : 0) | + xfer->max_size << USB_MPS1_S; + USB0.daintmsk |= (1 << (16 + epnum)); + } else { + // "USB Data FIFOs" section in reference manual + // Peripheral FIFO architecture + // + // --------------- 320 or 1024 ( 1280 or 4096 bytes ) + // | IN FIFO MAX | + // --------------- + // | ... | + // --------------- y + x + 16 + GRXFSIZ + // | IN FIFO 2 | + // --------------- x + 16 + GRXFSIZ + // | IN FIFO 1 | + // --------------- 16 + GRXFSIZ + // | IN FIFO 0 | + // --------------- GRXFSIZ + // | OUT FIFO | + // | ( Shared ) | + // --------------- 0 + // + // Since OUT FIFO = GRXFSIZ, FIFO 0 = 16, for simplicity, we equally allocated for the rest of endpoints + // - Size : (FIFO_SIZE/4 - GRXFSIZ - 16) / (EP_MAX-1) + // - Offset: GRXFSIZ + 16 + Size*(epnum-1) + // - IN EP 1 gets FIFO 1, IN EP "n" gets FIFO "n". + + uint8_t fifo_num = 0; + // Special Case for EP5, which is used by CDC but not actually called by the driver + // we can give it a fake FIFO + if (epnum == 5) { + fifo_num = EP_FIFO_NUM; + } else { + fifo_num = get_free_fifo(); + } + TU_ASSERT(fifo_num != 0); + + in_ep[epnum].diepctl &= ~(USB_D_TXFNUM1_M | USB_D_EPTYPE1_M | USB_DI_SETD0PID1 | USB_D_MPS1_M); + in_ep[epnum].diepctl |= USB_D_USBACTEP1_M | + fifo_num << USB_D_TXFNUM1_S | + desc_edpt->bmAttributes.xfer << USB_D_EPTYPE1_S | + (desc_edpt->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? (1 << USB_DI_SETD0PID1_S) : 0) | + xfer->max_size << 0; + + USB0.daintmsk |= (1 << (0 + epnum)); + + // Both TXFD and TXSA are in unit of 32-bit words. + // IN FIFO 0 was configured during enumeration, hence the "+ 16". + uint16_t const allocated_size = (USB0.grxfsiz & 0x0000ffff) + 16; + uint16_t const fifo_size = (EP_FIFO_SIZE/4 - allocated_size) / (EP_FIFO_NUM-1); + uint32_t const fifo_offset = allocated_size + fifo_size*(fifo_num-1); + + // DIEPTXF starts at FIFO #1. + USB0.dieptxf[epnum - 1] = (fifo_size << USB_NPTXFDEP_S) | fifo_offset; + } + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) +{ + (void) rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + // Disable non-control interrupt + USB0.daintmsk = USB_OUTEPMSK0_M | USB_INEPMSK0_M; + + for(uint8_t n = 1; n < EP_MAX; n++) + { + // disable OUT endpoint + out_ep[n].doepctl = 0; + xfer_status[n][TUSB_DIR_OUT].max_size = 0; + + // disable IN endpoint + in_ep[n].diepctl = 0; + xfer_status[n][TUSB_DIR_IN].max_size = 0; + } + + _allocated_fifos = 1; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + xfer_ctl_t * xfer = XFER_CTL_BASE(epnum, dir); + xfer->buffer = buffer; + // xfer->ff = NULL; // TODO support dcd_edpt_xfer_fifo API + xfer->total_len = total_bytes; + xfer->queued_len = 0; + xfer->short_packet = false; + + uint16_t num_packets = (total_bytes / xfer->max_size); + uint8_t short_packet_size = total_bytes % xfer->max_size; + + // Zero-size packet is special case. + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } + + ESP_LOGV(TAG, "Transfer <-> EP%i, %s, pkgs: %i, bytes: %i", + epnum, ((dir == TUSB_DIR_IN) ? "USB0.HOST (in)" : "HOST->DEV (out)"), + num_packets, total_bytes); + + // IN and OUT endpoint xfers are interrupt-driven, we just schedule them + // here. + if (dir == TUSB_DIR_IN) { + // A full IN transfer (multiple packets, possibly) triggers XFRC. + USB0.in_ep_reg[epnum].dieptsiz = (num_packets << USB_D_PKTCNT0_S) | total_bytes; + USB0.in_ep_reg[epnum].diepctl |= USB_D_EPENA1_M | USB_D_CNAK1_M; // Enable | CNAK + + // Enable fifo empty interrupt only if there are something to put in the fifo. + if(total_bytes != 0) { + USB0.dtknqr4_fifoemptymsk |= (1 << epnum); + } + } else { + // Each complete packet for OUT xfers triggers XFRC. + USB0.out_ep_reg[epnum].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[epnum].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + return true; +} + +#if 0 // TODO support dcd_edpt_xfer_fifo API +bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void)rhport; +} +#endif + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(in_ep[epnum].diepctl & USB_D_EPENA1_M)) { + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M); + } else { + // Stop transmitting packets and NAK IN xfers. + in_ep[epnum].diepctl |= USB_DI_SNAK1_M; + while ((in_ep[epnum].diepint & USB_DI_SNAK1_M) == 0) ; + + // Disable the endpoint. Note that both SNAK and STALL are set here. + in_ep[epnum].diepctl |= (USB_DI_SNAK1_M | USB_D_STALL1_M | USB_D_EPDIS1_M); + while ((in_ep[epnum].diepint & USB_D_EPDISBLD0_M) == 0) ; + in_ep[epnum].diepint = USB_D_EPDISBLD0_M; + } + + // Flush the FIFO, and wait until we have confirmed it cleared. + uint8_t const fifo_num = ((in_ep[epnum].diepctl >> USB_D_TXFNUM1_S) & USB_D_TXFNUM1_V); + USB0.grstctl |= (fifo_num << USB_TXFNUM_S); + USB0.grstctl |= USB_TXFFLSH_M; + while ((USB0.grstctl & USB_TXFFLSH_M) != 0) ; + } else { + // Only disable currently enabled non-control endpoint + if ((epnum == 0) || !(out_ep[epnum].doepctl & USB_EPENA0_M)) { + out_ep[epnum].doepctl |= USB_STALL0_M; + } else { + // Asserting GONAK is required to STALL an OUT endpoint. + // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt + // anyway, and it can't be cleared by user code. If this while loop never + // finishes, we have bigger problems than just the stack. + USB0.dctl |= USB_SGOUTNAK_M; + while ((USB0.gintsts & USB_GOUTNAKEFF_M) == 0) ; + + // Ditto here- disable the endpoint. Note that only STALL and not SNAK + // is set here. + out_ep[epnum].doepctl |= (USB_STALL0_M | USB_EPDIS0_M); + while ((out_ep[epnum].doepint & USB_EPDISBLD0_M) == 0) ; + out_ep[epnum].doepint = USB_EPDISBLD0_M; + + // Allow other OUT endpoints to keep receiving. + USB0.dctl |= USB_CGOUTNAK_M; + } + } +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + + usb_out_endpoint_t *out_ep = &(USB0.out_ep_reg[0]); + usb_in_endpoint_t *in_ep = &(USB0.in_ep_reg[0]); + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if (dir == TUSB_DIR_IN) { + in_ep[epnum].diepctl &= ~USB_D_STALL1_M; + + uint8_t eptype = (in_ep[epnum].diepctl & USB_D_EPTYPE1_M) >> USB_D_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + in_ep[epnum].diepctl |= USB_DI_SETD0PID1_M; + } + } else { + out_ep[epnum].doepctl &= ~USB_STALL1_M; + + uint8_t eptype = (out_ep[epnum].doepctl & USB_EPTYPE1_M) >> USB_EPTYPE1_S; + // Required by USB spec to reset DATA toggle bit to DATA0 on interrupt + // and bulk endpoints. + if (eptype == 2 || eptype == 3) { + out_ep[epnum].doepctl |= USB_DO_SETD0PID1_M; + } + } +} + +/*------------------------------------------------------------------*/ + +static void receive_packet(xfer_ctl_t *xfer, /* usb_out_endpoint_t * out_ep, */ uint16_t xfer_size) +{ + ESP_EARLY_LOGV(TAG, "USB - receive_packet"); + volatile uint32_t *rx_fifo = USB0.fifo[0]; + + // See above TODO + // uint16_t remaining = (out_ep->DOEPTSIZ & UsbDOEPTSIZ_XFRSIZ_Msk) >> UsbDOEPTSIZ_XFRSIZ_Pos; + // xfer->queued_len = xfer->total_len - remaining; + + uint16_t remaining = xfer->total_len - xfer->queued_len; + uint16_t to_recv_size; + + if (remaining <= xfer->max_size) { + // Avoid buffer overflow. + to_recv_size = (xfer_size > remaining) ? remaining : xfer_size; + } else { + // Room for full packet, choose recv_size based on what the microcontroller + // claims. + to_recv_size = (xfer_size > xfer->max_size) ? xfer->max_size : xfer_size; + } + + // Common buffer read +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + // Ring buffer + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void *) rx_fifo, to_recv_size); + } + else +#endif + { + uint8_t to_recv_rem = to_recv_size % 4; + uint16_t to_recv_size_aligned = to_recv_size - to_recv_rem; + + // Do not assume xfer buffer is aligned. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to collect. + if (to_recv_size >= 4) { + for (uint16_t i = 0; i < to_recv_size_aligned; i += 4) { + uint32_t tmp = (*rx_fifo); + base[i] = tmp & 0x000000FF; + base[i + 1] = (tmp & 0x0000FF00) >> 8; + base[i + 2] = (tmp & 0x00FF0000) >> 16; + base[i + 3] = (tmp & 0xFF000000) >> 24; + } + } + + // Do not read invalid bytes from RX FIFO. + if (to_recv_rem != 0) { + uint32_t tmp = (*rx_fifo); + uint8_t *last_32b_bound = base + to_recv_size_aligned; + + last_32b_bound[0] = tmp & 0x000000FF; + if (to_recv_rem > 1) { + last_32b_bound[1] = (tmp & 0x0000FF00) >> 8; + } + if (to_recv_rem > 2) { + last_32b_bound[2] = (tmp & 0x00FF0000) >> 16; + } + } + } + + xfer->queued_len += xfer_size; + + // Per USB spec, a short OUT packet (including length 0) is always + // indicative of the end of a transfer (at least for ctl, bulk, int). + xfer->short_packet = (xfer_size < xfer->max_size); +} + +static void transmit_packet(xfer_ctl_t *xfer, volatile usb_in_endpoint_t *in_ep, uint8_t fifo_num) +{ + ESP_EARLY_LOGV(TAG, "USB - transmit_packet"); + volatile uint32_t *tx_fifo = USB0.fifo[fifo_num]; + + uint16_t remaining = (in_ep->dieptsiz & 0x7FFFFU) >> USB_D_XFERSIZE0_S; + xfer->queued_len = xfer->total_len - remaining; + + uint16_t to_xfer_size = (remaining > xfer->max_size) ? xfer->max_size : remaining; + +#if 0 // TODO support dcd_edpt_xfer_fifo API + if (xfer->ff) + { + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void *) tx_fifo, to_xfer_size); + } + else +#endif + { + uint8_t to_xfer_rem = to_xfer_size % 4; + uint16_t to_xfer_size_aligned = to_xfer_size - to_xfer_rem; + + // Buffer might not be aligned to 32b, so we need to force alignment + // by copying to a temp var. + uint8_t *base = (xfer->buffer + xfer->queued_len); + + // This for loop always runs at least once- skip if less than 4 bytes + // to send off. + if (to_xfer_size >= 4) { + for (uint16_t i = 0; i < to_xfer_size_aligned; i += 4) { + uint32_t tmp = base[i] | (base[i + 1] << 8) | + (base[i + 2] << 16) | (base[i + 3] << 24); + (*tx_fifo) = tmp; + } + } + + // Do not read beyond end of buffer if not divisible by 4. + if (to_xfer_rem != 0) { + uint32_t tmp = 0; + uint8_t *last_32b_bound = base + to_xfer_size_aligned; + + tmp |= last_32b_bound[0]; + if (to_xfer_rem > 1) { + tmp |= (last_32b_bound[1] << 8); + } + if (to_xfer_rem > 2) { + tmp |= (last_32b_bound[2] << 16); + } + + (*tx_fifo) = tmp; + } + } +} + +static void read_rx_fifo(void) +{ + // Pop control word off FIFO (completed xfers will have 2 control words, + // we only pop one ctl word each interrupt). + uint32_t const ctl_word = USB0.grxstsp; + uint8_t const pktsts = (ctl_word & USB_PKTSTS_M) >> USB_PKTSTS_S; + uint8_t const epnum = (ctl_word & USB_CHNUM_M ) >> USB_CHNUM_S; + uint16_t const bcnt = (ctl_word & USB_BCNT_M ) >> USB_BCNT_S; + + switch (pktsts) { + case 0x01: // Global OUT NAK (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Global OUT NAK"); + break; + + case 0x02: { // Out packet recvd + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet"); + xfer_ctl_t *xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + receive_packet(xfer, bcnt); + } + break; + + case 0x03: // Out packet done (Interrupt) + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX type : Out packet done"); + break; + + case 0x04: // Step 2: Setup transaction completed (Interrupt) + // After this event, OEPINT interrupt will occur with SETUP bit set + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet done"); + USB0.out_ep_reg[epnum].doeptsiz |= USB_SUPCNT0_M; + break; + + case 0x06: { // Step1: Setup data packet received + volatile uint32_t *rx_fifo = USB0.fifo[0]; + + // We can receive up to three setup packets in succession, but + // only the last one is valid. Therefore we just overwrite it + _setup_packet[0] = (*rx_fifo); + _setup_packet[1] = (*rx_fifo); + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - RX : Setup packet : 0x%08x 0x%08x", _setup_packet[0], _setup_packet[1]); + } + break; + + default: // Invalid, do something here, like breakpoint? + TU_BREAKPOINT(); + break; + } +} + +static void handle_epout_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DOEPINTx is cleared. + // DOEPINT will be cleared when DAINT's out bits are cleared. + for (int n = 0; n < USB_OUT_EP_NUM; n++) { + xfer_ctl_t *xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + + if (USB0.daint & (1 << (16 + n))) { + // SETUP packet Setup Phase done. + if ((USB0.out_ep_reg[n].doepint & USB_SETUP0_M)) { + USB0.out_ep_reg[n].doepint = USB_STUPPKTRCVD0_M | USB_SETUP0_M; // clear + dcd_event_setup_received(0, (uint8_t *)&_setup_packet[0], true); + } + + // OUT XFER complete (single packet).q + if (USB0.out_ep_reg[n].doepint & USB_XFERCOMPL0_M) { + + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP OUT - XFER complete (single packet)"); + USB0.out_ep_reg[n].doepint = USB_XFERCOMPL0_M; + + // Transfer complete if short packet or total len is transferred + if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { + xfer->short_packet = false; + dcd_event_xfer_complete(0, n, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } else { + // Schedule another packet to be received. + USB0.out_ep_reg[n].doeptsiz |= USB_PKTCNT0_M | ((xfer->max_size & USB_XFERSIZE0_V) << USB_XFERSIZE0_S); + USB0.out_ep_reg[n].doepctl |= USB_EPENA0_M | USB_CNAK0_M; + } + } + } + } +} + +static void handle_epin_ints(void) +{ + // GINTSTS will be cleared with DAINT == 0 + // DAINT for a given EP clears when DIEPINTx is cleared. + // IEPINT will be cleared when DAINT's out bits are cleared. + for (uint32_t n = 0; n < USB_IN_EP_NUM; n++) { + xfer_ctl_t *xfer = &xfer_status[n][TUSB_DIR_IN]; + + if (USB0.daint & (1 << (0 + n))) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - EP IN %u", n); + + if (USB0.in_ep_reg[n].diepint & BIT(15)) { + USB0.in_ep_reg[n].diepint = BIT(15); + ESP_EARLY_LOGE(TAG, "Unknown Condition");//todo: + bus_reset(); + } + + // IN XFER complete (entire xfer). + if (USB0.in_ep_reg[n].diepint & USB_D_XFERCOMPL0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER complete!"); + USB0.in_ep_reg[n].diepint = USB_D_XFERCOMPL0_M; + dcd_event_xfer_complete(0, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + if (!(USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M)) { + ESP_EARLY_LOGE(TAG, "Complete but not empty: %u/%u", xfer->queued_len, xfer->total_len);//todo: + } + } + + // XFER FIFO empty + if (USB0.in_ep_reg[n].diepint & USB_D_TXFEMP0_M) { + ESP_EARLY_LOGV(TAG, "TUSB IRQ - IN XFER FIFO empty!"); + USB0.in_ep_reg[n].diepint = USB_D_TXFEMP0_M; + transmit_packet(xfer, &USB0.in_ep_reg[n], n); + + // Turn off TXFE if all bytes are written. + if (xfer->queued_len == xfer->total_len) + { + USB0.dtknqr4_fifoemptymsk &= ~(1 << n); + } + } + + // XFER Timeout + if (USB0.in_ep_reg[n].diepint & USB_D_TIMEOUT0_M) { + // Clear interrupt or enpoint will hang. + USB0.in_ep_reg[n].diepint = USB_D_TIMEOUT0_M; + ESP_EARLY_LOGE(TAG, "XFER Timeout");//todo: + // Maybe retry? + } + } + } +} + + +static void _dcd_int_handler(void* arg) +{ + (void) arg; + uint8_t const rhport = 0; + + const uint32_t int_msk = USB0.gintmsk; + const uint32_t int_status = USB0.gintsts & int_msk; + + if (int_status & USB_USBRST_M) { + // start of reset + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); + USB0.gintsts = USB_USBRST_M; + // FIFOs will be reassigned when the endpoints are reopen + _allocated_fifos = 1; + bus_reset(); + } + + if (int_status & USB_RESETDET_M) { + ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset while suspend"); + USB0.gintsts = USB_RESETDET_M; + // no need to double reset + if ((int_status & USB_USBRST_M) == 0) { + _allocated_fifos = 1; + bus_reset(); + } + } + + if (int_status & USB_ENUMDONE_M) { + // ENUMDNE detects speed of the link. For full-speed, we + // always expect the same value. This interrupt is considered + // the end of reset. + USB0.gintsts = USB_ENUMDONE_M; + enum_done_processing(); + dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); + } + + if(int_status & USB_USBSUSP_M) + { + USB0.gintsts = USB_USBSUSP_M; + //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + _allocated_fifos = 1; + } + + if(int_status & USB_WKUPINT_M) + { + USB0.gintsts = USB_WKUPINT_M; + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + + if (int_status & USB_OTGINT_M) + { + // OTG INT bit is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected"); + + uint32_t const otg_int = USB0.gotgint; + + if (otg_int & USB_SESENDDET_M) + { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + _allocated_fifos = 1; + } + + USB0.gotgint = otg_int; + } + + if (int_status & USB_SOF_M) { + USB0.gintsts = USB_SOF_M; + + // Disable SOF interrupt since currently only used for remote wakeup detection + USB0.gintmsk &= ~USB_SOFMSK_M; + + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } + + + if (int_status & USB_RXFLVI_M) { + // RXFLVL bit is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); + + // Mask out RXFLVL while reading data from FIFO + USB0.gintmsk &= ~USB_RXFLVIMSK_M; + read_rx_fifo(); + USB0.gintmsk |= USB_RXFLVIMSK_M; + } + + // OUT endpoint interrupt handling. + if (int_status & USB_OEPINT_M) { + // OEPINT is read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); + handle_epout_ints(); + } + + // IN endpoint interrupt handling. + if (int_status & USB_IEPINT_M) { + // IEPINT bit read-only + ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); + handle_epin_ints(); + } + + // Without handling + USB0.gintsts |= USB_CURMOD_INT_M | + USB_MODEMIS_M | + USB_OTGINT_M | + USB_NPTXFEMP_M | + USB_GINNAKEFF_M | + USB_GOUTNAKEFF | + USB_ERLYSUSP_M | + USB_USBSUSP_M | + USB_ISOOUTDROP_M | + USB_EOPF_M | + USB_EPMIS_M | + USB_INCOMPISOIN_M | + USB_INCOMPIP_M | + USB_FETSUSP_M | + USB_PTXFEMP_M; +} + +void dcd_int_enable (uint8_t rhport) +{ + (void) rhport; + esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_LOWMED, (intr_handler_t) _dcd_int_handler, NULL, &usb_ih); +} + +void dcd_int_disable (uint8_t rhport) +{ + (void) rhport; + esp_intr_free(usb_ih); +} + +#endif // #if OPT_MCU_ESP32S2 || OPT_MCU_ESP32S3 + diff --git a/components/fb_gfx/CMakeLists.txt b/components/fb_gfx/CMakeLists.txt new file mode 100644 index 0000000..5b6febc --- /dev/null +++ b/components/fb_gfx/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCS "fb_gfx.c") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_PRIV_INCLUDEDIRS "") +set(COMPONENT_PRIV_REQUIRES newlib) +register_component() \ No newline at end of file diff --git a/components/fb_gfx/FreeMonoBold12pt7b.h b/components/fb_gfx/FreeMonoBold12pt7b.h new file mode 100755 index 0000000..45db126 --- /dev/null +++ b/components/fb_gfx/FreeMonoBold12pt7b.h @@ -0,0 +1,250 @@ +const uint8_t FreeMonoBold12pt7bBitmaps[] = { + 0xFF, 0xFF, 0xFF, 0xF6, 0x66, 0x60, 0x6F, 0x60, 0xE7, 0xE7, 0x62, 0x42, + 0x42, 0x42, 0x42, 0x11, 0x87, 0x30, 0xC6, 0x18, 0xC3, 0x31, 0xFF, 0xFF, + 0xF9, 0x98, 0x33, 0x06, 0x60, 0xCC, 0x7F, 0xEF, 0xFC, 0x66, 0x0C, 0xC3, + 0x98, 0x63, 0x04, 0x40, 0x0C, 0x03, 0x00, 0xC0, 0xFE, 0x7F, 0x9C, 0x66, + 0x09, 0x80, 0x78, 0x0F, 0xE0, 0x7F, 0x03, 0xE0, 0xF8, 0x7F, 0xFB, 0xFC, + 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x38, 0x1F, 0x0C, 0x42, 0x10, 0xC4, 0x1F, + 0x03, 0x9C, 0x3C, 0x7F, 0x33, 0xE0, 0x8C, 0x21, 0x08, 0xC3, 0xE0, 0x70, + 0x3E, 0x1F, 0xC6, 0x61, 0x80, 0x70, 0x0C, 0x07, 0x83, 0xEE, 0xDF, 0xB3, + 0xCC, 0x73, 0xFE, 0x7F, 0x80, 0xFD, 0x24, 0x90, 0x39, 0xDC, 0xE6, 0x73, + 0x18, 0xC6, 0x31, 0x8C, 0x31, 0x8E, 0x31, 0xC4, 0xE7, 0x1C, 0xE3, 0x1C, + 0x63, 0x18, 0xC6, 0x31, 0x98, 0xCE, 0x67, 0x10, 0x0C, 0x03, 0x00, 0xC3, + 0xB7, 0xFF, 0xDF, 0xE1, 0xE0, 0xFC, 0x33, 0x0C, 0xC0, 0x06, 0x00, 0x60, + 0x06, 0x00, 0x60, 0x06, 0x0F, 0xFF, 0xFF, 0xF0, 0x60, 0x06, 0x00, 0x60, + 0x06, 0x00, 0x60, 0x06, 0x00, 0x3B, 0x9C, 0xCE, 0x62, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0x80, 0x00, 0x40, 0x30, 0x1C, 0x07, 0x03, 0x80, 0xE0, 0x30, + 0x1C, 0x06, 0x03, 0x80, 0xC0, 0x70, 0x18, 0x0E, 0x03, 0x01, 0xC0, 0x60, + 0x38, 0x0E, 0x01, 0x00, 0x1E, 0x0F, 0xC6, 0x1B, 0x87, 0xC0, 0xF0, 0x3C, + 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x87, 0x61, 0x8F, 0xC1, 0xE0, 0x1C, + 0x0F, 0x0F, 0xC3, 0xB0, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, + 0xC0, 0x30, 0x0C, 0x3F, 0xFF, 0xFC, 0x1F, 0x1F, 0xEE, 0x1F, 0x83, 0xC0, + 0xC0, 0x70, 0x38, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE3, 0xF0, 0xFF, 0xFF, + 0xFC, 0x3F, 0x0F, 0xF1, 0x87, 0x00, 0x60, 0x0C, 0x03, 0x83, 0xE0, 0x7C, + 0x01, 0xC0, 0x0C, 0x01, 0x80, 0x3C, 0x0F, 0xFF, 0x9F, 0xC0, 0x07, 0x07, + 0x83, 0xC3, 0xE1, 0xB1, 0xD8, 0xCC, 0xC6, 0xE3, 0x7F, 0xFF, 0xE0, 0x61, + 0xF8, 0xFC, 0x7F, 0x9F, 0xE6, 0x01, 0x80, 0x60, 0x1F, 0x87, 0xF9, 0x86, + 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xC1, 0xBF, 0xE7, 0xE0, 0x07, 0xC7, 0xF3, + 0xC1, 0xC0, 0x60, 0x38, 0x0E, 0xF3, 0xFE, 0xF1, 0xF8, 0x3E, 0x0F, 0x83, + 0x71, 0xCF, 0xE1, 0xF0, 0xFF, 0xFF, 0xFC, 0x1F, 0x07, 0x01, 0x80, 0x60, + 0x38, 0x0C, 0x03, 0x01, 0xC0, 0x60, 0x18, 0x0E, 0x03, 0x00, 0xC0, 0x1E, + 0x1F, 0xEE, 0x1F, 0x03, 0xC0, 0xF0, 0x36, 0x19, 0xFE, 0x7F, 0xB8, 0x7C, + 0x0F, 0x03, 0xE1, 0xDF, 0xE3, 0xF0, 0x3E, 0x1F, 0xCE, 0x3B, 0x07, 0xC1, + 0xF0, 0x7E, 0x3D, 0xFF, 0x3D, 0xC0, 0x70, 0x18, 0x0E, 0x0F, 0x3F, 0x8F, + 0x80, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x77, 0x70, 0x00, 0x00, 0x76, 0x6C, + 0xC8, 0x80, 0x00, 0x30, 0x0F, 0x03, 0xE0, 0xF8, 0x3E, 0x0F, 0x80, 0x3E, + 0x00, 0xF8, 0x03, 0xE0, 0x0F, 0x00, 0x20, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x60, 0x0F, 0x80, 0x3E, 0x00, 0xF8, + 0x03, 0xE0, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x0F, 0x00, 0x40, 0x00, 0x7C, + 0x7F, 0xB0, 0xF8, 0x30, 0x18, 0x1C, 0x3C, 0x3C, 0x18, 0x08, 0x00, 0x07, + 0x03, 0x81, 0xC0, 0x1E, 0x07, 0xF1, 0xC7, 0x30, 0x6C, 0x0D, 0x87, 0xB3, + 0xF6, 0xE6, 0xD8, 0xDB, 0x1B, 0x73, 0x67, 0xFC, 0x7F, 0x80, 0x30, 0x03, + 0x00, 0x71, 0xC7, 0xF8, 0x7C, 0x00, 0x3F, 0x80, 0x7F, 0x80, 0x1F, 0x00, + 0x76, 0x00, 0xEE, 0x01, 0x8C, 0x07, 0x18, 0x0E, 0x38, 0x1F, 0xF0, 0x7F, + 0xF0, 0xC0, 0x61, 0x80, 0xCF, 0xC7, 0xFF, 0x8F, 0xC0, 0xFF, 0xC7, 0xFF, + 0x0C, 0x1C, 0x60, 0x63, 0x03, 0x18, 0x38, 0xFF, 0x87, 0xFE, 0x30, 0x39, + 0x80, 0xCC, 0x06, 0x60, 0x7F, 0xFF, 0x7F, 0xF0, 0x0F, 0xF3, 0xFF, 0x70, + 0x76, 0x03, 0xC0, 0x3C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0x60, + 0x37, 0x07, 0x3F, 0xF0, 0xFC, 0xFF, 0x0F, 0xFC, 0x60, 0xE6, 0x06, 0x60, + 0x36, 0x03, 0x60, 0x36, 0x03, 0x60, 0x36, 0x03, 0x60, 0x76, 0x0E, 0xFF, + 0xCF, 0xF8, 0xFF, 0xF7, 0xFF, 0x8C, 0x0C, 0x60, 0x63, 0x1B, 0x18, 0xC0, + 0xFE, 0x07, 0xF0, 0x31, 0x81, 0x8C, 0xCC, 0x06, 0x60, 0x3F, 0xFF, 0xFF, + 0xFC, 0xFF, 0xFF, 0xFF, 0xCC, 0x06, 0x60, 0x33, 0x19, 0x98, 0xC0, 0xFE, + 0x07, 0xF0, 0x31, 0x81, 0x8C, 0x0C, 0x00, 0x60, 0x0F, 0xF0, 0x7F, 0x80, + 0x0F, 0xF1, 0xFF, 0x9C, 0x1C, 0xC0, 0x6C, 0x03, 0x60, 0x03, 0x00, 0x18, + 0x7F, 0xC3, 0xFE, 0x01, 0xB8, 0x0C, 0xE0, 0xE3, 0xFF, 0x07, 0xE0, 0x7C, + 0xF9, 0xF3, 0xE3, 0x03, 0x0C, 0x0C, 0x30, 0x30, 0xC0, 0xC3, 0xFF, 0x0F, + 0xFC, 0x30, 0x30, 0xC0, 0xC3, 0x03, 0x0C, 0x0C, 0xFC, 0xFF, 0xF3, 0xF0, + 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, + 0x00, 0xC0, 0x30, 0xFF, 0xFF, 0xF0, 0x0F, 0xF8, 0x7F, 0xC0, 0x30, 0x01, + 0x80, 0x0C, 0x00, 0x60, 0x03, 0x18, 0x18, 0xC0, 0xC6, 0x06, 0x30, 0x31, + 0xC3, 0x0F, 0xF8, 0x1F, 0x00, 0xFC, 0xFB, 0xF3, 0xE3, 0x0E, 0x0C, 0x70, + 0x33, 0x80, 0xFC, 0x03, 0xF0, 0x0F, 0xE0, 0x39, 0xC0, 0xC3, 0x03, 0x0E, + 0x0C, 0x18, 0xFC, 0x7F, 0xF0, 0xF0, 0xFF, 0x0F, 0xF0, 0x18, 0x01, 0x80, + 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, + 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xC0, 0xF7, 0x87, 0x9E, 0x1E, 0x7C, 0xF9, + 0xB3, 0xE6, 0xFD, 0x99, 0xF6, 0x67, 0x99, 0x8E, 0x66, 0x31, 0x98, 0x06, + 0xFC, 0xFF, 0xF3, 0xF0, 0xF1, 0xFF, 0xCF, 0xCF, 0x0C, 0x78, 0x63, 0xE3, + 0x1B, 0x18, 0xDC, 0xC6, 0x76, 0x31, 0xB1, 0x8F, 0x8C, 0x3C, 0x61, 0xE7, + 0xE7, 0x3F, 0x18, 0x0F, 0x03, 0xFC, 0x70, 0xE6, 0x06, 0xE0, 0x7C, 0x03, + 0xC0, 0x3C, 0x03, 0xC0, 0x3E, 0x07, 0x60, 0x67, 0x0E, 0x3F, 0xC0, 0xF0, + 0xFF, 0x8F, 0xFE, 0x30, 0x73, 0x03, 0x30, 0x33, 0x03, 0x30, 0x73, 0xFE, + 0x3F, 0x83, 0x00, 0x30, 0x03, 0x00, 0xFF, 0x0F, 0xF0, 0x0F, 0x03, 0xFC, + 0x70, 0xE6, 0x06, 0xE0, 0x7C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3E, 0x07, + 0x60, 0x67, 0x0E, 0x3F, 0xC1, 0xF0, 0x18, 0x33, 0xFF, 0x3F, 0xE0, 0xFF, + 0x83, 0xFF, 0x83, 0x07, 0x0C, 0x0C, 0x30, 0x30, 0xC1, 0xC3, 0xFE, 0x0F, + 0xF0, 0x31, 0xE0, 0xC3, 0x83, 0x07, 0x0C, 0x0C, 0xFE, 0x3F, 0xF8, 0x70, + 0x3F, 0xDF, 0xFE, 0x1F, 0x03, 0xC0, 0xF8, 0x07, 0xE0, 0x7E, 0x01, 0xF0, + 0x3C, 0x0F, 0x87, 0xFF, 0xBF, 0xC0, 0xFF, 0xFF, 0xFF, 0xC6, 0x3C, 0x63, + 0xC6, 0x3C, 0x63, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, + 0x3F, 0xC3, 0xFC, 0xFF, 0xFF, 0xFF, 0x60, 0x66, 0x06, 0x60, 0x66, 0x06, + 0x60, 0x66, 0x06, 0x60, 0x66, 0x06, 0x60, 0x63, 0x9C, 0x1F, 0xC0, 0xF0, + 0xFC, 0x3F, 0xFC, 0x3F, 0x30, 0x0C, 0x38, 0x1C, 0x18, 0x18, 0x1C, 0x38, + 0x1C, 0x38, 0x0E, 0x70, 0x0E, 0x70, 0x0F, 0x60, 0x07, 0xE0, 0x07, 0xE0, + 0x03, 0xC0, 0x03, 0xC0, 0xFC, 0xFF, 0xF3, 0xF6, 0x01, 0xDC, 0xC6, 0x77, + 0x99, 0xDE, 0x67, 0x79, 0x8D, 0xFE, 0x3F, 0xF8, 0xF3, 0xE3, 0xCF, 0x8F, + 0x3C, 0x38, 0x70, 0xE1, 0xC0, 0xF8, 0xFB, 0xE3, 0xE3, 0x86, 0x0F, 0x38, + 0x1F, 0xC0, 0x3E, 0x00, 0x70, 0x03, 0xE0, 0x0F, 0x80, 0x77, 0x03, 0x8E, + 0x1E, 0x1C, 0xFC, 0xFF, 0xF3, 0xF0, 0xF9, 0xFF, 0x9F, 0x30, 0xC3, 0x9C, + 0x19, 0x81, 0xF8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, + 0x3F, 0xC3, 0xFC, 0xFF, 0xBF, 0xEC, 0x3B, 0x0C, 0xC6, 0x33, 0x80, 0xC0, + 0x60, 0x38, 0xCC, 0x36, 0x0F, 0x03, 0xFF, 0xFF, 0xF0, 0xFF, 0xF1, 0x8C, + 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC7, 0xFE, 0x40, 0x30, 0x0E, + 0x01, 0x80, 0x70, 0x0C, 0x03, 0x80, 0x60, 0x1C, 0x03, 0x00, 0xE0, 0x18, + 0x07, 0x00, 0xC0, 0x38, 0x0E, 0x01, 0xC0, 0x70, 0x0C, 0x01, 0xFF, 0xC6, + 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x1F, 0xFE, 0x04, 0x03, + 0x01, 0xE0, 0xFC, 0x7B, 0x9C, 0x7E, 0x1F, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, + 0xCE, 0x73, 0x3F, 0x07, 0xF8, 0x00, 0xC0, 0x0C, 0x1F, 0xC7, 0xFC, 0x60, + 0xCC, 0x0C, 0xC1, 0xCF, 0xFF, 0x3F, 0xF0, 0xF0, 0x07, 0x80, 0x0C, 0x00, + 0x60, 0x03, 0x7C, 0x1F, 0xF8, 0xF1, 0xC7, 0x07, 0x30, 0x19, 0x80, 0xCC, + 0x06, 0x60, 0x73, 0xC7, 0x7F, 0xFB, 0xDF, 0x00, 0x1F, 0xB3, 0xFF, 0x70, + 0xFE, 0x07, 0xC0, 0x3C, 0x00, 0xC0, 0x0C, 0x00, 0x70, 0x77, 0xFF, 0x1F, + 0xC0, 0x01, 0xE0, 0x0F, 0x00, 0x18, 0x00, 0xC1, 0xF6, 0x3F, 0xF1, 0xC7, + 0x9C, 0x1C, 0xC0, 0x66, 0x03, 0x30, 0x19, 0x81, 0xC7, 0x1E, 0x3F, 0xFC, + 0x7D, 0xE0, 0x1F, 0x83, 0xFC, 0x70, 0xEE, 0x07, 0xFF, 0xFF, 0xFF, 0xE0, + 0x0E, 0x00, 0x70, 0x73, 0xFF, 0x1F, 0xC0, 0x07, 0xC3, 0xFC, 0x60, 0x0C, + 0x0F, 0xFD, 0xFF, 0x86, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, + 0x81, 0xFF, 0xBF, 0xF0, 0x1F, 0x79, 0xFF, 0xDC, 0x79, 0x81, 0xCC, 0x06, + 0x60, 0x33, 0x01, 0x9C, 0x1C, 0x71, 0xE1, 0xFF, 0x07, 0xD8, 0x00, 0xC0, + 0x06, 0x00, 0x70, 0x7F, 0x03, 0xF0, 0xF0, 0x03, 0xC0, 0x03, 0x00, 0x0C, + 0x00, 0x37, 0xC0, 0xFF, 0x83, 0xC7, 0x0C, 0x0C, 0x30, 0x30, 0xC0, 0xC3, + 0x03, 0x0C, 0x0C, 0x30, 0x33, 0xF3, 0xFF, 0xCF, 0xC0, 0x06, 0x00, 0xC0, + 0x00, 0x3F, 0x07, 0xE0, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, + 0x03, 0x0F, 0xFF, 0xFF, 0xC0, 0x06, 0x06, 0x00, 0xFF, 0xFF, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0xFE, 0xFC, + 0xF0, 0x07, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x3F, 0x19, 0xF8, 0xDE, 0x07, + 0xE0, 0x3E, 0x01, 0xF0, 0x0F, 0xC0, 0x6F, 0x03, 0x1C, 0x78, 0xFF, 0xC7, + 0xE0, 0x7E, 0x0F, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, + 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x61, 0xFF, 0xFF, 0xF8, 0xFE, 0xF1, + 0xFF, 0xF1, 0xCE, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31, + 0x8C, 0x63, 0x19, 0xF7, 0xBF, 0xEF, 0x78, 0x77, 0xC1, 0xFF, 0x83, 0xC7, + 0x0C, 0x0C, 0x30, 0x30, 0xC0, 0xC3, 0x03, 0x0C, 0x0C, 0x30, 0x33, 0xF1, + 0xFF, 0xC7, 0xC0, 0x1F, 0x83, 0xFC, 0x70, 0xEE, 0x07, 0xC0, 0x3C, 0x03, + 0xC0, 0x3E, 0x07, 0x70, 0xE3, 0xFC, 0x1F, 0x80, 0xF7, 0xE3, 0xFF, 0xC3, + 0xC3, 0x8E, 0x07, 0x30, 0x0C, 0xC0, 0x33, 0x00, 0xCE, 0x07, 0x3C, 0x38, + 0xFF, 0xC3, 0x7E, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x0F, 0xE0, 0x3F, 0x80, + 0x1F, 0xBC, 0xFF, 0xF7, 0x0F, 0x38, 0x1C, 0xC0, 0x33, 0x00, 0xCC, 0x03, + 0x38, 0x1C, 0x70, 0xF0, 0xFF, 0xC1, 0xFB, 0x00, 0x0C, 0x00, 0x30, 0x00, + 0xC0, 0x1F, 0xC0, 0x7F, 0x79, 0xE7, 0xFF, 0x1F, 0x31, 0xC0, 0x18, 0x01, + 0x80, 0x18, 0x01, 0x80, 0x18, 0x0F, 0xFC, 0xFF, 0xC0, 0x3F, 0x9F, 0xFE, + 0x1F, 0x82, 0xFE, 0x1F, 0xE0, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xF0, 0x30, + 0x06, 0x00, 0xC0, 0x7F, 0xEF, 0xFC, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, + 0x00, 0xC0, 0x18, 0x71, 0xFE, 0x1F, 0x00, 0xF1, 0xF7, 0x8F, 0x8C, 0x0C, + 0x60, 0x63, 0x03, 0x18, 0x18, 0xC0, 0xC6, 0x06, 0x38, 0xF0, 0xFF, 0xC3, + 0xEE, 0xFC, 0xFF, 0xF3, 0xF3, 0x87, 0x0E, 0x1C, 0x1C, 0x60, 0x73, 0x80, + 0xEC, 0x03, 0xF0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x00, 0xF8, 0x7F, 0xE1, + 0xF7, 0x39, 0x8C, 0xE6, 0x37, 0xB0, 0xFF, 0xC3, 0xFF, 0x07, 0xBC, 0x1C, + 0xF0, 0x73, 0x81, 0x86, 0x00, 0x7C, 0xF9, 0xF3, 0xE3, 0xCF, 0x07, 0xF8, + 0x0F, 0xC0, 0x1E, 0x00, 0xFC, 0x07, 0x38, 0x38, 0x73, 0xF3, 0xFF, 0xCF, + 0xC0, 0xF9, 0xFF, 0x9F, 0x70, 0xE3, 0x0C, 0x39, 0xC1, 0x98, 0x19, 0x81, + 0xF8, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0x60, 0x0E, 0x00, 0xC0, 0xFF, 0x0F, + 0xF0, 0x7F, 0xCF, 0xF9, 0x8E, 0x33, 0x80, 0x70, 0x1C, 0x07, 0x01, 0xC6, + 0x70, 0xFF, 0xFF, 0xFF, 0x80, 0x0E, 0x3C, 0x60, 0xC1, 0x83, 0x06, 0x0C, + 0x39, 0xE3, 0xC0, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x3C, 0x38, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF0, 0xE1, 0xC0, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x3C, + 0x79, 0x83, 0x06, 0x0C, 0x18, 0x31, 0xE3, 0x80, 0x3C, 0x37, 0xE7, 0x67, + 0xE6, 0x1C }; + +const GFXglyph FreeMonoBold12pt7bGlyphs[] = { + { 0, 0, 0, 14, 0, 1 }, // 0x20 ' ' + { 0, 4, 15, 14, 5, -14 }, // 0x21 '!' + { 8, 8, 7, 14, 3, -13 }, // 0x22 '"' + { 15, 11, 18, 14, 2, -15 }, // 0x23 '#' + { 40, 10, 20, 14, 2, -16 }, // 0x24 '$' + { 65, 10, 15, 14, 2, -14 }, // 0x25 '%' + { 84, 10, 13, 14, 2, -12 }, // 0x26 '&' + { 101, 3, 7, 14, 5, -13 }, // 0x27 ''' + { 104, 5, 19, 14, 6, -14 }, // 0x28 '(' + { 116, 5, 19, 14, 3, -14 }, // 0x29 ')' + { 128, 10, 10, 14, 2, -14 }, // 0x2A '*' + { 141, 12, 13, 14, 1, -12 }, // 0x2B '+' + { 161, 5, 7, 14, 4, -2 }, // 0x2C ',' + { 166, 12, 2, 14, 1, -7 }, // 0x2D '-' + { 169, 3, 3, 14, 5, -2 }, // 0x2E '.' + { 171, 10, 20, 14, 2, -16 }, // 0x2F '/' + { 196, 10, 15, 14, 2, -14 }, // 0x30 '0' + { 215, 10, 15, 14, 2, -14 }, // 0x31 '1' + { 234, 10, 15, 14, 2, -14 }, // 0x32 '2' + { 253, 11, 15, 14, 1, -14 }, // 0x33 '3' + { 274, 9, 14, 14, 2, -13 }, // 0x34 '4' + { 290, 10, 15, 14, 2, -14 }, // 0x35 '5' + { 309, 10, 15, 14, 2, -14 }, // 0x36 '6' + { 328, 10, 15, 14, 2, -14 }, // 0x37 '7' + { 347, 10, 15, 14, 2, -14 }, // 0x38 '8' + { 366, 10, 15, 14, 3, -14 }, // 0x39 '9' + { 385, 3, 11, 14, 5, -10 }, // 0x3A ':' + { 390, 4, 15, 14, 4, -10 }, // 0x3B ';' + { 398, 12, 11, 14, 1, -11 }, // 0x3C '<' + { 415, 12, 7, 14, 1, -9 }, // 0x3D '=' + { 426, 12, 11, 14, 1, -11 }, // 0x3E '>' + { 443, 9, 14, 14, 3, -13 }, // 0x3F '?' + { 459, 11, 19, 14, 2, -14 }, // 0x40 '@' + { 486, 15, 14, 14, -1, -13 }, // 0x41 'A' + { 513, 13, 14, 14, 0, -13 }, // 0x42 'B' + { 536, 12, 14, 14, 1, -13 }, // 0x43 'C' + { 557, 12, 14, 14, 1, -13 }, // 0x44 'D' + { 578, 13, 14, 14, 0, -13 }, // 0x45 'E' + { 601, 13, 14, 14, 0, -13 }, // 0x46 'F' + { 624, 13, 14, 14, 1, -13 }, // 0x47 'G' + { 647, 14, 14, 14, 0, -13 }, // 0x48 'H' + { 672, 10, 14, 14, 2, -13 }, // 0x49 'I' + { 690, 13, 14, 14, 1, -13 }, // 0x4A 'J' + { 713, 14, 14, 14, 0, -13 }, // 0x4B 'K' + { 738, 12, 14, 14, 1, -13 }, // 0x4C 'L' + { 759, 14, 14, 14, 0, -13 }, // 0x4D 'M' + { 784, 13, 14, 14, 0, -13 }, // 0x4E 'N' + { 807, 12, 14, 14, 1, -13 }, // 0x4F 'O' + { 828, 12, 14, 14, 0, -13 }, // 0x50 'P' + { 849, 12, 17, 14, 1, -13 }, // 0x51 'Q' + { 875, 14, 14, 14, 0, -13 }, // 0x52 'R' + { 900, 10, 14, 14, 2, -13 }, // 0x53 'S' + { 918, 12, 14, 14, 1, -13 }, // 0x54 'T' + { 939, 12, 14, 14, 1, -13 }, // 0x55 'U' + { 960, 16, 14, 14, -1, -13 }, // 0x56 'V' + { 988, 14, 14, 14, 0, -13 }, // 0x57 'W' + { 1013, 14, 14, 14, 0, -13 }, // 0x58 'X' + { 1038, 12, 14, 14, 1, -13 }, // 0x59 'Y' + { 1059, 10, 14, 14, 2, -13 }, // 0x5A 'Z' + { 1077, 5, 19, 14, 6, -14 }, // 0x5B '[' + { 1089, 10, 20, 14, 2, -16 }, // 0x5C '\' + { 1114, 5, 19, 14, 3, -14 }, // 0x5D ']' + { 1126, 10, 8, 14, 2, -15 }, // 0x5E '^' + { 1136, 14, 2, 14, 0, 4 }, // 0x5F '_' + { 1140, 4, 4, 14, 4, -15 }, // 0x60 '`' + { 1142, 12, 11, 14, 1, -10 }, // 0x61 'a' + { 1159, 13, 15, 14, 0, -14 }, // 0x62 'b' + { 1184, 12, 11, 14, 1, -10 }, // 0x63 'c' + { 1201, 13, 15, 14, 1, -14 }, // 0x64 'd' + { 1226, 12, 11, 14, 1, -10 }, // 0x65 'e' + { 1243, 11, 15, 14, 2, -14 }, // 0x66 'f' + { 1264, 13, 16, 14, 1, -10 }, // 0x67 'g' + { 1290, 14, 15, 14, 0, -14 }, // 0x68 'h' + { 1317, 11, 14, 14, 1, -13 }, // 0x69 'i' + { 1337, 8, 19, 15, 3, -13 }, // 0x6A 'j' + { 1356, 13, 15, 14, 1, -14 }, // 0x6B 'k' + { 1381, 11, 15, 14, 1, -14 }, // 0x6C 'l' + { 1402, 15, 11, 14, 0, -10 }, // 0x6D 'm' + { 1423, 14, 11, 14, 0, -10 }, // 0x6E 'n' + { 1443, 12, 11, 14, 1, -10 }, // 0x6F 'o' + { 1460, 14, 16, 14, 0, -10 }, // 0x70 'p' + { 1488, 14, 16, 14, 0, -10 }, // 0x71 'q' + { 1516, 12, 11, 14, 1, -10 }, // 0x72 'r' + { 1533, 10, 11, 14, 2, -10 }, // 0x73 's' + { 1547, 11, 14, 14, 1, -13 }, // 0x74 't' + { 1567, 13, 11, 14, 0, -10 }, // 0x75 'u' + { 1585, 14, 11, 14, 0, -10 }, // 0x76 'v' + { 1605, 14, 11, 14, 0, -10 }, // 0x77 'w' + { 1625, 14, 11, 14, 0, -10 }, // 0x78 'x' + { 1645, 12, 16, 14, 1, -10 }, // 0x79 'y' + { 1669, 11, 11, 14, 1, -10 }, // 0x7A 'z' + { 1685, 7, 19, 14, 3, -14 }, // 0x7B '{' + { 1702, 2, 19, 14, 6, -14 }, // 0x7C '|' + { 1707, 7, 19, 14, 4, -14 }, // 0x7D '}' + { 1724, 12, 4, 14, 1, -7 } }; // 0x7E '~' + +const GFXfont FreeMonoBold12pt7b = { + (uint8_t *)FreeMonoBold12pt7bBitmaps, + (GFXglyph *)FreeMonoBold12pt7bGlyphs, + 0x20, 0x7E, 24, 17 }; + +// Approx. 2402 bytes diff --git a/components/fb_gfx/component.mk b/components/fb_gfx/component.mk new file mode 100755 index 0000000..9cfcce5 --- /dev/null +++ b/components/fb_gfx/component.mk @@ -0,0 +1,2 @@ +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_SRCDIRS := . diff --git a/components/fb_gfx/fb_gfx.c b/components/fb_gfx/fb_gfx.c new file mode 100644 index 0000000..ab373c1 --- /dev/null +++ b/components/fb_gfx/fb_gfx.c @@ -0,0 +1,167 @@ +// 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 "stdint.h" +#include "stdarg.h" +#include "string.h" +#include "stdio.h" +#include "stdlib.h" +#include "fb_gfx.h" + +typedef struct { // Data stored PER GLYPH + uint16_t bitmapOffset; // Pointer into GFXfont->bitmap + uint8_t width, height; // Bitmap dimensions in pixels + uint8_t xAdvance; // Distance to advance cursor (x axis) + int8_t xOffset, yOffset; // Dist from cursor pos to UL corner +} GFXglyph; + +typedef struct { // Data stored for FONT AS A WHOLE: + uint8_t *bitmap; // Glyph bitmaps, concatenated + GFXglyph *glyph; // Glyph array + uint8_t first, last; // ASCII extents + uint8_t yAdvance; // Newline distance (y axis) + uint8_t yOffset; // Y offset of the font zero line (y axis) +} GFXfont; + +#include "FreeMonoBold12pt7b.h"//14x24 +#define gfxFont ((GFXfont*)(&FreeMonoBold12pt7b)) + +void fb_gfx_fillRect(fb_data_t *fb, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) +{ + int32_t line_step = (fb->width - w) * fb->bytes_per_pixel; + uint8_t *data = fb->data + ((x + (y * fb->width)) * fb->bytes_per_pixel); + uint8_t c0 = color >> 16; + uint8_t c1 = color >> 8; + uint8_t c2 = color; + for (int i=0; ibytes_per_pixel == 2){ + data[0] = c1; + data[1] = c2; + } else if(fb->bytes_per_pixel == 1){ + data[0] = c2; + } else { + data[0] = c0; + data[1] = c1; + data[2] = c2; + } + data+=fb->bytes_per_pixel; + } + data += line_step; + } +} + +void fb_gfx_drawFastHLine(fb_data_t *fb, int32_t x, int32_t y, int32_t w, uint32_t color) +{ + fb_gfx_fillRect(fb, x, y, w, 1, color); +} + +void fb_gfx_drawFastVLine(fb_data_t *fb, int32_t x, int32_t y, int32_t h, uint32_t color) +{ + fb_gfx_fillRect(fb, x, y, 1, h, color); +} + +uint8_t fb_gfx_putc(fb_data_t *fb, int32_t x, int32_t y, uint32_t color, unsigned char c) +{ + uint16_t line_width; + uint8_t xa = 0, bit = 0, bits = 0, xx, yy; + uint8_t *bitmap; + GFXglyph *glyph; + + if ((c < 32) || (c < gfxFont->first) || (c > gfxFont->last)) { + return xa; + } + + c -= gfxFont->first; + + glyph = &(gfxFont->glyph[c]); + bitmap = gfxFont->bitmap + glyph->bitmapOffset; + + xa = glyph->xAdvance; + x += glyph->xOffset; + y += glyph->yOffset; + y += gfxFont->yOffset; + line_width = 0; + + for(yy=0; yyheight; yy++) { + for(xx=0; xxwidth; xx++) { + if(bit == 0) { + bits = *bitmap++; + bit = 0x80; + } + if(bits & bit) { + line_width++; + } else if (line_width) { + fb_gfx_drawFastHLine(fb, x+xx-line_width, y+yy, line_width, color); + line_width=0; + } + bit >>= 1; + } + if (line_width) { + fb_gfx_drawFastHLine(fb, x+xx-line_width, y+yy, line_width, color); + line_width=0; + } + } + return xa; +} + +uint32_t fb_gfx_print(fb_data_t *fb, int32_t x, int32_t y, uint32_t color, const char * str) +{ + uint32_t l = 0; + int xc = x, yc = y, lc = fb->width - gfxFont->glyph[0].xAdvance; + uint8_t fh = gfxFont->yAdvance; + char c = *str++; + while(c){ + if(c != '\r'){ + if(c == '\n'){ + yc += fh; + xc = x; + } else { + if(xc > lc){ + yc += fh; + xc = x; + } + xc += fb_gfx_putc(fb, xc, yc, color, c); + } + } + l++; + c = *str++; + } + return l; +} + +uint32_t fb_gfx_printf(fb_data_t *fb, int32_t x, int32_t y, uint32_t color, const char *format, ...) +{ + char loc_buf[64]; + char * temp = loc_buf; + int len; + va_list arg; + va_list copy; + va_start(arg, format); + va_copy(copy, arg); + len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg); + va_end(copy); + if(len >= sizeof(loc_buf)){ + temp = (char*)malloc(len+1); + if(temp == NULL) { + return 0; + } + } + vsnprintf(temp, len+1, format, arg); + va_end(arg); + fb_gfx_print(fb, x, y, color, temp); + if(len > 64){ + free(temp); + } + return len; +} diff --git a/components/fb_gfx/include/fb_gfx.h b/components/fb_gfx/include/fb_gfx.h new file mode 100644 index 0000000..158c80f --- /dev/null +++ b/components/fb_gfx/include/fb_gfx.h @@ -0,0 +1,44 @@ +// 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 _FB_GFX_H_ +#define _FB_GFX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + typedef enum { + FB_RGB888, FB_BGR888, FB_RGB565, FB_BGR565, FB_GRAY + } fb_format_t; + + typedef struct { + int width; + int height; + int bytes_per_pixel; + fb_format_t format; + uint8_t * data; + } fb_data_t; + + void fb_gfx_fillRect (fb_data_t *fb, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); + void fb_gfx_drawFastHLine(fb_data_t *fb, int32_t x, int32_t y, int32_t w, uint32_t color); + void fb_gfx_drawFastVLine(fb_data_t *fb, int32_t x, int32_t y, int32_t h, uint32_t color); + uint8_t fb_gfx_putc (fb_data_t *fb, int32_t x, int32_t y, uint32_t color, unsigned char c); + uint32_t fb_gfx_print (fb_data_t *fb, int32_t x, int32_t y, uint32_t color, const char * str); + uint32_t fb_gfx_printf (fb_data_t *fb, int32_t x, int32_t y, uint32_t color, const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* _FB_GFX_H_ */ diff --git a/configs/builds.json b/configs/builds.json new file mode 100644 index 0000000..c32e465 --- /dev/null +++ b/configs/builds.json @@ -0,0 +1,120 @@ +{ + "mem_variants_files":[ + { + "file":"libspi_flash.a", + "src":"build/esp-idf/spi_flash/libspi_flash.a", + "out":"lib/libspi_flash.a", + "targets":["esp32","esp32c3","esp32s2","esp32s3"] + }, + { + "file":"libesp_system.a", + "src":"build/esp-idf/esp_system/libesp_system.a", + "out":"lib/libesp_system.a", + "targets":["esp32s3"] + }, + { + "file":"libfreertos.a", + "src":"build/esp-idf/freertos/libfreertos.a", + "out":"lib/libfreertos.a", + "targets":["esp32s3"] + }, + { + "file":"libbootloader_support.a", + "src":"build/esp-idf/bootloader_support/libbootloader_support.a", + "out":"lib/libbootloader_support.a", + "targets":["esp32s3"] + }, + { + "file":"libesp_hw_support.a", + "src":"build/esp-idf/esp_hw_support/libesp_hw_support.a", + "out":"lib/libesp_hw_support.a", + "targets":["esp32s3"] + }, + { + "file":"sections.ld", + "src":"build/esp-idf/esp_system/ld/sections.ld", + "out":"ld/sections.ld", + "targets":["esp32s3"] + } + ], + "targets":[ + { + "target": "esp32s3", + "features":[], + "idf_libs":["qio","80m","qio_ram"], + "bootloaders":[ + ["qio","120m","qio_ram"], + ["qio","80m","qio_ram"], + ["dio","80m","qio_ram"], + ["opi","80m","opi_ram"] + ], + "mem_variants":[ + ["qio","80m","opi_ram"], + ["dio","80m","qio_ram"], + ["dio","80m","opi_ram"], + ["opi","80m","opi_ram"], + ["opi","80m","qio_ram"] + ] + }, + { + "target": "esp32s2", + "features":["qio_ram"], + "idf_libs":["qio","80m"], + "bootloaders":[ + ["qio","80m"], + ["qout","80m"], + ["dio","80m"], + ["dout","80m"], + ["qio","40m"], + ["qout","40m"], + ["dio","40m"], + ["dout","40m"] + ], + "mem_variants":[ + ["qout","80m"], + ["dio","80m"], + ["dout","80m"] + ] + }, + { + "target": "esp32c3", + "features":[], + "idf_libs":["qio","80m"], + "bootloaders":[ + ["qio","80m"], + ["qout","80m"], + ["dio","80m"], + ["dout","80m"], + ["qio","40m"], + ["qout","40m"], + ["dio","40m"], + ["dout","40m"] + ], + "mem_variants":[ + ["qout","80m"], + ["dio","80m"], + ["dout","80m"] + ] + }, + { + "target": "esp32", + "features":["qio_ram"], + "idf_libs":["qio","80m"], + "bootloaders":[ + ["qio","80m"], + ["qout","80m"], + ["dio","80m"], + ["dout","80m"], + ["qio","40m"], + ["qout","40m"], + ["dio","40m"], + ["dout","40m"] + ], + "mem_variants":[ + ["qout","80m"], + ["dio","80m"], + ["dout","80m"] + ] + } + ] +} \ No newline at end of file diff --git a/configs/defconfig.120m b/configs/defconfig.120m new file mode 100644 index 0000000..a21a828 --- /dev/null +++ b/configs/defconfig.120m @@ -0,0 +1,2 @@ +CONFIG_ESPTOOLPY_FLASHFREQ_120M=y +CONFIG_SPIRAM_SPEED_120M=y \ No newline at end of file diff --git a/configs/defconfig.40m b/configs/defconfig.40m new file mode 100644 index 0000000..079a033 --- /dev/null +++ b/configs/defconfig.40m @@ -0,0 +1,2 @@ +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_SPIRAM_SPEED_40M=y \ No newline at end of file diff --git a/configs/defconfig.80m b/configs/defconfig.80m new file mode 100644 index 0000000..38980b0 --- /dev/null +++ b/configs/defconfig.80m @@ -0,0 +1,2 @@ +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_SPIRAM_SPEED_80M=y \ No newline at end of file diff --git a/configs/defconfig.common b/configs/defconfig.common new file mode 100644 index 0000000..910ca8d --- /dev/null +++ b/configs/defconfig.common @@ -0,0 +1,73 @@ +CONFIG_AUTOSTART_ARDUINO=y +# CONFIG_WS2812_LED_ENABLE is not set +CONFIG_ARDUHAL_ESP_LOG=y +CONFIG_BOOTLOADER_LOG_LEVEL_NONE=y +CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y +CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y +CONFIG_BT_ENABLED=y +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BLE_MESH=y +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_STACK_CHECK_MODE_NORM=y +CONFIG_COMPILER_WARN_WRITE_STRINGS=y +CONFIG_ESP_HTTPS_SERVER_ENABLE=y +CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048 +CONFIG_ESP_TASK_WDT_PANIC=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=4096 +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESP_WIFI_FTM_ENABLE=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=8 +CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_CSI_ENABLED=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +# CONFIG_ESP32_WIFI_IRAM_OPT is not set +# CONFIG_ESP32_WIFI_RX_IRAM_OPT is not set +CONFIG_ETH_SPI_ETHERNET_DM9051=y +CONFIG_ETH_SPI_ETHERNET_W5500=y +CONFIG_FATFS_CODEPAGE_850=y +CONFIG_FATFS_LFN_STACK=y +# CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_FMB_TIMER_PORT_ENABLED=y +CONFIG_FREERTOS_HZ=1000 +# CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION is not set +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_HEAP_POISONING_LIGHT=y +CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 +CONFIG_HTTPD_WS_SUPPORT=y +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y +# CONFIG_LOG_COLORS is not set +CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +CONFIG_LWIP_TCP_SYNMAXRTX=6 +CONFIG_LWIP_TCP_MSS=1436 +CONFIG_LWIP_TCP_RTO_TIME=3000 +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2560 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0=y +CONFIG_LWIP_MAX_SOCKETS=16 +CONFIG_LWIP_DHCP_RESTORE_LAST_IP=y +CONFIG_LWIP_DHCP_OPTIONS_LEN=128 +CONFIG_LWIP_SNTP_MAX_SERVERS=3 +CONFIG_LWIP_SNTP_UPDATE_DELAY=10800000 +CONFIG_LWIP_DHCP_GET_NTP_SRV=y +CONFIG_MBEDTLS_PSK_MODES=y +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_MBEDTLS_CAMELLIA_C=y +# CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN is not set +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048 +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=10 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=2 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=4096 +# CONFIG_SPI_MASTER_ISR_IN_IRAM is not set +# CONFIG_SPI_SLAVE_ISR_IN_IRAM is not set +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=0 +CONFIG_LWIP_IPV6_AUTOCONFIG=y diff --git a/configs/defconfig.dio b/configs/defconfig.dio new file mode 100644 index 0000000..17c6c1f --- /dev/null +++ b/configs/defconfig.dio @@ -0,0 +1 @@ +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y \ No newline at end of file diff --git a/configs/defconfig.dout b/configs/defconfig.dout new file mode 100644 index 0000000..48d652c --- /dev/null +++ b/configs/defconfig.dout @@ -0,0 +1 @@ +CONFIG_ESPTOOLPY_FLASHMODE_DOUT=y \ No newline at end of file diff --git a/configs/defconfig.esp32 b/configs/defconfig.esp32 new file mode 100644 index 0000000..122a80b --- /dev/null +++ b/configs/defconfig.esp32 @@ -0,0 +1,17 @@ +CONFIG_BTDM_CTRL_MODE_BTDM=y +CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE=20 +CONFIG_BT_BTC_TASK_STACK_SIZE=8192 +CONFIG_BT_BTU_TASK_STACK_SIZE=8192 +CONFIG_BT_CLASSIC_ENABLED=y +CONFIG_BT_A2DP_ENABLE=y +CONFIG_BT_SPP_ENABLED=y +CONFIG_BT_HFP_ENABLE=y +CONFIG_BT_STACK_NO_LOG=y +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y +CONFIG_ESP32_SPIRAM_SUPPORT=y +CONFIG_ESP32_ULP_COPROC_ENABLED=y +CONFIG_ESP32_XTAL_FREQ_AUTO=y +# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set +CONFIG_FREERTOS_FPU_IN_ISR=y +# CONFIG_USE_WAKENET is not set +# CONFIG_USE_MULTINET is not set \ No newline at end of file diff --git a/configs/defconfig.esp32c3 b/configs/defconfig.esp32c3 new file mode 100644 index 0000000..31c42f7 --- /dev/null +++ b/configs/defconfig.esp32c3 @@ -0,0 +1,4 @@ +CONFIG_BT_BLE_BLUFI_ENABLE=y +CONFIG_ESP32C3_RTC_CLK_CAL_CYCLES=576 +# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 is not set +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=2304 diff --git a/configs/defconfig.esp32s2 b/configs/defconfig.esp32s2 new file mode 100644 index 0000000..38db2c3 --- /dev/null +++ b/configs/defconfig.esp32s2 @@ -0,0 +1,7 @@ +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S2_SPIRAM_SUPPORT=y +CONFIG_ESP32S2_KEEP_USB_ALIVE=y +# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 is not set +# CONFIG_USE_WAKENET is not set +# CONFIG_USE_MULTINET is not set \ No newline at end of file diff --git a/configs/defconfig.esp32s3 b/configs/defconfig.esp32s3 new file mode 100644 index 0000000..e0b30c9 --- /dev/null +++ b/configs/defconfig.esp32s3 @@ -0,0 +1,11 @@ +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=576 +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO=y +# CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND is not set +# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set +CONFIG_SR_WN_MODEL_WN8_QUANT=y +CONFIG_SR_WN_WN8_HIESP=y +CONFIG_SR_MN_ENGLISH=y +CONFIG_SR_MN_EN_MULTINET5_SINGLE_RECOGNITION_QUANT8=y \ No newline at end of file diff --git a/configs/defconfig.opi b/configs/defconfig.opi new file mode 100644 index 0000000..7cfbc5c --- /dev/null +++ b/configs/defconfig.opi @@ -0,0 +1,2 @@ +CONFIG_ESPTOOLPY_OCT_FLASH=y +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR=y \ No newline at end of file diff --git a/configs/defconfig.opi_ram b/configs/defconfig.opi_ram new file mode 100644 index 0000000..16e6a27 --- /dev/null +++ b/configs/defconfig.opi_ram @@ -0,0 +1,3 @@ +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +# CONFIG_SPIRAM_MEMTEST is not set \ No newline at end of file diff --git a/configs/defconfig.qio b/configs/defconfig.qio new file mode 100644 index 0000000..b467882 --- /dev/null +++ b/configs/defconfig.qio @@ -0,0 +1 @@ +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y \ No newline at end of file diff --git a/configs/defconfig.qio_ram b/configs/defconfig.qio_ram new file mode 100644 index 0000000..902680b --- /dev/null +++ b/configs/defconfig.qio_ram @@ -0,0 +1 @@ +# CONFIG_SPIRAM_BOOT_INIT is not set \ No newline at end of file diff --git a/configs/defconfig.qout b/configs/defconfig.qout new file mode 100644 index 0000000..154cabf --- /dev/null +++ b/configs/defconfig.qout @@ -0,0 +1 @@ +CONFIG_ESPTOOLPY_FLASHMODE_QOUT=y \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt new file mode 100644 index 0000000..1ab83d3 --- /dev/null +++ b/main/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "sketch.cpp" "arduino-lib-builder-gcc.c" "arduino-lib-builder-cpp.cpp" "arduino-lib-builder-as.S" INCLUDE_DIRS ".") diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild new file mode 100644 index 0000000..d30fccc --- /dev/null +++ b/main/Kconfig.projbuild @@ -0,0 +1,15 @@ +config LIB_BUILDER_FLASHMODE + string + default "qio" if ESPTOOLPY_FLASHMODE_QIO + default "qout" if ESPTOOLPY_FLASHMODE_QOUT + default "dio" if ESPTOOLPY_FLASHMODE_DIO + default "dout" if ESPTOOLPY_FLASHMODE_DOUT + default "opi" if ESPTOOLPY_FLASHMODE_OPI + +config LIB_BUILDER_FLASHFREQ + string + default "120m" if ESPTOOLPY_FLASHFREQ_120M + default "80m" if ESPTOOLPY_FLASHFREQ_80M + default "40m" if ESPTOOLPY_FLASHFREQ_40M + default "26m" if ESPTOOLPY_FLASHFREQ_26M + default "20m" if ESPTOOLPY_FLASHFREQ_20M diff --git a/main/arduino-lib-builder-as.S b/main/arduino-lib-builder-as.S new file mode 100644 index 0000000..e69de29 diff --git a/main/arduino-lib-builder-cpp.cpp b/main/arduino-lib-builder-cpp.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/arduino-lib-builder-gcc.c b/main/arduino-lib-builder-gcc.c new file mode 100644 index 0000000..e69de29 diff --git a/main/component.mk b/main/component.mk new file mode 100644 index 0000000..08c3b49 --- /dev/null +++ b/main/component.mk @@ -0,0 +1 @@ +CXXFLAGS += -fno-rtti diff --git a/main/sketch.cpp b/main/sketch.cpp new file mode 100644 index 0000000..10a17a8 --- /dev/null +++ b/main/sketch.cpp @@ -0,0 +1,10 @@ +#include "Arduino.h" + +void setup() { + Serial.begin(115200); +} + +void loop() { + Serial.println("Hello World!"); + delay(1000); +} diff --git a/tools/archive-build.sh b/tools/archive-build.sh new file mode 100755 index 0000000..d6682ff --- /dev/null +++ b/tools/archive-build.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +IDF_COMMIT=$(git -C "$IDF_PATH" rev-parse --short HEAD) +IDF_BRANCH=$(git -C "$IDF_PATH" symbolic-ref --short HEAD) + +idf_version_string=${IDF_BRANCH//\//_}"-$IDF_COMMIT" +archive_path="dist/arduino-esp32-libs-$idf_version_string.tar.gz" +build_archive_path="dist/arduino-esp32-build-$idf_version_string.tar.gz" + +mkdir -p dist && rm -rf "$archive_path" "$build_archive_path" +if [ -d "out" ]; then + cd out && tar zcf "../$archive_path" * && cd .. +fi +if [ -d "build" ]; then + cd build && tar zcf "../$build_archive_path" * && cd .. +fi diff --git a/tools/config.sh b/tools/config.sh new file mode 100755 index 0000000..a403109 --- /dev/null +++ b/tools/config.sh @@ -0,0 +1,118 @@ +#!/bin/bash + + +if [ -z $IDF_PATH ]; then + export IDF_PATH="$PWD/esp-idf" +fi + +if [ -z $IDF_BRANCH ]; then + IDF_BRANCH="release/v4.4" +fi + +if [ -z $AR_PR_TARGET_BRANCH ]; then + AR_PR_TARGET_BRANCH="master" +fi + +if [ -z $IDF_TARGET ]; then + if [ -f sdkconfig ]; then + IDF_TARGET=`cat sdkconfig | grep CONFIG_IDF_TARGET= | cut -d'"' -f2` + if [ "$IDF_TARGET" = "" ]; then + IDF_TARGET="esp32" + fi + else + IDF_TARGET="esp32" + fi +fi + +IDF_COMPS="$IDF_PATH/components" +IDF_TOOLCHAIN="xtensa-$IDF_TARGET-elf" + +# Owner of the target ESP32 Arduino repository +AR_USER="espressif" + +# The full name of the repository +AR_REPO="$AR_USER/arduino-esp32" + +AR_REPO_URL="https://github.com/$AR_REPO.git" +if [ -n $GITHUB_TOKEN ]; then + AR_REPO_URL="https://$GITHUB_TOKEN@github.com/$AR_REPO.git" +fi + +AR_ROOT="$PWD" +AR_COMPS="$AR_ROOT/components" +AR_OUT="$AR_ROOT/out" +AR_TOOLS="$AR_OUT/tools" +AR_PLATFORM_TXT="$AR_OUT/platform.txt" +AR_ESPTOOL_PY="$AR_TOOLS/esptool.py" +AR_GEN_PART_PY="$AR_TOOLS/gen_esp32part.py" +AR_SDK="$AR_TOOLS/sdk/$IDF_TARGET" + +function get_os(){ + OSBITS=`arch` + if [[ "$OSTYPE" == "linux"* ]]; then + if [[ "$OSBITS" == "i686" ]]; then + echo "linux32" + elif [[ "$OSBITS" == "x86_64" ]]; then + echo "linux64" + elif [[ "$OSBITS" == "armv7l" ]]; then + echo "linux-armel" + else + echo "unknown" + return 1 + fi + elif [[ "$OSTYPE" == "darwin"* ]]; then + echo "macos" + elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then + echo "win32" + else + echo "$OSTYPE" + return 1 + fi + return 0 +} + +AR_OS=`get_os` + +export SED="sed" +export SSTAT="stat -c %s" + +if [[ "$AR_OS" == "macos" ]]; then + export SED="gsed" + export SSTAT="stat -f %z" +fi + +function git_commit_exists(){ #git_commit_exists + local repo_path="$1" + local commit_message="$2" + local commits_found=`git -C "$repo_path" log --all --grep="$commit_message" | grep commit` + if [ -n "$commits_found" ]; then echo 1; else echo 0; fi +} + +function git_branch_exists(){ # git_branch_exists + local repo_path="$1" + local branch_name="$2" + local branch_found=`git -C "$repo_path" ls-remote --heads origin "$branch_name"` + if [ -n "$branch_found" ]; then echo 1; else echo 0; fi +} + +function git_pr_exists(){ # git_pr_exists + local pr_num=`curl -s -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" "https://api.github.com/repos/$AR_REPO/pulls?head=$AR_USER:$1&state=open" | jq -r '.[].number'` + if [ ! "$pr_num" == "" ] && [ ! "$pr_num" == "null" ]; then echo 1; else echo 0; fi +} + +function git_create_pr(){ # git_create_pr + local pr_branch="$1" + local pr_title="$2" + local pr_target="$3" + local pr_body="" + for component in `ls "$AR_COMPS"`; do + if [ ! $component == "arduino" ] && [ -d "$AR_COMPS/$component/.git" ]; then + pr_body+="$component: "$(git -C "$AR_COMPS/$component" symbolic-ref --short HEAD)" "$(git -C "$AR_COMPS/$component" rev-parse --short HEAD)"\r\n" + fi + done + local pr_data="{\"title\": \"$pr_title\", \"body\": \"$pr_body\", \"head\": \"$AR_USER:$pr_branch\", \"base\": \"$pr_target\"}" + git_create_pr_res=`echo "$pr_data" | curl -k -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3.raw+json" --data @- "https://api.github.com/repos/$AR_REPO/pulls"` + local done_pr=`echo "$git_create_pr_res" | jq -r '.title'` + if [ ! "$done_pr" == "" ] && [ ! "$done_pr" == "null" ]; then echo 1; else echo 0; fi +} + diff --git a/tools/copy-bootloader.sh b/tools/copy-bootloader.sh new file mode 100755 index 0000000..53b10b3 --- /dev/null +++ b/tools/copy-bootloader.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +IDF_TARGET=$1 +FLASH_MODE="$2" +FLASH_FREQ="$3" +BOOTCONF=$FLASH_MODE"_$FLASH_FREQ" + +source ./tools/config.sh + +echo "Copying bootloader: $AR_SDK/bin/bootloader_$BOOTCONF.bin" + +mkdir -p "$AR_SDK/bin" + +# Workaround for getting the bootloaders to be flashable with esptool v4.x +# It might still be needed for IDF5, but using the included esptool instead +#cp "build/bootloader/bootloader.bin" "$AR_SDK/bin/bootloader_$BOOTCONF.bin" +if [ ! -e "tools/esptool" ]; then + git clone https://github.com/espressif/esptool tools/esptool +fi +./tools/esptool/esptool.py --chip "$IDF_TARGET" elf2image --dont-append-digest "build/bootloader/bootloader.elf" -o "$AR_SDK/bin/bootloader_$BOOTCONF.bin" diff --git a/tools/copy-libs.sh b/tools/copy-libs.sh new file mode 100755 index 0000000..681fa68 --- /dev/null +++ b/tools/copy-libs.sh @@ -0,0 +1,529 @@ +#!/bin/bash +# config + +IDF_TARGET=$1 +IS_XTENSA=$4 +OCT_FLASH="$2" +OCT_PSRAM= + +if [ "$3" = "y" ]; then + OCT_PSRAM="opi" +else + OCT_PSRAM="qspi" +fi +MEMCONF=$OCT_FLASH"_$OCT_PSRAM" + +source ./tools/config.sh + +echo "IDF_TARGET: $IDF_TARGET, MEMCONF: $MEMCONF, PWD: $PWD, OUT: $AR_SDK" + +# clean previous +if [ -e "$AR_SDK/sdkconfig" ]; then + rm -rf "$AR_SDK/sdkconfig" +fi +if [ -e "$AR_SDK/lib" ]; then + rm -rf "$AR_SDK/lib" +fi +if [ -e "$AR_SDK/ld" ]; then + rm -rf "$AR_SDK/ld" +fi +if [ -e "$AR_SDK/include" ]; then + rm -rf "$AR_SDK/include" +fi +if [ -e "$AR_SDK/$MEMCONF" ]; then + rm -rf "$AR_SDK/$MEMCONF" +fi +mkdir -p "$AR_SDK" + +function get_actual_path(){ + p="$PWD"; cd "$1"; r="$PWD"; cd "$p"; echo "$r"; +} + +# +# START OF DATA EXTRACTION FROM CMAKE +# + +C_FLAGS="" +CPP_FLAGS="" +AS_FLAGS="" + +INCLUDES="" +DEFINES="" + +LD_FLAGS="" +LD_LIBS="" +LD_LIB_FILES="" +LD_LIBS_SEARCH="" +LD_SCRIPTS="" +LD_SCRIPT_DIRS="" + +PIO_CC_FLAGS="" +PIO_C_FLAGS="" +PIO_CXX_FLAGS="" +PIO_AS_FLAGS="" +PIO_LD_FLAGS="" +PIO_LD_FUNCS="" +PIO_LD_SCRIPTS="" + +#collect includes, defines and c-flags +str=`cat build/compile_commands.json | grep arduino-lib-builder-gcc.c | grep command | cut -d':' -f2 | cut -d',' -f1` +str="${str:2:${#str}-1}" #remove leading space and quotes +str=`printf '%b' "$str"` #unescape the string +set -- $str +for item in "${@:2:${#@}-5}"; do + prefix="${item:0:2}" + if [ "$prefix" = "-I" ]; then + item="${item:2}" + if [ "${item:0:1}" = "/" ]; then + item=`get_actual_path $item` + INCLUDES+="$item " + elif [ "${item:0:2}" = ".." ]; then + if [[ "${item:0:14}" = "../components/" && "${item:0:22}" != "../components/arduino/" ]] || [[ "${item:0:11}" = "../esp-idf/" ]]; then + item="$PWD${item:2}" + item=`get_actual_path $item` + INCLUDES+="$item " + fi + else + item="$PWD/build/$item" + item=`get_actual_path $item` + INCLUDES+="$item " + fi + elif [ "$prefix" = "-D" ]; then + if [[ "${item:2:7}" != "ARDUINO" ]] && [[ "$item" != "-DESP32" ]]; then #skip ARDUINO defines + DEFINES+="$item " + fi + elif [[ "$item" != "-Wall" && "$item" != "-Werror=all" && "$item" != "-Wextra" ]]; then + if [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" ]]; then + C_FLAGS+="$item " + fi + fi +done + +#collect asm-flags +str=`cat build/compile_commands.json | grep arduino-lib-builder-as.S | grep command | cut -d':' -f2 | cut -d',' -f1` +str="${str:2:${#str}-1}" #remove leading space and quotes +str=`printf '%b' "$str"` #unescape the string +set -- $str +for item in "${@:2:${#@}-5}"; do + prefix="${item:0:2}" + if [[ "$prefix" != "-I" && "$prefix" != "-D" && "$item" != "-Wall" && "$item" != "-Werror=all" && "$item" != "-Wextra" ]]; then + if [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" ]]; then + AS_FLAGS+="$item " + if [[ $C_FLAGS == *"$item"* ]]; then + PIO_CC_FLAGS+="$item " + else + PIO_AS_FLAGS+="$item " + fi + fi + fi +done + +#collect cpp-flags +str=`cat build/compile_commands.json | grep arduino-lib-builder-cpp.cpp | grep command | cut -d':' -f2 | cut -d',' -f1` +str="${str:2:${#str}-1}" #remove leading space and quotes +str=`printf '%b' "$str"` #unescape the string +set -- $str +for item in "${@:2:${#@}-5}"; do + prefix="${item:0:2}" + if [[ "$prefix" != "-I" && "$prefix" != "-D" && "$item" != "-Wall" && "$item" != "-Werror=all" && "$item" != "-Wextra" ]]; then + if [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" ]]; then + CPP_FLAGS+="$item " + if [[ $PIO_CC_FLAGS != *"$item"* ]]; then + PIO_CXX_FLAGS+="$item " + fi + fi + fi +done + +set -- $C_FLAGS +for item; do + if [[ $PIO_CC_FLAGS != *"$item"* ]]; then + PIO_C_FLAGS+="$item " + fi +done + +#parse link command to extract libs and flags +add_next=0 +is_dir=0 +is_script=0 +if [ -f "build/CMakeFiles/arduino-lib-builder.elf.dir/link.txt" ]; then + str=`cat build/CMakeFiles/arduino-lib-builder.elf.dir/link.txt` +else + libs=`cat build/build.ninja | grep LINK_LIBRARIES` + libs="${libs:19:${#libs}-1}" + flags=`cat build/build.ninja | grep LINK_FLAGS` + flags="${flags:15:${#flags}-1}" + if [ "$IDF_TARGET" = "esp32" ]; then + flags="-Wno-frame-address $flags" + fi + if [ "$IDF_TARGET" != "esp32c3" ]; then + flags="-mlongcalls $flags" + fi + str="$flags $libs" +fi +if [ "$IDF_TARGET" = "esp32" ]; then + LD_SCRIPTS+="-T esp32.rom.redefined.ld " + PIO_LD_SCRIPTS+="esp32.rom.redefined.ld " +fi +set -- $str +for item; do + prefix="${item:0:1}" + if [ "$prefix" = "-" ]; then + if [ "${item:0:10}" != "-Wl,--Map=" ]; then + if [ "$item" = "-L" ]; then # -L /path + add_next=1 + is_dir=1 + elif [ "${item:0:2}" = "-L" ]; then # -L/path + LD_SCRIPT_DIRS+="${item:2} " + elif [ "$item" = "-T" ]; then # -T script.ld + add_next=1 + is_script=1 + LD_SCRIPTS+="$item " + elif [ "$item" = "-u" ]; then # -u function_name + add_next=1 + LD_FLAGS+="$item " + elif [ "${item:0:2}" = "-l" ]; then # -l[lib_name] + LD_LIBS+="$item " + exclude_libs=";m;c;gcc;stdc++;" + short_name="${item:2}" + if [[ $exclude_libs != *";$short_name;"* && $LD_LIBS_SEARCH != *"lib$short_name.a"* ]]; then + LD_LIBS_SEARCH+="lib$short_name.a " + #echo "lib add: $item" + fi + elif [ "$item" = "-o" ]; then + add_next=0 + is_script=0 + is_dir=0 + elif [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" && "${item:0:17}" != "-Wl,--start-group" && "${item:0:15}" != "-Wl,--end-group" ]]; then + LD_FLAGS+="$item " + PIO_LD_FLAGS+="$item " + fi + fi + else + if [ "$add_next" = "1" ]; then + add_next=0 + if [ "$is_dir" = "1" ]; then + is_dir=0 + LD_SCRIPT_DIRS+="$item " + elif [ "$is_script" = "1" ]; then + is_script=0 + LD_SCRIPTS+="$item " + PIO_LD_SCRIPTS+="$item " + else + LD_FLAGS+="$item " + PIO_LD_FUNCS+="$item " + fi + else + if [ "${item:${#item}-2:2}" = ".a" ]; then + if [ "${item:0:1}" != "/" ]; then + item="$PWD/build/$item" + fi + lname=$(basename $item) + lname="${lname:3:${#lname}-5}" + if [[ "$lname" != "main" && "$lname" != "arduino" ]]; then + lsize=$($SSTAT "$item") + if (( lsize > 8 )); then + # do we already have this file? + if [[ $LD_LIB_FILES != *"$item"* ]]; then + # do we already have lib with the same name? + if [[ $LD_LIBS != *"-l$lname"* ]]; then + # echo "collecting lib '$lname' and file: $item" + LD_LIB_FILES+="$item " + LD_LIBS+="-l$lname " + else + # echo "!!! need to rename: '$lname'" + for i in {2..9}; do + n_item="${item:0:${#item}-2}_$i.a" + n_name=$lname"_$i" + if [ -f "$n_item" ]; then + # echo "renamed add: -l$n_name" + LD_LIBS+="-l$n_name " + break + elif [[ $LD_LIB_FILES != *"$n_item"* && $LD_LIBS != *"-l$n_name"* ]]; then + echo "Renaming '$lname' to '$n_name': $item" + cp -f "$item" "$n_item" + LD_LIB_FILES+="$n_item " + LD_LIBS+="-l$n_name " + break + fi + done + fi + else + # echo "just add: -l$lname" + LD_LIBS+="-l$lname " + fi + else + echo "*** Skipping $(basename $item): size too small $lsize" + fi + fi + elif [[ "${item:${#item}-4:4}" = ".obj" || "${item:${#item}-4:4}" = ".elf" || "${item:${#item}-4:4}" = "-g++" ]]; then + item="$item" + else + echo "*** BAD LD ITEM: $item ${item:${#item}-2:2}" + fi + fi + fi +done + +# +# END OF DATA EXTRACTION FROM CMAKE +# + +AR_PLATFORMIO_PY="$AR_TOOLS/platformio-build-$IDF_TARGET.py" + +# start generation of platformio-build.py +awk "/ASFLAGS=\[/{n++}{print>n\"pio_start.txt\"}" $AR_COMPS/arduino/tools/platformio-build-$IDF_TARGET.py +awk "/\"ARDUINO_ARCH_ESP32\"/{n++}{print>n\"pio_end.txt\"}" 1pio_start.txt +cat pio_start.txt > "$AR_PLATFORMIO_PY" +rm pio_end.txt 1pio_start.txt pio_start.txt + +echo " ASFLAGS=[" >> "$AR_PLATFORMIO_PY" +if [ "$IS_XTENSA" = "y" ]; then + echo " \"-mlongcalls\"" >> "$AR_PLATFORMIO_PY" +else + echo " \"-march=rv32imc\"" >> "$AR_PLATFORMIO_PY" +fi +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +echo " ASPPFLAGS=[" >> "$AR_PLATFORMIO_PY" +set -- $PIO_AS_FLAGS +for item; do + echo " \"$item\"," >> "$AR_PLATFORMIO_PY" +done +echo " \"-x\", \"assembler-with-cpp\"" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +echo " CFLAGS=[" >> "$AR_PLATFORMIO_PY" +set -- $PIO_C_FLAGS +last_item="${@: -1}" +for item in "${@:0:${#@}}"; do + if [ "${item:0:1}" != "/" ]; then + echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + fi +done +echo " \"$last_item\"" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +echo " CXXFLAGS=[" >> "$AR_PLATFORMIO_PY" +set -- $PIO_CXX_FLAGS +last_item="${@: -1}" +for item in "${@:0:${#@}}"; do + if [ "${item:0:1}" != "/" ]; then + echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + fi +done +echo " \"$last_item\"" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +echo " CCFLAGS=[" >> "$AR_PLATFORMIO_PY" +set -- $PIO_CC_FLAGS +for item; do + echo " \"$item\"," >> "$AR_PLATFORMIO_PY" +done +echo " \"-MMD\"" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +echo " LINKFLAGS=[" >> "$AR_PLATFORMIO_PY" +set -- $PIO_LD_FLAGS +for item; do + echo " \"$item\"," >> "$AR_PLATFORMIO_PY" +done +set -- $PIO_LD_SCRIPTS +for item; do + echo " \"-T\", \"$item\"," >> "$AR_PLATFORMIO_PY" +done +set -- $PIO_LD_FUNCS +for item; do + echo " \"-u\", \"$item\"," >> "$AR_PLATFORMIO_PY" +done +echo " '-Wl,-Map=\"%s\"' % join(\"\${BUILD_DIR}\", \"\${PROGNAME}.map\")" >> "$AR_PLATFORMIO_PY" + +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +# # include dirs +AR_INC="" +echo " CPPPATH=[" >> "$AR_PLATFORMIO_PY" + +set -- $INCLUDES + +for item; do + if [[ "$item" != $PWD ]]; then + ipath="$item" + fname=`basename "$ipath"` + dname=`basename $(dirname "$ipath")` + if [[ "$fname" == "main" && "$dname" == "esp32-arduino-lib-builder" ]]; then + continue + fi + while [[ "$dname" != "components" && "$dname" != "build" ]]; do + ipath=`dirname "$ipath"` + fname=`basename "$ipath"` + dname=`basename $(dirname "$ipath")` + done + if [[ "$fname" == "arduino" ]]; then + continue + fi + if [[ "$fname" == "config" ]]; then + continue + fi + + out_sub="${item#*$ipath}" + out_cpath="$AR_SDK/include/$fname$out_sub" + AR_INC+=" \"-I{compiler.sdk.path}/include/$fname$out_sub\"" + if [ "$out_sub" = "" ]; then + echo " join(FRAMEWORK_DIR, \"tools\", \"sdk\", \"$IDF_TARGET\", \"include\", \"$fname\")," >> "$AR_PLATFORMIO_PY" + else + pio_sub="${out_sub:1}" + pio_sub=`echo $pio_sub | sed 's/\//\\", \\"/g'` + echo " join(FRAMEWORK_DIR, \"tools\", \"sdk\", \"$IDF_TARGET\", \"include\", \"$fname\", \"$pio_sub\")," >> "$AR_PLATFORMIO_PY" + fi + for f in `find "$item" -name '*.h'`; do + rel_f=${f#*$item} + rel_p=${rel_f%/*} + mkdir -p "$out_cpath$rel_p" + cp -n $f "$out_cpath$rel_p/" + done + for f in `find "$item" -name '*.hpp'`; do + rel_f=${f#*$item} + rel_p=${rel_f%/*} + mkdir -p "$out_cpath$rel_p" + cp -n $f "$out_cpath$rel_p/" + done + fi +done +echo " join(FRAMEWORK_DIR, \"tools\", \"sdk\", \"$IDF_TARGET\", env.BoardConfig().get(\"build.arduino.memory_type\", \"$MEMCONF\"), \"include\")," >> "$AR_PLATFORMIO_PY" +echo " join(FRAMEWORK_DIR, \"cores\", env.BoardConfig().get(\"build.core\"))" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +mkdir -p "$AR_SDK/lib" + +AR_LIBS="$LD_LIBS" +PIO_LIBS="" +set -- $LD_LIBS +for item; do + if [ "$PIO_LIBS" != "" ]; then + PIO_LIBS+=", " + fi + PIO_LIBS+="\"$item\"" +done + +set -- $LD_LIB_FILES +for item; do + cp "$item" "$AR_SDK/lib/" +done + +echo " LIBPATH=[" >> "$AR_PLATFORMIO_PY" +echo " join(FRAMEWORK_DIR, \"tools\", \"sdk\", \"$IDF_TARGET\", \"lib\")," >> "$AR_PLATFORMIO_PY" +echo " join(FRAMEWORK_DIR, \"tools\", \"sdk\", \"$IDF_TARGET\", \"ld\")," >> "$AR_PLATFORMIO_PY" +echo " join(FRAMEWORK_DIR, \"tools\", \"sdk\", \"$IDF_TARGET\", env.BoardConfig().get(\"build.arduino.memory_type\", \"$MEMCONF\"))" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +echo " LIBS=[" >> "$AR_PLATFORMIO_PY" +echo " $PIO_LIBS" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PLATFORMIO_PY" +echo "" >> "$AR_PLATFORMIO_PY" + +echo " CPPDEFINES=[" >> "$AR_PLATFORMIO_PY" +set -- $DEFINES +for item; do + item="${item:2}" #remove -D + if [[ $item == *"="* ]]; then + item=(${item//=/ }) + re='^[+-]?[0-9]+([.][0-9]+)?$' + if [[ ${item[1]} =~ $re ]]; then + echo " (\"${item[0]}\", ${item[1]})," >> "$AR_PLATFORMIO_PY" + else + echo " (\"${item[0]}\", '${item[1]}')," >> "$AR_PLATFORMIO_PY" + fi + else + echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + fi +done + +# remove backslashes for Arduino +DEFINES=`echo "$DEFINES" | tr -d '\\'` + + +# end generation of platformio-build.py +cat 1pio_end.txt >> "$AR_PLATFORMIO_PY" +rm 1pio_end.txt + +# arduino platform.txt +platform_file="$AR_COMPS/arduino/platform.txt" +if [ -f "$AR_PLATFORM_TXT" ]; then + # use the file we have already compiled for other chips + platform_file="$AR_PLATFORM_TXT" +fi +awk "/compiler.cpreprocessor.flags.$IDF_TARGET=/{n++}{print>n\"platform_start.txt\"}" "$platform_file" +$SED -i "/compiler.cpreprocessor.flags.$IDF_TARGET\=/d" 1platform_start.txt +awk "/compiler.ar.flags.$IDF_TARGET=/{n++}{print>n\"platform_mid.txt\"}" 1platform_start.txt +rm -rf 1platform_start.txt + +cat platform_start.txt > "$AR_PLATFORM_TXT" +echo "compiler.cpreprocessor.flags.$IDF_TARGET=$DEFINES $AR_INC" >> "$AR_PLATFORM_TXT" +echo "compiler.c.elf.libs.$IDF_TARGET=$AR_LIBS" >> "$AR_PLATFORM_TXT" +echo "compiler.c.flags.$IDF_TARGET=$C_FLAGS -MMD -c" >> "$AR_PLATFORM_TXT" +echo "compiler.cpp.flags.$IDF_TARGET=$CPP_FLAGS -MMD -c" >> "$AR_PLATFORM_TXT" +echo "compiler.S.flags.$IDF_TARGET=$AS_FLAGS -x assembler-with-cpp -MMD -c" >> "$AR_PLATFORM_TXT" +echo "compiler.c.elf.flags.$IDF_TARGET=$LD_SCRIPTS $LD_FLAGS" >> "$AR_PLATFORM_TXT" +cat 1platform_mid.txt >> "$AR_PLATFORM_TXT" +rm -rf platform_start.txt platform_mid.txt 1platform_mid.txt + +# sdkconfig +cp -f "sdkconfig" "$AR_SDK/sdkconfig" + +# esptool.py +cp "$IDF_COMPS/esptool_py/esptool/esptool.py" "$AR_ESPTOOL_PY" + +# gen_esp32part.py +cp "$IDF_COMPS/partition_table/gen_esp32part.py" "$AR_GEN_PART_PY" + +# copy precompiled libs (if we need them) +function copy_precompiled_lib(){ + lib_file="$1" + lib_name="$(basename $lib_file)" + if [[ $LD_LIBS_SEARCH == *"$lib_name"* ]]; then + cp "$lib_file" "$AR_SDK/ld/" + fi +} + +# idf ld scripts +mkdir -p "$AR_SDK/ld" +set -- $LD_SCRIPT_DIRS +for item; do + item="${item%\"}" + item="${item#\"}" + find "$item" -name '*.ld' -exec cp -f {} "$AR_SDK/ld/" \; + for lib in `find "$item" -name '*.a'`; do + copy_precompiled_lib "$lib" + done +done + +# Handle Mem Variants +mkdir -p "$AR_SDK/$MEMCONF/include" +mv "$PWD/build/config/sdkconfig.h" "$AR_SDK/$MEMCONF/include/sdkconfig.h" +for mem_variant in `jq -c '.mem_variants_files[]' configs/builds.json`; do + skip_file=1 + for file_target in $(echo "$mem_variant" | jq -c '.targets[]' | tr -d '"'); do + if [ "$file_target" == "$IDF_TARGET" ]; then + skip_file=0 + break + fi + done + if [ $skip_file -eq 0 ]; then + file=$(echo "$mem_variant" | jq -c '.file' | tr -d '"') + out=$(echo "$mem_variant" | jq -c '.out' | tr -d '"') + mv "$AR_SDK/$out" "$AR_SDK/$MEMCONF/$file" + fi +done; + +# Add IDF versions to sdkconfig +echo "#define CONFIG_ARDUINO_IDF_COMMIT \"$IDF_COMMIT\"" >> "$AR_SDK/$MEMCONF/include/sdkconfig.h" +echo "#define CONFIG_ARDUINO_IDF_BRANCH \"$IDF_BRANCH\"" >> "$AR_SDK/$MEMCONF/include/sdkconfig.h" diff --git a/tools/copy-mem-variant.sh b/tools/copy-mem-variant.sh new file mode 100755 index 0000000..9b8f3b5 --- /dev/null +++ b/tools/copy-mem-variant.sh @@ -0,0 +1,39 @@ +#!/bin/bash +IDF_TARGET=$1 +OCT_FLASH="$2" +OCT_PSRAM= + +if [ "$3" = "y" ]; then + OCT_PSRAM="opi" +else + OCT_PSRAM="qspi" +fi + +MEMCONF=$OCT_FLASH"_$OCT_PSRAM" + +source ./tools/config.sh + +echo "IDF_TARGET: $IDF_TARGET, MEMCONF: $MEMCONF" + +# Add IDF versions to sdkconfig +echo "#define CONFIG_ARDUINO_IDF_COMMIT \"$IDF_COMMIT\"" >> "build/config/sdkconfig.h" +echo "#define CONFIG_ARDUINO_IDF_BRANCH \"$IDF_BRANCH\"" >> "build/config/sdkconfig.h" + +# Handle Mem Variants +rm -rf "$AR_SDK/$MEMCONF" +mkdir -p "$AR_SDK/$MEMCONF/include" +mv "build/config/sdkconfig.h" "$AR_SDK/$MEMCONF/include/sdkconfig.h" +for mem_variant in `jq -c '.mem_variants_files[]' configs/builds.json`; do + skip_file=1 + for file_target in $(echo "$mem_variant" | jq -c '.targets[]' | tr -d '"'); do + if [ "$file_target" == "$IDF_TARGET" ]; then + skip_file=0 + break + fi + done + if [ $skip_file -eq 0 ]; then + file=$(echo "$mem_variant" | jq -c '.file' | tr -d '"') + src=$(echo "$mem_variant" | jq -c '.src' | tr -d '"') + cp "$src" "$AR_SDK/$MEMCONF/$file" + fi +done; diff --git a/tools/copy-to-arduino.sh b/tools/copy-to-arduino.sh new file mode 100755 index 0000000..ba5b172 --- /dev/null +++ b/tools/copy-to-arduino.sh @@ -0,0 +1,25 @@ +#!/bin/bash +source ./tools/config.sh + +if [ -z $ESP32_ARDUINO ]; then + if [[ "$AR_OS" == "macos" ]]; then + ESP32_ARDUINO="$HOME/Documents/Arduino/hardware/espressif/esp32" + else + ESP32_ARDUINO="$HOME/Arduino/hardware/espressif/esp32" + fi +fi + +if ! [ -d "$ESP32_ARDUINO" ]; then + echo "ERROR: Target arduino folder does not exist!" + exit 1 +fi + +echo "Installing new libraries to $ESP32_ARDUINO" + +rm -rf $ESP32_ARDUINO/tools/sdk $ESP32_ARDUINO/tools/esptool.py $ESP32_ARDUINO/tools/gen_esp32part.py $ESP32_ARDUINO/tools/platformio-build-*.py $ESP32_ARDUINO/platform.txt + +cp -f $AR_OUT/platform.txt $ESP32_ARDUINO/ +cp -Rf $AR_TOOLS/sdk $ESP32_ARDUINO/tools/ +cp -f $AR_TOOLS/esptool.py $ESP32_ARDUINO/tools/ +cp -f $AR_TOOLS/gen_esp32part.py $ESP32_ARDUINO/tools/ +cp -f $AR_TOOLS/platformio-build-*.py $ESP32_ARDUINO/tools/ diff --git a/tools/cron.sh b/tools/cron.sh new file mode 100644 index 0000000..6122b1e --- /dev/null +++ b/tools/cron.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ ! "$GITHUB_EVENT_NAME" == "schedule" ]; then + echo "Wrong event '$GITHUB_EVENT_NAME'!" + exit 1 +fi + +git checkout "$IDF_BRANCH" #local branches should match what the matrix wants to build +source ./build.sh +bash ./tools/push-to-arduino.sh diff --git a/tools/current_commit.sh b/tools/current_commit.sh new file mode 100755 index 0000000..8d890dc --- /dev/null +++ b/tools/current_commit.sh @@ -0,0 +1,2 @@ +IDF_COMMIT=$(wget -q -O- "https://github.com/espressif/arduino-esp32/search?q=update+idf&type=Commits" | grep -i "update idf" | grep -e "to [0-9a-f]*" | sed "s/^.*to \([0-9a-f]*\).*/\1/" | head -1) +echo Current commit is $IDF_COMMIT diff --git a/tools/install-esp-idf.sh b/tools/install-esp-idf.sh new file mode 100755 index 0000000..a67b4eb --- /dev/null +++ b/tools/install-esp-idf.sh @@ -0,0 +1,102 @@ +#/bin/bash + +source ./tools/config.sh + +if ! [ -x "$(command -v $SED)" ]; then + echo "ERROR: $SED is not installed! Please install $SED first." + exit 1 +fi + +# +# CLONE ESP-IDF +# + +IDF_REPO_URL="https://github.com/espressif/esp-idf.git" +if [ ! -d "$IDF_PATH" ]; then + echo "ESP-IDF is not installed! Installing local copy" + git clone $IDF_REPO_URL -b $IDF_BRANCH + idf_was_installed="1" +fi + +if [ "$IDF_COMMIT" ]; then + git -C "$IDF_PATH" checkout "$IDF_COMMIT" + commit_predefined="1" +fi + +# +# UPDATE ESP-IDF TOOLS AND MODULES +# + +if [ ! -x $idf_was_installed ] || [ ! -x $commit_predefined ]; then + git -C $IDF_PATH submodule update --init --recursive + $IDF_PATH/install.sh +fi + +# +# SETUP ESP-IDF ENV +# + +source $IDF_PATH/export.sh +export IDF_COMMIT=$(git -C "$IDF_PATH" rev-parse --short HEAD) +export IDF_BRANCH=$(git -C "$IDF_PATH" symbolic-ref --short HEAD) + +# +# SETUP ARDUINO DEPLOY +# + +if [ "$GITHUB_EVENT_NAME" == "schedule" ] || [ "$GITHUB_EVENT_NAME" == "repository_dispatch" -a "$GITHUB_EVENT_ACTION" == "deploy" ]; then + # format new branch name and pr title + if [ -x $commit_predefined ]; then #commit was not specified at build time + AR_NEW_BRANCH_NAME="idf-$IDF_BRANCH" + AR_NEW_COMMIT_MESSAGE="IDF $IDF_BRANCH $IDF_COMMIT" + AR_NEW_PR_TITLE="IDF $IDF_BRANCH" + else + AR_NEW_BRANCH_NAME="idf-$IDF_COMMIT" + AR_NEW_COMMIT_MESSAGE="IDF $IDF_COMMIT" + AR_NEW_PR_TITLE="$AR_NEW_COMMIT_MESSAGE" + fi + + AR_HAS_COMMIT=`git_commit_exists "$AR_COMPS/arduino" "$AR_NEW_COMMIT_MESSAGE"` + AR_HAS_BRANCH=`git_branch_exists "$AR_COMPS/arduino" "$AR_NEW_BRANCH_NAME"` + AR_HAS_PR=`git_pr_exists "$AR_NEW_BRANCH_NAME"` + + if [ "$AR_HAS_COMMIT" == "1" ]; then + echo "Commit '$AR_NEW_COMMIT_MESSAGE' Already Exists" + mkdir -p dist && echo "Commit '$AR_NEW_COMMIT_MESSAGE' Already Exists" > dist/log.txt + exit 0 + fi + + if [ "$AR_HAS_BRANCH" == "1" ]; then + echo "Branch '$AR_NEW_BRANCH_NAME' Already Exists" + fi + + if [ "$AR_HAS_PR" == "1" ]; then + echo "PR '$AR_NEW_PR_TITLE' Already Exists" + fi + + # setup git for pushing + git config --global github.user "$GITHUB_ACTOR" + git config --global user.name "$GITHUB_ACTOR" + git config --global user.email "$GITHUB_ACTOR@github.com" + + # create or checkout the branch + if [ ! $AR_HAS_BRANCH == "0" ]; then + echo "Switching to arduino branch '$AR_NEW_BRANCH_NAME'..." + git -C "$AR_COMPS/arduino" checkout $AR_NEW_BRANCH_NAME + else + echo "Creating arduino branch '$AR_NEW_BRANCH_NAME'..." + git -C "$AR_COMPS/arduino" checkout -b $AR_NEW_BRANCH_NAME + fi + if [ $? -ne 0 ]; then + echo "ERROR: Checkout of branch '$AR_NEW_BRANCH_NAME' failed" + exit 1 + fi + + export AR_NEW_BRANCH_NAME + export AR_NEW_COMMIT_MESSAGE + export AR_NEW_PR_TITLE + + export AR_HAS_COMMIT + export AR_HAS_BRANCH + export AR_HAS_PR +fi diff --git a/tools/prepare-ci.sh b/tools/prepare-ci.sh new file mode 100755 index 0000000..e39a798 --- /dev/null +++ b/tools/prepare-ci.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +sudo apt-get install -y git wget curl libssl-dev libncurses-dev flex bison gperf python3 cmake ninja-build ccache +curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && python3 get-pip.py && \ +pip3 install setuptools pyserial click future wheel cryptography pyparsing pyelftools diff --git a/tools/push-to-arduino.sh b/tools/push-to-arduino.sh new file mode 100755 index 0000000..f9a2b99 --- /dev/null +++ b/tools/push-to-arduino.sh @@ -0,0 +1,54 @@ +#!/bin/bash +source ./tools/config.sh + +if [ -x $GITHUB_TOKEN ]; then + echo "ERROR: GITHUB_TOKEN was not defined" + exit 1 +fi + +if ! [ -d "$AR_COMPS/arduino" ]; then + echo "ERROR: Target arduino folder does not exist!" + exit 1 +fi + +# +# UPDATE FILES +# + +if [ $AR_HAS_COMMIT == "0" ]; then + # make changes to the files + echo "Patching files in branch '$AR_NEW_BRANCH_NAME'..." + ESP32_ARDUINO="$AR_COMPS/arduino" ./tools/copy-to-arduino.sh + + cd $AR_COMPS/arduino + + # did any of the files change? + if [ -n "$(git status --porcelain)" ]; then + echo "Pushing changes to branch '$AR_NEW_BRANCH_NAME'..." + git add . && git commit --message "$AR_NEW_COMMIT_MESSAGE" && git push -u origin $AR_NEW_BRANCH_NAME + if [ $? -ne 0 ]; then + echo "ERROR: Pushing to branch '$AR_NEW_BRANCH_NAME' failed" + exit 1 + fi + else + echo "No changes in branch '$AR_NEW_BRANCH_NAME'" + if [ $AR_HAS_BRANCH == "0" ]; then + echo "Delete created branch '$AR_NEW_BRANCH_NAME'" + git branch -d $AR_NEW_BRANCH_NAME + fi + exit 0 + fi +fi + +# +# CREATE PULL REQUEST +# + +if [ "$AR_HAS_PR" == "0" ]; then + pr_created=`git_create_pr "$AR_NEW_BRANCH_NAME" "$AR_NEW_PR_TITLE" "$AR_PR_TARGET_BRANCH"` + if [ $pr_created == "0" ]; then + echo "ERROR: Failed to create PR '$AR_NEW_PR_TITLE': "`echo "$git_create_pr_res" | jq -r '.message'`": "`echo "$git_create_pr_res" | jq -r '.errors[].message'` + exit 1 + fi +fi +exit 0 diff --git a/tools/repository_dispatch.sh b/tools/repository_dispatch.sh new file mode 100644 index 0000000..a920f5b --- /dev/null +++ b/tools/repository_dispatch.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +if [ ! "$GITHUB_EVENT_NAME" == "repository_dispatch" ]; then + echo "Wrong event '$GITHUB_EVENT_NAME'!" + exit 1 +fi + +EVENT_JSON=`cat "$GITHUB_EVENT_PATH"` +action=`echo "$EVENT_JSON" | jq -r '.action'` +payload=`echo "$EVENT_JSON" | jq -r '.client_payload'` +branch=`echo "$payload" | jq -r '.branch'` +commit=`echo "$payload" | jq -r '.commit'` +builder=`echo "$payload" | jq -r '.builder'` +arduino=`echo "$payload" | jq -r '.arduino'` + +echo "Action: $action, Branch: $branch, Commit: $commit, Builder: $builder" + +if [ ! "$action" == "deploy" ] && [ ! "$action" == "build" ]; then + echo "Bad Action $action" + exit 1 +fi + +export GITHUB_EVENT_ACTION="$action" + +if [ ! "$commit" == "" ] && [ ! "$commit" == "null" ]; then + export IDF_COMMIT="$commit" +else + commit="" + if [ ! "$branch" == "" ] && [ ! "$branch" == "null" ]; then + export IDF_BRANCH="$branch" + fi +fi + +if [ ! "$builder" == "" ] && [ ! "$builder" == "null" ]; then + git checkout "$builder" +fi + +if [ ! "$arduino" == "" ] && [ ! "$arduino" == "null" ]; then + export AR_BRANCH="$arduino" +fi + +source ./build.sh + +if [ "$action" == "deploy" ]; then + bash ./tools/push-to-arduino.sh +fi diff --git a/tools/update-components.sh b/tools/update-components.sh new file mode 100755 index 0000000..1c33919 --- /dev/null +++ b/tools/update-components.sh @@ -0,0 +1,146 @@ +#/bin/bash + +source ./tools/config.sh + +CAMERA_REPO_URL="https://github.com/espressif/esp32-camera.git" +DL_REPO_URL="https://github.com/espressif/esp-dl.git" +SR_REPO_URL="https://github.com/espressif/esp-sr.git" +RMAKER_REPO_URL="https://github.com/espressif/esp-rainmaker.git" +DSP_REPO_URL="https://github.com/espressif/esp-dsp.git" +LITTLEFS_REPO_URL="https://github.com/joltwallet/esp_littlefs.git" +TINYUSB_REPO_URL="https://github.com/hathach/tinyusb.git" + +# +# CLONE/UPDATE ARDUINO +# + +if [ ! -d "$AR_COMPS/arduino" ]; then + git clone $AR_REPO_URL "$AR_COMPS/arduino" +fi + +if [ -z $AR_BRANCH ]; then + if [ -z $GITHUB_HEAD_REF ]; then + current_branch=`git branch --show-current` + else + current_branch="$GITHUB_HEAD_REF" + fi + echo "Current Branch: $current_branch" + if [[ "$current_branch" != "master" && `git_branch_exists "$AR_COMPS/arduino" "$current_branch"` == "1" ]]; then + export AR_BRANCH="$current_branch" + else + has_ar_branch=`git_branch_exists "$AR_COMPS/arduino" "idf-$IDF_BRANCH"` + if [ "$has_ar_branch" == "1" ]; then + export AR_BRANCH="idf-$IDF_BRANCH" + else + has_ar_branch=`git_branch_exists "$AR_COMPS/arduino" "$AR_PR_TARGET_BRANCH"` + if [ "$has_ar_branch" == "1" ]; then + export AR_BRANCH="$AR_PR_TARGET_BRANCH" + fi + fi + fi +fi + +if [ "$AR_BRANCH" ]; then + git -C "$AR_COMPS/arduino" checkout "$AR_BRANCH" && \ + git -C "$AR_COMPS/arduino" fetch && \ + git -C "$AR_COMPS/arduino" pull --ff-only +fi +if [ $? -ne 0 ]; then exit 1; fi + +# +# CLONE/UPDATE ESP32-CAMERA +# + +if [ ! -d "$AR_COMPS/esp32-camera" ]; then + git clone $CAMERA_REPO_URL "$AR_COMPS/esp32-camera" +else + git -C "$AR_COMPS/esp32-camera" fetch && \ + git -C "$AR_COMPS/esp32-camera" pull --ff-only +fi +#this is a temp measure to fix build issue in recent IDF master +if [ -f "$AR_COMPS/esp32-camera/idf_component.yml" ]; then + rm -rf "$AR_COMPS/esp32-camera/idf_component.yml" +fi +if [ $? -ne 0 ]; then exit 1; fi + +# +# CLONE/UPDATE ESP-DL +# + +if [ ! -d "$AR_COMPS/esp-dl" ]; then + git clone $DL_REPO_URL "$AR_COMPS/esp-dl" +else + git -C "$AR_COMPS/esp-dl" fetch && \ + git -C "$AR_COMPS/esp-dl" pull --ff-only +fi +if [ $? -ne 0 ]; then exit 1; fi + +# +# CLONE/UPDATE ESP-SR +# + +if [ ! -d "$AR_COMPS/esp-sr" ]; then + git clone $SR_REPO_URL "$AR_COMPS/esp-sr" +else + git -C "$AR_COMPS/esp-sr" fetch && \ + git -C "$AR_COMPS/esp-sr" pull --ff-only +fi +if [ $? -ne 0 ]; then exit 1; fi + +# +# CLONE/UPDATE ESP-LITTLEFS +# + +if [ ! -d "$AR_COMPS/esp_littlefs" ]; then + git clone $LITTLEFS_REPO_URL "$AR_COMPS/esp_littlefs" && \ + git -C "$AR_COMPS/esp_littlefs" submodule update --init --recursive +else + git -C "$AR_COMPS/esp_littlefs" fetch && \ + git -C "$AR_COMPS/esp_littlefs" pull --ff-only && \ + git -C "$AR_COMPS/esp_littlefs" submodule update --init --recursive +fi +if [ $? -ne 0 ]; then exit 1; fi + +# +# CLONE/UPDATE ESP-RAINMAKER +# + +if [ ! -d "$AR_COMPS/esp-rainmaker" ]; then + git clone $RMAKER_REPO_URL "$AR_COMPS/esp-rainmaker" && \ + git -C "$AR_COMPS/esp-rainmaker" submodule update --init --recursive + # git -C "$AR_COMPS/esp-rainmaker" checkout f1b82c71c4536ab816d17df016d8afe106bd60e3 +else + git -C "$AR_COMPS/esp-rainmaker" fetch && \ + git -C "$AR_COMPS/esp-rainmaker" pull --ff-only && \ + git -C "$AR_COMPS/esp-rainmaker" submodule update --init --recursive +fi +if [ $? -ne 0 ]; then exit 1; fi + +# +# CLONE/UPDATE ESP-DSP +# + +if [ ! -d "$AR_COMPS/esp-dsp" ]; then + git clone $DSP_REPO_URL "$AR_COMPS/esp-dsp" + # cml=`cat "$AR_COMPS/esp-dsp/CMakeLists.txt"` + # echo "if(IDF_TARGET STREQUAL \"esp32\" OR IDF_TARGET STREQUAL \"esp32s2\" OR IDF_TARGET STREQUAL \"esp32s3\")" > "$AR_COMPS/esp-dsp/CMakeLists.txt" + # echo "$cml" >> "$AR_COMPS/esp-dsp/CMakeLists.txt" + # echo "endif()" >> "$AR_COMPS/esp-dsp/CMakeLists.txt" +else + git -C "$AR_COMPS/esp-dsp" fetch && \ + git -C "$AR_COMPS/esp-dsp" pull --ff-only +fi +if [ $? -ne 0 ]; then exit 1; fi + +# +# CLONE/UPDATE TINYUSB +# + +if [ ! -d "$AR_COMPS/arduino_tinyusb/tinyusb" ]; then + git clone $TINYUSB_REPO_URL "$AR_COMPS/arduino_tinyusb/tinyusb" +else + git -C "$AR_COMPS/arduino_tinyusb/tinyusb" fetch && \ + git -C "$AR_COMPS/arduino_tinyusb/tinyusb" pull --ff-only +fi +if [ $? -ne 0 ]; then exit 1; fi +